On Tue, Aug 17, 2010 at 02:15:13AM +0200, LuX wrote:
>On Sun, 15 Aug 2010 18:51:55 -0400, Kris Maglione wrote:
>> Yes, I already fixed that problem when I made it into an example
>> file for distribution. Attached.
>
>I have a few unessential remarks, if you allow me:
Of course.
>- Although I don't understand this, it seems that the last 'tail -1' is
> no longer needed.
Ah, you're right. I'd intended to remove that. Fortunately this
changeset hasn't left my patch queue yet. :)
>- Since you replaced the call to dirname by a 'sub' command just after
> the comment '# Strip the trailing filename', it happens that when I
> type 'ls /' in the input area, it is the content of the $HOME
> directory instead of / which is displayed by wimenu. Here is a fix:
>
> # Strip the trailing filename
> if(match(str, "^/[^/]*$"))
> str = "/" str
> sub("(/|^)[^/]*$", "", str)
This would be better:
sub("[^/]+$", "", str)
I'll update the script.
>- I have read somewhere that /dev/shm was a good place to put files
> used by programs to discuss one with each others. This would apply
> to "fifo" in this case. I don't know if you have an opinion on this.
That would not help in this case. For one thing, /dev/shm is
very system specific. Only certain Linux distributions support
it. For another, its value is in that it's a memory filesystem,
so file contents are stored in RAM rather than on disk. But our
file is a FIFO, anyway. Its contents never touch the disk. It
would probably be better in ~/.wmii/menu_fifo or the like,
though.
>- I liked more the previous behaviour, when the script ends by sending
> the input string to stdout (like wimenu does) so that it can can be
> processed by some independent script like for example this one:
I think that you're right in principle. However, I'm going to
leave the example as is because it illustrates the purpose of
the script better and as it's fully self-contained, it works
without modification.
>In addition I enjoyed adding another minor feature: when a list of
>options has been declared in the script for the initial command of the
>input line, every time a '-' is typed at the beginning of a new
>argument in a line starting with that command, this list of options is
>displayed instead of a list of files. I find it convenient for some
>commands, like 'lp' or 'pdfnup' which accept many options, useful to
>me but that I do not use to remember.
I think this is a good idea, and it was what my help file
example was meant to suggest. I'd suggest some slight changes,
though:
--- menu_thing 2010-08-16 20:32:26.000000000 -0400
+++ - 2010-08-16 20:49:19.051116173 -0400
@@ -5,18 +5,18 @@
# Program name completion requires that a program list already
# exist in $(wmiir namespace)/.proglist
-fifo="/dev/shm/wim_$USER"
+fifo=$HOME/.wmii/menu_fifo
mkfifo $fifo 2>/dev/null
script=$(cat <<'!'
BEGIN {
- progs = "cat $(wmiir namespace)/.proglist"
+ progs = read("cat $(wmiir namespace)/.proglist")
# Favorite options for some programs
opt["lp"] = "-o media=a4\n-o landscape\n-o sides=two-sided-long-edge\nsides=two-sided-short-edge\n-o number-up=N\n"
# Print the first set of completions to wimenu’s fifo
- print read(progs) >fifo
+ print progs >fifo
fflush(fifo)
}
@@ -25,13 +25,17 @@
# Skip the trailing part of the command.
# If there is none, this is the result.
if (!getline rest) {
- print
- exit
+ print
+ exit
}
if (!match($0, /.*[ \t]/))
# First argument, provide the program list
- update(0, progs)
+ update(0, "", progs)
+ else if($NF ~ /^-/)
+ # If the last argument starts with a -, list
+ # options declared in opt instead of files
+ update(RLENGTH, "", opt[$1])
else {
# Set the offset to the location of the last
# space, and save that part of the completion
@@ -46,31 +50,21 @@
# If the last component of the path begins with
# a ., include hidden files
arg = ""
- if(match(str, "(^|/)\\.[^/]*$"))
- arg = "-A"
+ if(str ~ "(^|/)\\.[^/]*$")
+ arg = "-A "
# Substitute ~/ for $HOME/
sub("^~/", ENVIRON["HOME"] "/", str)
# Strip the trailing filename
- if(match(str, "^/[^/]*$"))
- str = "/" str
- sub("(/|^)[^/]*$", "", str)
-
- # If the last argument starts with a -, list
- # options declared in opt instead of files
- lscmd = "ls " arg quote(str)
- if(match($0, "\\ -[^\\ ]*$")) {
- lsopt = opt[gensub(/\ .*/, "", 1)]
- lscmd = "echo -n \"" lsopt "\""
- }
+ sub("[^/]+$", "", str)
- update(offset, lscmd)
+ update(offset, "ls " arg quote(str))
}
}
# Push out a new set of completions
- function update(offset, cmd) {
+ function update(offset, cmd, cmpl) {
# Only push out the completion if the offset or the
# ls command has changed. The behavior will be the
# same regardless, but this is a minor optimization
@@ -78,7 +72,8 @@
loffset = offset
lcmd = cmd
- cmpl = read(cmd)
+ if(cmd && cmpl == "")
+ cmpl = read(cmd)
print offset >fifo
print cmpl >fifo
fflush(fifo)
>Note: It would be better to declare the 'opt' array outside this
>script, in a sort of configuration file, but I don't know how to do
>this.
The following will do what you want:
cat >>$HOME/.wmii/menu_opts <<!
lp:
-o media=a4
-o landscape
-o sides=two-sided-long-edge
-o sides=two-sided-short-edge
-o number-up=N
!
#!/bin/sh
# This script will launch wimenu and provide command
# completion for the first argument and filename completion
# for each following argument, and pass the result to stdout.
# Program name completion requires that a program list already
# exist in $(wmiir namespace)/.proglist
export opts=$HOME/.wmii/menu_opts
fifo=$HOME/.wmii/menu_fifo
mkfifo $fifo 2>/dev/null
script=$(cat <<'!'
BEGIN {
progs = "cat $(wmiir namespace)/.proglist"
# Print the first set of completions to wimenu’s fifo
print read(progs) >fifo
fflush(fifo)
}
# Process the input and provide the completions
{
# Skip the trailing part of the command.
# If there is none, this is the result.
if (!getline rest) {
print
exit
}
program = $1
sub(/"/, "\\\"", program)
if (!match($0, /.*[ \t]/))
# First argument, provide the program list
update(0, progs)
else if($NF ~ /^-/)
# If the last argument starts with a -, list
# options declared in opt instead of files
update(RLENGTH,
"awk <$opts '$0 == \"" program ":\", /^$/ {" \
"if(/^[ \\t]/) { sub(/^[ \\t]+/, \"\"); print }" \
"}'")
else {
# Set the offset to the location of the last
# space, and save that part of the completion
offset = RLENGTH
str = substr($0, offset + 1)
# If we are completing a sub-directory, adjust
# the offset to the position of the last /
if (match(str, ".*/"))
offset += RLENGTH
# If the last component of the path begins with
# a ., include hidden files
arg = ""
if(str ~ "(^|/)\\.[^/]*$")
arg = "-A "
# Substitute ~/ for $HOME/
sub("^~/", ENVIRON["HOME"] "/", str)
# Strip the trailing filename
sub("[^/]+$", "", str)
update(offset, "ls " arg quote(str))
}
}
# Push out a new set of completions
function update(offset, cmd, cmpl) {
# Only push out the completion if the offset or the
# ls command has changed. The behavior will be the
# same regardless, but this is a minor optimization
if (offset != loffset || cmd != lcmd) {
loffset = offset
lcmd = cmd
print offset >fifo
print read(cmd) >fifo
fflush(fifo)
}
}
# Quote a string. This should work in any Bourne
# or POSIX compatible shell.
function quote(str) {
if (!match(str, /[\[\](){}$'"^#~!&;*?|<>]/))
return str
gsub(/\\/, "'\\\\'", str)
gsub(/'/, "'\\''", str)
return "'" str "'"
}
# Read the output of a command and return it
function read(cmd) {
if (cmd in cache)
return cache[cmd]
print "read " cmd
res = ""
while (cmd | getline)
res = res quote($0) "\n"
close(cmd)
return cache[cmd] = res
}
!
)
wimenu -h "$HOME/.bash_history" -n 5000 -c "$@" <$fifo | awk -v "fifo=$fifo" "$script"
-- Kris Maglione Sufficiently advanced political correctness is indistinguishable from sarcasm. --Eric NaggumReceived on Tue Aug 17 2010 - 03:22:18 CEST
This archive was generated by hypermail 2.2.0 : Tue Aug 17 2010 - 03:24:02 CEST