On Mon, Aug 16, 2010 at 12:37:54AM +0200, LuX wrote:
On Thu, 12 Aug 2010 21:19:52 -0400, Kris Maglione wrote:
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:

I have an issue with this second variant, which I didn't notice first
and am unable to solve. Whether I quit it with Return or Esc, the
result is the same: the input string is sent to stdout. If you still
want to help… I'm stuck here.

Yes, I already fixed that problem when I made it into an example file for distribution. Attached.

This is why I left completion up to the program executing the menu.
It knows what it's running it for better than I do.

---> I think that this is very clever!

Bash completion is excellent, but not customizable (as far as I know).
Thus I do agree that it is a good thing that wimenu comes with a much
more elementary completion (it is not intended to duplicate bash), but
fully customizable (it allows to do other things, even those that bash
can not).

Bash completion is actually written in bash, so it's very customizable. This is also why it can in theory be used to provide completion results for wimenu, if someone well enough acquainted with its internals puts his mind to it.

Example: In bash I have always been missing a history behaving like in
vim. Let me explain this. If you have typed a long command 'cmd' at
some moment and want to repeat it, you will probably want to use the
history. Bash will then display successively all the (possibly
numerous) other commands that you typed in the mean time, while vim
while jump directly to 'cmd' provided you type only the beginning of
it. Using bash history inside wimenu with your script (the 'second
variant' mentioned above, which I called 'wim' in another post) allows
to recover this nice behaviour of vim, which eventually makes wim a
significantly BETTER way (in my opinion) of typing commands than to
use a terminal.

Just add this to ~/.inputrc:

    C-w: backward-kill-word
    C-p: history-search-backward
    C-n: history-search-forward

Although I believe C-r brings up some kind of incrimental search dialog. I don't use bash though, so I'm a bit rusty.

PS: I haven't been able to access
http://lists.suckless.org/dev/att-5538/menu.pl I take you at your word if you say that it is 'considerably more
arcane than the awk version'. Anyway this is one more reason to 'make
a point of only using POSIX utilities in examples' as you said.

Hm. Silly pipermail. I take it you're not subscribed to the list, then? I'll paste it inline below, although I've a much more sophisticated version now (attached).

#!/usr/bin/env perl
use warnings;
use strict;
use IPC::Open2;

my $proglist = `wmiir namespace|tr -d "\n"` . "/.proglist";
open2 my $procout, my $procin, "wimenu", "-c";

sub quote(_) {
    local ($_) = @_;
    return $_ unless m/[\[\](){}\$'^#~!&;*?|<>\s]/;
    s/'/''/g;
    "'$_'";
}

my $oldoffset;
sub update(&;$) {
    my ($choices, $offset) = @_;
    if(not defined $offset or $offset != $oldoffset) {
        $oldoffset = $offset || 0;
        print $procin $offset, "\n" if defined $offset;
        print $procin $choices->(), "\n\n";
    }
}

sub readout(@) {
    my ($mode, $expr, @rest) = @_;
    open(my $fd, $mode, $expr, @rest);
    join "\n", map {chomp; quote} <$fd>
}

update {readout "<", $proglist};

while(local $_ = <$procout>) {
    chomp;
    unless(<$procout>) {
        print;
        exit;
    }
    if(not /.*\s/) {
        update {readout "<", $proglist} 0;
    } else {
        my $offset = length $&;
        $_ = substr $_, $offset;
        my @args = m{(/|^)\.[^/]*$} && ("-A") || ();
        $offset += length $& if m{.*/};
        s,/.*?$,,;
        update {readout "-|", "ls", @args, $_ || "."} $offset;
    }
}

--
Kris Maglione

When a religion is good, I conceive it will support itself; and when
it does not support itself, and God does not take care to support it
so that its professors are obliged to call for help of the civil
power, 'tis a sign, I apprehend, of its being a bad one.
        --Benjamin Franklin

Attachment: wimenu-file-completion.sh
Description: Bourne shell script

#!/usr/bin/env perl
use warnings;
use strict;
use File::Glob qw(:glob);
use IPC::Open2;

sub dequote(_);
sub quote(_);
sub readout(@);
sub update(&;$$);

open2 my $procout, my $procin, ("wimenu", "-c", @ARGV);

sub main() {
    my $proglist = `wmiir namespace` . "/.proglist";
    $proglist =~ s/\n//;

    update {readout "<", $proglist};

    while(local $_ = <$procout>) {
        chomp;
        exec $ENV{SHELL} || "sh", "-c", "exec $_" unless <$procout>;

        if(not m{^(?:
                      (?:[^\s\\'] | \\. | '[^']*')+
                      \s+
                  )+}x) {
            update {readout "<", $proglist} 0, "";
        } else {
            my $offset = length $&;
            $_ = substr $_, $offset;

            $offset += length $& if m{.*/};
            s{ ((?:^|/) \.?) [^[\]{}~?*/]* $ }{$1*}x;

            update {map {...@.*/(?!$)@@; quote} bsd_glob dequote($_ || "*"), 
GLOB_MARK|GLOB_NOCHECK|GLOB_QUOTE|GLOB_TILDE} $offset, $_;
        }
    }
}

sub dequote(_) {
    local ($_) = @_;
    s{
        ((?:[^\\'] | \\. | \\$)*)
        (?: ' (.*?) (?:'|$) )?
    }{
        my ($a, $b) = ($1, $2 || "");

        $a =~ s{ (\\.) | \$(\w+) | \$\{\w+\} }{
            $1 || $ENV{$2 || $3}
        }gex;
        $b =~ s/[[\]{}~?*\\]/\\$&/g;
        "$a$b"
    }gex;
    $_
}

sub quote(_) {
    local ($_) = @_;
    return $_ unless m/[[\](){}<>\$'"^#~!&;*?|\s]/;

    s/['\\]/'\\$&'/g;
    s{^ (.*?) (/?) $}{'$1'$2}x;
    $_
}

sub readout(@) {
    my ($mode, $expr, @rest) = @_;
    open(my $fd, $mode, $expr, @rest);
    map {chomp; quote} <$fd>
}

my ($oldoffset, $oldpattern);
sub update(&;$$) {
    my ($choices, $offset, $pattern) = @_;

    if(not defined $offset or $offset != $oldoffset or $pattern ne $oldpattern) 
{
        $oldoffset  = $offset || 0;
        $oldpattern = $pattern || "";
        print $procin $offset, "\n" if defined $offset;
        print $procin join "\n", $choices->(), "\n";
    }
}

main;

# vim:se sts=4 sw=4 et:

Reply via email to