0
0
mirror of https://gitlab.nic.cz/labs/bird.git synced 2024-12-23 02:01:55 +00:00

Bash completion for Bird client and daemon.

This commit is contained in:
Jan Moskyto Matejka 2017-05-17 17:15:42 +02:00
parent d19617f06b
commit 5b8eb44c14
6 changed files with 228 additions and 27 deletions

54
bird-complete.bash Normal file
View File

@ -0,0 +1,54 @@
#!/bin/bash
function _bird_complete {
CMD=$1
NOW=$2
PREV=$3
case $PREV in
-c|-D|-P|-s)
COMPREPLY=( $(compgen -f -- $NOW) )
;;
-g)
COMPREPLY=( $(compgen -g -- $NOW) )
;;
-u)
COMPREPLY=( $(compgen -u -- $NOW) )
;;
*)
COMPREPLY=( $(compgen -W '-c -d -D -f -g -h -l -p -P -R -s -u --help --version' -- $NOW) )
;;
esac
}
function _birdc_complete {
CMD=$1
NOW=$2
PREV=$3
echo "bagr" >>xxb
case $PREV in
-*([lvr])s)
COMPREPLY=( $(compgen -W "$(find -maxdepth 1 -type s)" -- $NOW) )
return
;;
esac
case $NOW in
-*([lvr])s)
COMPREPLY=( $(compgen -W "$(find -maxdepth 1 -type s | sed 's#^#'$NOW'#') ${NOW}l ${NOW}r ${NOW}v" -- $NOW) )
return
;;
-*)
COMPREPLY=( $(compgen -W "${NOW}l ${NOW}v ${NOW}r ${NOW}s") )
return
;;
esac
COMPREPLY=( $($CMD -C "$NOW" "$COMP_TYPE" "$COMP_CWORD" "$COMP_POINT" "${COMP_WORDS[@]}") )
}
complete -F _bird_complete bird
complete -F _birdc_complete birdc
complete -F _birdc_complete birdcl

View File

@ -1,4 +1,4 @@
src := commands.c util.c client.c
src := commands.c util.c client.c complete.c
obj := $(src-o-files)
$(all-client)

View File

@ -49,6 +49,7 @@ static byte *server_read_pos = server_read_buf;
int init = 1; /* During intial sequence */
int busy = 1; /* Executing BIRD command */
int interactive; /* Whether stdin is terminal */
int complete = 0;
static int num_lines, skip_input;
int term_lns, term_cls;
@ -69,6 +70,13 @@ parse_args(int argc, char **argv)
int server_changed = 0;
int c;
if ((argc > 1) && !strcmp(argv[1], "-C")) {
complete_init(argc-2, argv+2);
argv += 6;
argc -= 6;
complete = 1;
}
while ((c = getopt(argc, argv, opt_list)) >= 0)
switch (c)
{
@ -87,6 +95,8 @@ parse_args(int argc, char **argv)
server_path = xbasename(server_path);
break;
default:
if (complete)
exit(0);
usage(argv[0]);
}
@ -442,6 +452,10 @@ main(int argc, char **argv)
interactive = isatty(0);
parse_args(argc, argv);
cmd_build_tree();
if (complete)
return do_complete(init_cmd);
server_connect();
select_loop();
return 0;

View File

@ -6,8 +6,7 @@
* Can be freely distributed and used under the terms of the GNU GPL.
*/
extern int init, busy, interactive;
extern int init, busy, interactive, complete;
extern int term_lns, term_cls;
/* birdc.c / birdcl.c */
@ -24,16 +23,21 @@ void more_end(void);
void cleanup(void);
/* commands.c */
void cmd_build_tree(void);
void cmd_help(char *cmd, int len);
int cmd_complete(char *cmd, int len, char *buf, int again);
char *cmd_expand(char *cmd);
/* client.c */
void submit_command(char *cmd_raw);
/* commands.c */
void cmd_build_tree(void);
void cmd_help(const char *cmd, int len);
int cmd_complete(const char *cmd, int len, char *buf, int again);
char *cmd_expand(char *cmd);
/* complete.c */
void complete_init(int argc, char **argv);
int do_complete(char *cmd);
/* die() with system error messages */
#define DIE(x, y...) die(x ": %s", ##y, strerror(errno))

View File

