-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathshell-cmd-comp.sh
More file actions
executable file
·158 lines (122 loc) · 3.23 KB
/
shell-cmd-comp.sh
File metadata and controls
executable file
·158 lines (122 loc) · 3.23 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
#!/bin/bash
# Author: Siyuan Liu
# E-mail: siyuanl96@gmail.com
export SHELL_CMD_COMP_DIR="/home/`whoami`/.shellCmdComp.d/"
# For debug
# SHELL_CMD_COMP_DIR=".shellCmdComp.d/"
if [ ! -d "${SHELL_CMD_COMP_DIR}" ]; then
mkdir ${SHELL_CMD_COMP_DIR}
fi
function _shell_cmd_complete_push_stack() {
local line=`expr $1 + 1`
local indent=$2
local stack=""
local mark=""
local cmd_tree=$3
mark=`sed -n ''$line',+0p' $cmd_tree | sed 's/[ \t]//g'`
line=`expr $line + 1`
if [ "$mark" == "&" ]; then
stack=`sed -n ''${line}',/^'${indent%??}'\S/p' $cmd_tree | sed -n '/^'${indent}'\S/p'`
echo $stack
fi
}
function _shell_cmd_complete_cmd_end() {
local cmd_tree=$1
local line=$2
local indent=$3
local opts=""
opts=`sed -n ''${line}',/^'${indent%??}'\S/p' $cmd_tree | sed -n '/^'${indent}'\S/p' | sed -n '/[^&@$]$/p'`
if [ "$opts" == "" ]; then
echo 1
fi
}
function _shell_cmd_complete() {
COMPREPLY=()
local cur=${COMP_WORDS[COMP_CWORD]}
local cmd=${COMP_WORDS[0]}
# The first line is reserved.
local line=1
local indent="\t"
local cmd_tree="${SHELL_CMD_COMP_DIR}${cmd}.comp"
local match=""
local stack=()
local stack_line=()
local arr=()
local opts=""
local level=0
local push=1
local same=0
# process sub-command
for i in $(seq 2 $COMP_CWORD)
do
if [ $push -eq 1 ]; then
level=`expr $level + 1`
stack_line[$level]=$line
stack[level]=$(_shell_cmd_complete_push_stack $line $indent $cmd_tree)
else
indent=${indent%??}
# Find the level to which the previous cmd belongs.
local cmd_level=$level
while [ $cmd_level -gt 0 ]
do
if [ "${stack[cmd_level]}" != "" ]; then
match="${COMP_WORDS[i-1]//\//\\/}"
local belong=`echo ${stack[cmd_level]} | sed -n '/'${COMP_WORDS[i-1]}'/p'`
if [ "$belong" != "" ]; then
break
fi
fi
cmd_level=`expr $cmd_level - 1`
indent=${indent%??}
done
# echo "cmd_level:$cmd_level, level:$level"
if [ "$cmd_level" != "$level" ]; then
level=$cmd_level
while [[ "${stack[level]}" == " " ]]
do
if [ $level -lt 1 ]; then
break
fi
level=`expr $level - 1`
indent=${indent%??}
done
fi
line=${stack_line[level]}
fi
match="${COMP_WORDS[i-1]//\//\\/}"
stack[level]=`echo ${stack[level]} | sed 's/'${match}'/ /'`
# echo "stack[$level]B: ${stack_line[level]} ${stack[level]} :E"
match="${indent}${match}"
# echo "line:$line match:$match"
line=`sed -n ''${line}',/'${match}'/=' $cmd_tree`
arr=($line)
line=${arr[-1]}
local end=$(_shell_cmd_complete_cmd_end $cmd_tree $line "${indent}\t")
if [ "$end" == "1" ]; then
# echo "POP stack"
push=0
else
push=1
fi
indent="${indent}\t"
done
# echo "Search from line:$line indent:$indent"
opts=`sed -n ''${line}',/^'${indent%??}'\S/p' $cmd_tree | sed -n '/^'${indent}'\S/p' | sed -n '/[^&@$]$/p'`
if [ "$opts" == "" ]; then
# Return to the level where sub-commands can be appended
for j in $(seq 0 $level)
do
# echo "Back stack[`expr $level - $j`]:${stack[level-j]}"
if [ "${stack[level-j]}" != "" ]; then
opts="${opts}${stack[level-j]}"
fi
done
fi
# '*' means it supports any input parameters.
if [[ "${opts}" =~ "*" ]]; then
_filedir
else
COMPREPLY=( $(compgen -W '$opts' -- $cur) )
fi
return 0
}