aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarc André Tanner <mat@brain-dump.org>2016-09-25 10:57:01 +0200
committerMarc André Tanner <mat@brain-dump.org>2016-09-25 11:53:12 +0200
commitc3bbd835fca0ba184f191b270d9aebfc2466be82 (patch)
tree956502573e1e83d7bf39ec04c11cb8c1131a413c
parentd3798ba58d3f8ebef9a024c8d538d7bebb0b6931 (diff)
downloadvis-c3bbd835fca0ba184f191b270d9aebfc2466be82.tar.gz
vis-c3bbd835fca0ba184f191b270d9aebfc2466be82.tar.xz
vis: move file name and word completion logic to a shell script
The shell script should be reviewed for quoting issues, currently it allows command injections as in: $ vis-complete "'; rm -f some-file; echo " However it is intended for interactive usage and from within vis it is only ever called with a valid completion prefix. The file name completion logic now supports nested directories. Close #347
-rw-r--r--Makefile2
-rw-r--r--main.c6
-rwxr-xr-xvis-complete35
-rw-r--r--vis.h3
4 files changed, 42 insertions, 4 deletions
diff --git a/Makefile b/Makefile
index 9b241c8..ee85e9a 100644
--- a/Makefile
+++ b/Makefile
@@ -87,6 +87,8 @@ install: vis vis-menu
@chmod 755 ${DESTDIR}${PREFIX}/bin/vis-open
@cp -f vis-clipboard ${DESTDIR}${PREFIX}/bin
@chmod 755 ${DESTDIR}${PREFIX}/bin/vis-clipboard
+ @cp -f vis-complete ${DESTDIR}${PREFIX}/bin
+ @chmod 755 ${DESTDIR}${PREFIX}/bin/vis-complete
@test ${CONFIG_LUA} -eq 0 || { \
echo installing support files to ${DESTDIR}${SHAREPREFIX}/vis; \
mkdir -p ${DESTDIR}${SHAREPREFIX}/vis; \
diff --git a/main.c b/main.c
index 485478e..b0b932d 100644
--- a/main.c
+++ b/main.c
@@ -2131,8 +2131,7 @@ static const char *complete_word(Vis *vis, const char *keys, const Arg *arg) {
Buffer cmd;
buffer_init(&cmd);
char *prefix = get_completion_prefix(vis);
- if (prefix && buffer_printf(&cmd, "tr -cs '[:alnum:]_' '\n' | grep '^%s.' | sort -u | "
- VIS_MENU " -b | sed 's/^%s//' | tr -d '\n'", prefix, prefix)) {
+ if (prefix && buffer_printf(&cmd, VIS_COMPLETE " --word '%s'", prefix)) {
Filerange all = text_range_new(0, text_size(txt));
insert_dialog_selection(vis, &all, (const char*[]){ buffer_content0(&cmd), NULL });
}
@@ -2145,8 +2144,7 @@ static const char *complete_filename(Vis *vis, const char *keys, const Arg *arg)
Buffer cmd;
buffer_init(&cmd);
char *prefix = get_completion_prefix(vis);
- if (prefix && buffer_printf(&cmd, "ls -1 | grep '^%s.' | sort | "
- VIS_MENU " -b | sed 's/^%s//' | tr -d '\n'", prefix, prefix)) {
+ if (prefix && buffer_printf(&cmd, VIS_COMPLETE " --file '%s'", prefix)) {
Filerange empty = text_range_new(0, 0);
insert_dialog_selection(vis, &empty, (const char*[]){ buffer_content0(&cmd), NULL });
}
diff --git a/vis-complete b/vis-complete
new file mode 100755
index 0000000..29dc457
--- /dev/null
+++ b/vis-complete
@@ -0,0 +1,35 @@
+#!/bin/sh
+set -e
+
+PATTERN=""
+COMPLETE_WORD=0
+
+while [ $# -gt 0 ]; do
+ case "$1" in
+ -h|--help)
+ echo "usage: $(basename "$0") [-h] [--file|--word] [pattern]"
+ exit 0;
+ ;;
+ --file)
+ shift
+ ;;
+ --word)
+ COMPLETE_WORD=1
+ shift
+ ;;
+ *)
+ PATTERN="$1"
+ break
+ ;;
+ esac
+done
+
+if [ $COMPLETE_WORD = 1 ]; then
+ CMD=$(printf "tr -cs '[:alnum:]_' '\n' | grep '^%s.' | sort -u" "$PATTERN")
+else
+ CMD=$(printf "find . ! -path '*/\.*' -a -path './%s*' | cut -b 3- | sort" "$PATTERN")
+fi
+
+CMD=$(printf "$CMD | vis-menu -b | sed 's/^%s//' | tr -d '\n'" "$PATTERN")
+
+exec /bin/sh -c "$CMD"
diff --git a/vis.h b/vis.h
index 91f9868..a9ffb90 100644
--- a/vis.h
+++ b/vis.h
@@ -23,6 +23,9 @@ typedef struct Win Win;
#ifndef VIS_CLIPBOARD
#define VIS_CLIPBOARD "vis-clipboard"
#endif
+#ifndef VIS_COMPLETE
+#define VIS_COMPLETE "vis-complete"
+#endif
typedef struct {
void (*vis_init)(Vis*);