On Thu, Aug 12, 2010 at 10:51:59PM +0200, LuX wrote:
>I would really like to use the 'custom completion' feature documented
>in the man page of wimenu-3.9.2, just as in the provided example:
>
>Unfortunately the example script given there goes far beyond my
>skills. I have copied and pasted it in a file ~/wim. Then 'sh wim'
>does exactly what is expected (fortunately enough I didn't have any
>important file called 'fifo' in my home directory ;)) except that once
>I have selected something, for example 'foo 1', and pressed Return, I
>would like to recover the string 'foo 1' in order to do something with
>it. Instead of this wim quits silently and I haven't found a way to
>recover the selected string.
>
>Any hint?
Yes... Unfortunately awk dies on SIGPIPE in that example, so it
never runs the END block. This slight variation should work:
wimenu -c <fifo | awk '
BEGIN {
# Define the completion results
cmds = "foo\nbar\nbaz\n"
cmd["foo"] = "1\n2\n3\n"
cmd["bar"] = "4\n5\n6\n"
cmd["baz"] = "7\n8\n9\n"
# Print the first set of completions to wimenu’s fifo
fifo = "fifo"
print cmds >fifo; fflush(fifo)
}
//
# Push out a new set of completions
function update(str, opts) {
print length(str) >fifo # Print the length of the preceding string
print opts >fifo # and the options themself
fflush(fifo)
}
# Ensure correct argument count with trailing spaces
/ $/ { $0 = $0 "#"; }
{ # Process the input and provide the completions
if (NF == 1)
update("", cmds) # The first arg, command choices
else
update($1 " ", cmd[$1]) # The second arg, command arguments
# Skip the trailing part of the command
getline rest
}
' | tail -1
As for modifying it, you'd probably be happier with python,
perl, or ruby, but I make a point of only using POSIX utilities
in examples. But if you're looking for a start, this is the
above modified to (crudely) complete a command and then files in
the current directory:
script=$(cat <<'!'
# Push out a new set of completions
function update(offset, cmd) {
# Only push out the completion if the offset has
# changed. The behavior will be the same regardless,
# but this is a minor optimization
if (offset != loffset) {
loffset = offset
print offset >fifo
print read(cmd) >fifo
fflush(fifo)
}
}
# Quote a string. This requires that your shell supports
# rc quoting syntax (zsh with 'setopt rcquotes' or rc, namely)
function quote(str) {
if (!match(str, /[\[\](){}$'"^#~!&;*?|<>]/))
return str
gsub(/'/, "''", str)
return "'" str "'"
}
# Read the output of a command and return it
function read(cmd) {
# We need to use a cache since every use of an
# input command refers to the same process, which
# means it can only be run once.
if (cmd in cache)
return cache[cmd]
res = ""
while (cmd | getline)
res = res quote($0) "\n"
return cache[cmd] = res
}
BEGIN {
fifo = "fifo"
progs = ". wmii.sh; wi_proglist $PATH"
# Print the first set of completions to wimenu’s fifo
print read(progs) >fifo
fflush(fifo)
}
// # Print the line
# Process the input and provide the completions
{
if (!match($0, /.*[ \t]/))
# First argument, provide the program list
update(0, progs)
else {
# Set the offset to the location of the last
# space, and save that part of the completion
offset = RLENGTH # Set by match() above
str = substr($0, offset + 1)
# If we're completing a sub-directory, adjust
# the offset to the position of the last /
if (match(str, ".*/"))
offset += RLENGTH
cmd = "ls " quote(str)
if (str && !match(cmd, "/$"))
# Use dirname to chop off the end of the
# last directory component
cmd = "ls \"$(dirname " quote(str) ")\""
update(offset, cmd)
}
# Skip the trailing part of the command
getline rest
}
!
)
wimenu -c <fifo | awk "$script" | tail -1
Although that may confuse you more than help. I've been told
that awk is a fairly arcane language.
Ideally, it should be fairly simple to use a simple bash script
to provide completions based on its programmable completion
system, but I've never gotten far enough into its internals to
make it work. If you'd like to try, though, I'm sure that
someone in #bash could help.
>By the way, is it intended to add to dmenu a similar feature (and also
>the -S option of wimenu)? I'm asking this because at my office wmii is
>not available (there is no wmii package in fedora) thus I'm using i3
>with dmenu instead. On the other hand the vertical mode of dmenu is
>much more comfortable than the horizontal mode of wimenu on the small
>screen of my laptop…
I can't speak for the dmenu developers, but new features are
usually added only after someone's written a patch and it
becomes popular. You might be able to find an rpm somewhere. I
would provide one, but I hate rpm with a passion. Personally, I
just install wmii to my home directory.
make PREFIX=$HOME/wmiinst install
and adding ~/wmiinst/bin to $PATH does the trick. If you don't
have a compiler available, you should be able to copy the tree
from any system, if you 'export LDFLAGS=-static' when you build.
I might add a horizontal mode to wimenu. I'm personally not very
fond of it, but others seem to find it useful and it's a simple
enough change.
-- Kris Maglione The object-oriented model makes it easy to build up programs by accretion. What this often means, in practice, is that it provides a structured way to write spaghetti code. --Paul GrahamReceived on Fri Aug 13 2010 - 03:19:52 CEST
This archive was generated by hypermail 2.2.0 : Fri Aug 13 2010 - 03:24:02 CEST