Re: Strange compgen behaviour

2009-09-25 Thread Mathias Dahl
 Hm, I can't see any problem here. My version lets you pick any file in
 any subdir by simply typing the name (or part of it) without the
 directory part. After all, 'find -name' matches names, not paths (if you
 want to match full paths, use 'find -path'). I'd also rather use printf
 %P\n (capital P) instead of %p, the results look nicer (IMHO).

When I try with %P it works (better). However, when I do that and use
the -o filenames option I see only the filenames of the sub folders
and sometimes that name does not reflect what it is as well as the
folder does (if for example I have a folder called Cool Movie 2 and in
it a file called thefile.avi). So, it seems I did not really want what
I thought I wanted from the beginning :) The output I get now looks
like this:

...
filie_in_root_folder.avi
Some sub folder/file_in_sub_folder.avi
...

The only annoyance now is the hardcoded quoting (to handle spaces and
other bad chars) I do using sed, but I guess I have to live with it.

This has been an interesting topic!

/Mathias


Re: Strange compgen behaviour

2009-09-25 Thread Mathias Dahl
 This has been an interesting topic!

I thought I should share the final version as well:

_mm() {
local cur files
COMPREPLY=()
cur=${COMP_WORDS[COMP_CWORD]}
files=$(find /home/mathias/Videos/movies/ -iname *.avi -type f -
printf %P\n | grep ${cur} | sed s/\\([][\\(\\) ,\']\\)/\\1/
g)
local IFS=$'\n'
COMPREPLY=(${files})
}

complete -F _mm mm

And the `mm' script needs to append the root folder, of course, like
so:

#!/bin/bash
mplayer /home/mathias/Videos/movies/$1

Works quite well. Maybe it will be useful to someone else too.

/Mathias


Re: Strange compgen behaviour

2009-09-25 Thread Mathias Dahl

 printf %q $filename

 will either insert backslashes in front of all the shell metacharacters,
 or $'...' quote the whole thing, or take some other action which renders
 a string safe.  It's basically the opposite of eval.

Interesting! Can I make it part of my pipe (in place of `sed') or need
I change it to a for or while loop? This is what I have now:

files=$(find /home/mathias/Videos/movies/ -iname *.avi -type f -
printf %P\n | grep ${cur} | sed s/\\([][\\(\\) ,\']\\)/\\1/
g)

/Mathias


Re: Strange compgen behaviour

2009-09-25 Thread Mathias Dahl
 Interesting! Can I make it part of my pipe (in place of `sed') or need
 I change it to a for or while loop? This is what I have now:

 files=$(find /home/mathias/Videos/movies/ -iname *.avi -type f -
 printf %P\n | grep ${cur} | sed s/\\([][\\(\\) ,\']\\)/\\1/
 g)

Got this to work:

 files=$(find /home/mathias/Videos/movies/ -iname *.avi -type f -
printf %P\n | grep ${cur} | while read file; do
printf %q $file
echo
done)

With the %q option to printf it no longer accepts a \n so I needed the
extra echo.

/Mathias


Re: Strange compgen behaviour

2009-09-24 Thread Mathias Dahl
 Hm, compgen appears to behave strange if words contain whitespace.
 However, you don't need it, as you build the list yourself. Try this:

   _mm2() {
       local cur files
       cur=${COMP_WORDS[COMP_CWORD]}
       files=$(find /home/mathias/Videos/movies/ -iname $cur*.avi -type
 f -printf %P\n)
       local IFS=$'\n'
       COMPREPLY=($files)
   }

Ah, you're right of course, I can do the matching myself. I have yet
another version working now (had to change your latest suggestion and
use grep for matching because -name does not like full paths which
becomes the case here):

_mm() {
local cur files
COMPREPLY=()
cur=${COMP_WORDS[COMP_CWORD]}
files=$(find /home/mathias/Videos/movies/ -iname *.avi -type f -
printf %p\n | grep ${cur})
local IFS=$'\n'
COMPREPLY=(${files})
}
complete -o filenames -F _mm mm

Now, this works almost. The remaining problem is that because `find'
finds file in subdirs (which I want, otherwise I could add the -
maxdepth option) as well, the `-o filenames' argument to `complete'
does not play well with it. I see the names of files in subdirs listed
when I type TAB (without path) but can never pick them without knowing
the name of the folder they are in. So I have to get rid of that
option, but then I have to shell quote the file name myself to handle
spaces, brackets of various sorts, comma characters etc. Will hunt for
such a function and see. There are all sorts of crazy helper functions
in /etc/bash_completion, of which I barely understand anything.

Thanks!


Re: Strange compgen behaviour

2009-09-24 Thread Mathias Dahl
 ...but then I have to shell quote the file name myself to handle
 spaces, brackets of various sorts, comma characters etc. Will hunt for
 such a function and see. There are all sorts of crazy helper functions
 in /etc/bash_completion, of which I barely understand anything.

I did not find any generic way to quote/escape file names so I
hardcoded some chars I know exist in my file names and used sed:

_mm() {
local cur files
COMPREPLY=()
cur=${COMP_WORDS[COMP_CWORD]}
files=$(find /home/mathias/Videos/movies/ -iname *.avi -type f -
printf %p\n | grep ${cur} | sed 's/\([\(\) ,]\)/\\\1/g')
local IFS=$'\n'
COMPREPLY=(${files})
}
complete -F _mm mm

However, I don't like it, is feels ugly and one of these days there
will be some other funky char in some filename... :(

/Mathias


Re: Strange compgen behaviour

2009-09-23 Thread Mathias Dahl
 It depends heavily on how the variables IFS and zf are set. From 'man bash':

 -W wordlist
     The  wordlist is split using the characters in the IFS special
     variable as delimiters, and each resultant word is expanded.
     The possible completions are the members  of  the  resultant
     list which match the word being completed.

I used a newline since the original listing comes from `find'.

 You didn't say how you assigned the variable zf. If you simply did
 zf=$(ls /home/mathias/Videos/movies/*), the Brazil line will be split
 into 4 words instead of 1. However, your output suggest that you somehow
 managed to combine all file names to a single word starting with
 Harry.Potter.

Yes, that could be the case.

 Try this: Choose a character which doesn't appear in any file name,
 e.g., ':'.

      list=$(printf %s: /home/mathias/Videos/movies/*)
      IFS=: compgen -W $list -- $zc

That works, thanks! However, I also want files from sub folders to be
found, so I use `find' to list them.

Here is my latest attempt, using the idea of setting IFS to `:':

_mm2() {
local cur files
COMPREPLY=()
cur=${COMP_WORDS[COMP_CWORD]}
files=$(find /home/mathias/Videos/movies/ -iname '*.avi' -type f -
printf %p:)
OLDIFS=$IFS
IFS=:
COMPREPLY=($(compgen -W ${files} -- ${cur}))
IFS=$OLDIFS
}
complete -o filenames -F _mm2 mm

Looks like it should work but it does not. Typing mmSPCTAB gives
the listing and completes all the way to the path, but if I add B
again it does not match Brazil.

Any ideas?