Add bash autocompletion support

This commit is contained in:
pancake 2016-10-04 14:34:06 +02:00
parent f3176a1174
commit 41d6e9edde
10 changed files with 297 additions and 47 deletions

View File

@ -652,7 +652,11 @@ int main(int argc, char **argv) {
case 'v': return blob_version ("rabin2");
case 'L':
bin->cb_printf = (PrintfCallback)printf;
r_bin_list (bin, rad == R_CORE_BIN_JSON);
if (rad) {
r_bin_list (bin, 'q');
} else {
r_bin_list (bin, rad == R_CORE_BIN_JSON);
}
return 1;
case 'G':
laddr = r_num_math (NULL, optarg);
@ -926,7 +930,11 @@ int main(int argc, char **argv) {
// List fatmach0 sub-binaries, etc
if (action & R_BIN_REQ_LISTARCHS || ((arch || bits || arch_name) &&
!r_bin_select (bin, arch, bits, arch_name))) {
r_bin_list_archs (bin, (rad == R_CORE_BIN_JSON)? 'j': 1);
if (rad == R_CORE_BIN_SIMPLEST || rad == R_CORE_BIN_SIMPLE) {
r_bin_list_archs (bin, 'q');
} else {
r_bin_list_archs (bin, (rad == R_CORE_BIN_JSON)? 'j': 1);
}
actions_done++;
free (arch_name);
}

View File

@ -468,10 +468,19 @@ int main(int argc, char **argv, char **envp) {
case 'D':
debug = 2;
debugbackend = optarg;
if (!strcmp (optarg, "?")) {
r_debug_plugin_list (r.dbg, 'q');
r_cons_flush();
return 0;
}
break;
case 'e':
r_config_eval (r.config, optarg);
r_list_append (evals, optarg);
if (!strcmp (optarg, "q")) {
r_core_cmd0 (&r, "eq");
} else {
r_config_eval (r.config, optarg);
r_list_append (evals, optarg);
}
break;
case 'f': fullfile = 1; break;
case 'F': forcebin = optarg; break;
@ -509,7 +518,13 @@ int main(int argc, char **argv, char **envp) {
case 'n': run_anal--; break;
case 'N': run_rc = 0; break;
case 'p':
r_config_set (r.config, "file.project", optarg);
if (!strcmp (optarg, "?")) {
r_core_project_list (&r, 0);
r_cons_flush ();
return 0;
} else {
r_config_set (r.config, "file.project", optarg);
}
break;
case 'P':
patchfile = optarg;

187
doc/bash_autocompletion.sh Normal file
View File

@ -0,0 +1,187 @@
#!/bin/bash
_r2 () {
local cur
COMPREPLY=()
cur=${COMP_WORDS[COMP_CWORD]}
prv=${COMP_WORDS[COMP_CWORD-1]}
case "$prv" in
-a)
COMPREPLY=( $(compgen -W "$(rasm2 -qL)" -- $cur))
return 0
;;
-b)
COMPREPLY=( $(compgen -W "8 16 32 64" -- $cur ))
return 0
;;
-o)
COMPREPLY=( $(compgen -W "$(r2 -qc 'e asm.os=?' --)" -- $cur ))
return 0
;;
-e)
COMPREPLY=( $(compgen -W "$(r2 -qceq --)" -- $cur ))
return 0
;;
-F)
COMPREPLY=( $(compgen -W "$(rabin2 -qL)" -- $cur ))
return 0
;;
-H)
COMPREPLY=( $(compgen -W "$(r2 -H |cut -d = -f 1)" -- $cur))
return 0
;;
-p)
COMPREPLY=( $(compgen -W "$(r2 -p?)" -- $cur ))
return 0
;;
-D)
COMPREPLY=( $(compgen -W "$(r2 -D?)" -- $cur ))
return 0
;;
esac
case "$cur" in
-*)
COMPREPLY=( $( compgen -W '-0 -a -A -b -B -c -C -d -D -e -f -F -h -hh -H -i -I -k -l -L -m -M -n -nn -N -o -q -p -P -R -s -S -t -u -v -V -w -z -zz' -- $cur))
;;
*)
COMPREPLY=( $(compgen -f -- $cur))
;;
esac
return 0
}
complete -F _r2 -o filenames r2
complete -F _r2 -o filenames radare2
_rasm2 () {
local cur
COMPREPLY=()
cur=${COMP_WORDS[COMP_CWORD]}
prv=${COMP_WORDS[COMP_CWORD-1]}
case "$prv" in
-a)
COMPREPLY=( $(compgen -W "$(rasm2 -qL)" -- $cur))
return 0
;;
-b)
COMPREPLY=( $(compgen -W "8 16 32 64" -- $cur ))
return 0
;;
-c)
# TODO. grab -a and get asm.cpu=? output
return 0
;;
-k)
COMPREPLY=( $(compgen -W "$(r2 -qc 'e asm.os=?' --)" -- $cur ))
return 0
;;
-s)
COMPREPLY=( $(compgen -W "$(r2 -qc 'e asm.syntax=?' --)" -- $cur ))
return 0
;;
esac
case "$cur" in
-*)
COMPREPLY=( $( compgen -W '-a -A -b -c -C -d -D -e -E -f -F -h -i -k-l -L -o -O -s -B -v -w -q' -- $cur))
;;
*)
COMPREPLY=( $(compgen -f -- $cur))
;;
esac
return 0
}
complete -F _rasm2 -o filenames rasm2
_rabin2 () {
local cur
COMPREPLY=()
cur=${COMP_WORDS[COMP_CWORD]}
prv=${COMP_WORDS[COMP_CWORD-1]}
case "$prv" in
-a)
COMPREPLY=( $(compgen -W "$(rasm2 -qL)" -- $cur))
return 0
;;
-b)
COMPREPLY=( $(compgen -W "8 16 32 64" -- $cur ))
return 0
;;
-c)
# TODO. grab -a and get asm.cpu=? output
return 0
;;
-k)
COMPREPLY=( $(compgen -W "$(r2 -qc 'e asm.os=?' --)" -- $cur ))
return 0
;;
-s)
COMPREPLY=( $(compgen -W "$(r2 -qc 'e asm.syntax=?' --)" -- $cur ))
return 0
;;
esac
case "$cur" in
-*)
COMPREPLY=( $( compgen -W '-a -A -b -c -C -d -D -e -E -f -F -h -i -k-l -L -o -O -s -B -v -w -q' -- $cur))
;;
*)
COMPREPLY=( $(compgen -f -- $cur))
;;
esac
return 0
}
complete -F _rabin2 -o filenames rabin2
_rafind2 () {
local cur
COMPREPLY=()
cur=${COMP_WORDS[COMP_CWORD]}
case "$cur" in
-*)
COMPREPLY=( $( compgen -W '-a -b -e -f -h -m -M -n -r -s -S -t -v -x -X -z -Z' -- $cur))
;;
*)
COMPREPLY=( $(compgen -f -- $cur))
;;
esac
return 0
}
complete -F _rafind2 -o filenames rafind2
_radiff2() {
local cur
COMPREPLY=()
cur=${COMP_WORDS[COMP_CWORD]}
prv=${COMP_WORDS[COMP_CWORD-1]}
case "$prv" in
-a)
COMPREPLY=( $(compgen -W "$(rasm2 -qL)" -- $cur))
return 0
;;
-b)
COMPREPLY=( $(compgen -W "8 16 32 64" -- $cur ))
return 0
;;
esac
case "$cur" in
-*)
COMPREPLY=( $( compgen -W '-a -A -AA -AAA -b -c -C -d -D -g -j -n -O -p -r -s -ss -S -t -x -v -V' -- $cur))
;;
*)
COMPREPLY=( $(compgen -f -- $cur))
;;
esac
return 0
}
complete -F _radiff2 -o filenames radiff2

