wmii

git clone git://oldgit.suckless.org/wmii/
Log | Files | Refs | README | LICENSE

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"