wimenu-file-completion.sh (2855B)
1 #!/bin/sh 2 # This script will launch wimenu and provide command 3 # completion for the first argument and filename completion 4 # for each following argument, and execute the result. 5 # Program name completion requires that a program list already 6 # exist in $(wmiir namespace)/.proglist 7 8 fifo="$HOME/.wmii/menu_fifo" 9 mkfifo $fifo 2>/dev/null 10 11 script=$(cat <<'!' 12 BEGIN { 13 progs = "cat $(wmiir namespace)/.proglist" 14 15 # Print the first set of completions to wimenu’s fifo 16 print read(progs) >fifo 17 fflush(fifo) 18 } 19 20 # Process the input and provide the completions 21 { 22 # Skip the trailing part of the command. 23 # If there is none, this is the result. 24 if (!getline rest) { 25 print 26 exit 27 } 28 29 if (!match($0, /.*[ \t]/)) 30 # First argument, provide the program list 31 update(0, progs) 32 else { 33 # Set the offset to the location of the last 34 # space, and save that part of the completion 35 offset = RLENGTH 36 str = substr($0, offset + 1) 37 38 # If we're completing a sub-directory, adjust 39 # the offset to the position of the last / 40 if (match(str, ".*/")) 41 offset += RLENGTH 42 43 # If the last component of the path begins with 44 # a ., include hidden files 45 arg = "" 46 if(match(str, "(^|/)\\.[^/]*$")) 47 arg = "-A" 48 49 # Substitute ~/ for $HOME/ 50 sub("^~/", ENVIRON["HOME"] "/", str) 51 52 # Strip the trailing filename 53 sub("[^/]+$", "", str) 54 55 update(offset, "ls " arg quote(str)) 56 } 57 } 58 59 # Push out a new set of completions 60 function update(offset, cmd) { 61 # Only push out the completion if the offset or the 62 # option of ls has changed. The behavior will be the 63 # same regardless, but this is a minor optimization 64 if (offset != loffset || cmd != lcmd) { 65 loffset = offset 66 lcmd = cmd 67 68 cmpl = read(cmd) 69 print offset >fifo 70 print cmpl >fifo 71 fflush(fifo) 72 } 73 } 74 75 # Quote a string. This should work in any Bourne 76 # or POSIX compatible shell. 77 function quote(str) { 78 if (!match(str, /[\[\](){}$'"^#~!&;*?|<>]/)) 79 return str 80 gsub(/\\/, "'\\\\'", str) 81 gsub(/'/, "'\\''", str) 82 return "'" str "'" 83 } 84 85 # Read the output of a command and return it 86 function read(cmd) { 87 if (cmd in cache) 88 return cache[cmd] 89 res = "" 90 while (cmd | getline) 91 res = res quote($0) "\n" 92 close(cmd) 93 return cache[cmd] = res 94 } 95 ! 96 ) 97 res="$(wimenu -c "$@" <$fifo | awk -v "fifo=$fifo" "$script")" 98 exec ${SHELL:-sh} -c "exec $res"