View File

@ -1367,7 +1367,14 @@ R_API int r_bin_list(RBin *bin, int json) {
RListIter *it;
RBinXtrPlugin *bp;
RBinXtrPlugin *bx;
if (json) {
if (json == 'q') {
r_list_foreach (bin->plugins, it, bp) {
bin->cb_printf ("%s\n", bp->name);
}
r_list_foreach (bin->binxtrs, it, bx) {
bin->cb_printf ("%s\n", bx->name);
}
} else if (json) {
bin->cb_printf ("{\"bin\":[");
r_list_foreach (bin->plugins, it, bp) {
bin->cb_printf ("{\"filetype\":\"%s\",\"name\":\"%s\",\"license\":\"%s\"}",
@ -1848,13 +1855,19 @@ static void list_xtr_archs(RBin *bin, int mode) {
arch = xtr_data->metadata->arch;
machine = xtr_data->metadata->machine;
bits = xtr_data->metadata->bits;
if (mode == 'j') {
switch (mode) {
case 'q':
bin->cb_printf ("%s\n", arch);
break;
case 'j':
bin->cb_printf ("%s{\"arch\":\"%s\",\"bits\":%d,"
"\"offset\":%" PFMT64d ",\"size\":\"%" PFMT64d ",\"machine\":\"%s\"}",
i++? ",": "", arch, bits, xtr_data->offset, xtr_data->size, machine);
} else {
break;
default:
bin->cb_printf ("%03i 0x%08" PFMT64x " %"PFMT64d" %s_%i %s\n", i++,
xtr_data->offset, xtr_data->size, arch, bits, machine);
break;
}
}
}
@ -1908,16 +1921,18 @@ R_API void r_bin_list_archs(RBin *bin, int mode) {
}
if (info && narch > 1) {
if (mode) {
if (mode == 'j') {
bin->cb_printf ("%s{\"arch\":\"%s\",\"bits\":%d,"
"\"offset\":%" PFMT64d ",\"machine\":\"%s\"}",
i? ",": "", arch, bits,
boffset, machine);
} else {
bin->cb_printf ("%03i 0x%08" PFMT64x " %d %s_%i %s\n", i,
boffset, obj_size, arch, bits, machine);
}
switch (mode) {
case 'q':
bin->cb_printf ("%s\n", arch);
break;
case 'j':
bin->cb_printf ("%s{\"arch\":\"%s\",\"bits\":%d,"
"\"offset\":%" PFMT64d ",\"machine\":\"%s\"}",
i? ",": "", arch, bits,
boffset, machine);
default:
bin->cb_printf ("%03i 0x%08" PFMT64x " %d %s_%i %s\n", i,
boffset, obj_size, arch, bits, machine);
}
snprintf (archline, sizeof (archline) - 1,
"0x%08" PFMT64x ":%d:%s:%d:%s",
@ -1926,31 +1941,37 @@ R_API void r_bin_list_archs(RBin *bin, int mode) {
//sdb_array_push (binfile_sdb, ARCHS_KEY, archline, 0);
} else {
if (info) {
if (mode) {
if (mode == 'j') {
bin->cb_printf ("%s{\"arch\":\"%s\",\"bits\":%d,"
"\"offset\":%" PFMT64d "}",
i? ",": "", arch, bits,
boffset);
} else {
bin->cb_printf ("%03i 0x%08" PFMT64x " %d %s_%d\n", i,
boffset, obj_size, arch, bits);
}
switch (mode) {
case 'q':
bin->cb_printf ("%s\n", arch);
break;
case 'j':
bin->cb_printf ("%s{\"arch\":\"%s\",\"bits\":%d,"
"\"offset\":%" PFMT64d "}",
i? ",": "", arch, bits,
boffset);
break;
default:
bin->cb_printf ("%03i 0x%08" PFMT64x " %d %s_%d\n", i,
boffset, obj_size, arch, bits);
}
snprintf (archline, sizeof (archline),
"0x%08" PFMT64x ":%d:%s:%d",
boffset, obj_size, arch, bits);
} else if (nbinfile && mode) {
if (mode) {
if (mode == 'j') {
bin->cb_printf ("%s{\"arch\":\"unk_%d\",\"bits\":%d,"
"\"offset\":%" PFMT64d ",\"size\":%d}",
i? ",": "", i, bits,
boffset, obj_size);
} else {
bin->cb_printf ("%03i 0x%08" PFMT64x " %d unk_0\n", i,
boffset, obj_size);
}
switch (mode) {
case 'q':
bin->cb_printf ("%s\n", arch);
break;
case 'j':
bin->cb_printf ("%s{\"arch\":\"unk_%d\",\"bits\":%d,"
"\"offset\":%" PFMT64d ",\"size\":%d}",
i? ",": "", i, bits,
boffset, obj_size);
break;
default:
bin->cb_printf ("%03i 0x%08" PFMT64x " %d unk_0\n", i,
boffset, obj_size);
}
snprintf (archline, sizeof (archline),
"0x%08" PFMT64x ":%d:%s:%d",

View File

@ -69,6 +69,11 @@ R_API void r_config_list(RConfig *cfg, const char *str, int rad) {
node->desc? node->desc: "");
}
break;
case 'q':
r_list_foreach (cfg->nodes, iter, node) {
cfg->cb_printf ("%s\n", node->name);
}
break;
case 'j':
cfg->cb_printf ("{");
r_list_foreach (cfg->nodes, iter, node) {

View File

@ -3207,12 +3207,16 @@ static int cmd_debug(void *data, const char *input) {
cmd_debug_pid (core, input);
break;
case 'h': // "dh"
if (input[1]==' ') {
if (input[1]=='q') {
r_debug_plugin_list (core->dbg, 'q');
} else if (input[1]==' ') {
char *str = r_str_chop (strdup (input + 2));
r_config_set (core->config, "dbg.backend", str);
// implicit by config.set r_debug_use (core->dbg, str);
free (str);
} else r_debug_plugin_list (core->dbg);
} else {
r_debug_plugin_list (core->dbg, 0);
}
break;
case 'i':
{

View File

@ -179,9 +179,12 @@ static int cmd_eval(void *data, const char *input) {
case 'x': // exit
// XXX we need headers for the cmd_xxx files.
return cmd_quit (data, "");
case 'j':
case 'j': // json
r_config_list (core->config, NULL, 'j');
break;
case 'q': // quiet list of eval keys
r_config_list (core->config, NULL, 'q');
break;
case '\0': // "e"
r_config_list (core->config, NULL, 0);
break;

View File

@ -822,7 +822,10 @@ static int cb_dbgstatus(void *user, void *data) {
static int cb_dbgbackend(void *user, void *data) {
RCore *core = (RCore*) user;
RConfigNode *node = (RConfigNode*) data;
// XXX: remove this spagetti
if (!strcmp (node->value, "?")) {
r_debug_plugin_list (core->dbg, 'q');
return false;
}
if (!strcmp (node->value, "bf")) {
r_config_set (core->config, "asm.arch", "bf");
}

View File

@ -51,7 +51,7 @@ R_API bool r_debug_use(RDebug *dbg, const char *str) {
return (dbg->h != NULL);
}
R_API int r_debug_plugin_list(RDebug *dbg) {
R_API int r_debug_plugin_list(RDebug *dbg, int mode) {
char spaces[16];
int count = 0;
struct list_head *pos;
@ -61,9 +61,13 @@ R_API int r_debug_plugin_list(RDebug *dbg) {
RDebugPlugin *h = list_entry(pos, RDebugPlugin, list);
int sp = 8-strlen (h->name);
spaces[sp] = 0;
dbg->cb_printf ("%d %s %s %s%s\n",
count, (h == dbg->h)? "dbg": "---",
h->name, spaces, h->license);
if (mode == 'q') {
dbg->cb_printf ("%s\n", h->name);
} else {
dbg->cb_printf ("%d %s %s %s%s\n",
count, (h == dbg->h)? "dbg": "---",
h->name, spaces, h->license);
}
spaces[sp] = ' ';
count++;
}

View File

@ -397,7 +397,7 @@ R_API int r_debug_kill_setup(RDebug *dbg, int sig, int action);
/* handle.c */
R_API void r_debug_plugin_init(RDebug *dbg);
R_API int r_debug_plugin_set(RDebug *dbg, const char *str);
R_API int r_debug_plugin_list(RDebug *dbg);
R_API int r_debug_plugin_list(RDebug *dbg, int mode);
R_API bool r_debug_plugin_add(RDebug *dbg, RDebugPlugin *foo);
/* memory */