@ -100,7 +100,7 @@ cmd_display_help(struct cmd_info *c1, struct cmd_info *c2)
}
static struct cmd_node *
cmd_find_abbrev(struct cmd_node *root, char *cmd, int len, int *pambiguous)
cmd_find_abbrev(struct cmd_node *root, const char *cmd, int len, int *pambiguous)
{
struct cmd_node *m, *best = NULL, *best2 = NULL;
@ -127,21 +127,24 @@ cmd_find_abbrev(struct cmd_node *root, char *cmd, int len, int *pambiguous)
}
static void
cmd_list_ambiguous(struct cmd_node *root, char *cmd, int len)
cmd_list_ambiguous(struct cmd_node *root, const char *cmd, int len)
{
struct cmd_node *m;
for(m=root->son; m; m=m->sibling)
if (m->len > len && !memcmp(m->token, cmd, len))
cmd_display_help(m->help, m->cmd);
if (m->len > len && !memcmp(m->token, cmd, len))
if (complete)
printf("%s\n", m->token);
else
cmd_display_help(m->help, m->cmd);
}
void
cmd_help(char *cmd, int len)
cmd_help(const char *cmd, int len)
{
char *end = cmd + len;
const char *end = cmd + len;
struct cmd_node *n, *m;
char *z;
const char *z;
int ambig;
n = &cmd_root;
@ -171,7 +174,7 @@ cmd_help(char *cmd, int len)
}
static int
cmd_find_common_match(struct cmd_node *root, char *cmd, int len, int *pcount, char *buf)
cmd_find_common_match(struct cmd_node *root, const char *cmd, int len, int *pcount, char *buf)
{
struct cmd_node *m;
int best, best_prio, i;
@ -212,13 +215,13 @@ cmd_find_common_match(struct cmd_node *root, char *cmd, int len, int *pcount, ch
}
int
cmd_complete(char *cmd, int len, char *buf, int again)
cmd_complete(const char *cmd, int len, char *buf, int again)
{
char *start = cmd;
char *end = cmd + len;
char *fin;
const char *start = cmd;
const char *end = cmd + len;
const char *fin;
struct cmd_node *n, *m;
char *z;
const char *z;
int ambig, cnt = 0, common;
/* Find the last word we want to complete */
@ -242,9 +245,11 @@ cmd_complete(char *cmd, int len, char *buf, int again)
{
if (!again)
return -1;
input_start_list();
if (!complete)
input_start_list();
cmd_list_ambiguous(n, z, cmd-z);
input_stop_list();
if (!complete)
input_stop_list();
return 0;
}
if (!m)
@ -273,9 +278,11 @@ cmd_complete(char *cmd, int len, char *buf, int again)
}
if (!again)
return -1;
input_start_list();
if (!complete)
input_start_list();
cmd_list_ambiguous(n, fin, end-fin);
input_stop_list();
if (!complete)
input_stop_list();
return 0;
}

122
client/complete.c Normal file
View File

@ -0,0 +1,122 @@
/*
* BIRD Client Bash Expansion
*
* (c) 2017 Jan Moskyto Matejka <mq@jmq.cz>
*
* Can be freely distributed and used under the terms of the GNU GPL.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "nest/bird.h"
#include "client/client.h"
static const char *c_now;
static int comp_type, comp_cword, comp_point;
void complete_init(int argc, char **argv) {
/* In argv, there are:
* $NOW
* $COMP_TYPE
* $COMP_CWORD
* $COMP_POINT
* ${COMP_WORDS[@]}
*/
c_now = argv[0];
if (argc < 4)
die("Not enough args.");
if (sscanf(argv[1], "%d", &comp_type) != 1)
die("Strange COMP_TYPE=\"%s\".", argv[1]);
if (sscanf(argv[2], "%d", &comp_cword) != 1)
die("Strange COMP_CWORD=\"%s\".", argv[2]);
if (sscanf(argv[3], "%d", &comp_point) != 1)
die("Strange COMP_POINT=\"%s\".", argv[3]);
return;
}
int do_complete(char *cmd) {
if ((*cmd == 0) && (comp_type == 63))
printf("-s\n-l\n-v\n-r\n");
char buf[256];
int res = cmd_complete(cmd, strlen(cmd), buf, (comp_type == 63));
if (res == 1)
printf("%s%s\n", c_now, buf);
return 0;
}
#if 0
/* Environment and input check */
if (!comp_line || !index(comp_line, ' '))
die("Environment variable COMP_LINE not found.");
/* Drop the command name */
comp_line = index(comp_line, ' ') + 1;
/* StrTok copy */
char *clt = strdup(comp_line);
char *tok = strtok(clt, " ");
do {
if (!tok)
break;
if (!tok[0])
goto next;
if (want_socket) {
opt_s = tok;
goto next;
}
if (tok[0] == '-')
switch(tok[1]) {
case 's':
if (tok[2])
opt_s = tok+2;
else
want_socket = 1;
goto next;
case 'v':
opt_v++;
goto next;
case 'r':
opt_r++;
goto next;
case 'l':
opt_l++;
goto next;
default:
return 0;
}
next:
tok = strtok(NULL, " ");
} while (tok);
fprintf(stderr, "KEY \"%s\"\nLINE \"%s\"\nPOINT \"%s\"\nTYPE \"%s\"\n",
comp_key, comp_line, comp_point, comp_type);
char buf[256];
int result = cmd_complete(comp_line, atoi(comp_point), buf, 0);
if (result < 0)
return 0;
puts(buf);
return 0;
}
#endif