Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

Re: complete based on contents of another folder or folders?



I'm sending this even though PWS already answered, because it takes
a somewhat different tack on the question, and I'd already written most
of it ...

On Aug 7,  6:21am, TJ Luoma wrote:
} 
} ps - Is there an "intro-to-zsh-completion" (aka "completion for
} dummies" ;-) somewhere?

http://zsh.sourceforge.net/Guide/zshguide06.html#l144 perhaps?  You
probably want specifically to read the section on "new" completion.

} 1)
} "open -a [tab]" should offer "any file found in
} [...] 
} which ends with '.app' and should not show the dirname (and doesn't
} need to show the '.app' suffix, but that's not crucial).

This should already be handled for you if you have enabled "new"
completion with the "compinit" function in your startup files.

There's an entire subtree Completion/Darwin/ in the zsh sources that
has MacOS X functions.  Completion/Darwin/Type/_retrieve_mac_apps is
used to populate the list of applications for most Darwin completers.
It uses Spotlight to find all the .app files that "open" might call.

Of course this might not help much with providing an example of how
to write such a completer yourself.  (See PWS's example.)

} (I assume that once completion is setup, 'open -a B[tab]' will only
} offer apps which start with the letter "B")

Yep.

} 2) Similarly
} 
}         get_app [tab]
} 
} should offer completions based on files found in
} ~/Dropbox/get_app/rcs/ with the following stipulations:

This doesn't exist by default so it's probably a better example.  Let's
build it up, starting with "based on files":

    compdef _files get_app

"found in ~/Dropbox/get_app/rcs/":

    compdef "_files -W ~/Dropbox/get_app/rcs/" get_app

} - no filenames do NOT have spaces in them

I'm not sure what that means.  "All filenames DO have spaces" perhaps?
In any case this shouldn't matter, completion will take care of doing
quoting.

} - subfolders may exist, but should be ignored (same is true for files
} which begin with '.')

Files beginning with "." are ignored by default, as with globbing,
unless you explicitly have a leading dot on the word you complete.

To exclude subfolders, you have to add a completion style that only
matches files:

    zstyle ':completion::complete:get_app::*' file-patterns '*(.)'

There is a similar option for the _files completer --

    compdef "_files -g '*(.)' -W ~/Dropbox/get_app/rcs/" get_app

-- but it doesn't work the same way; it applies at any point in the
folder hierarchy, whereas the file-patterns style will determine if
the subfolder is considered at all.  There is a useful side-effect
of the -g option which is that files matching the pattern are placed
in a separate "completion group" from directory names, so files are
completed first and directories appear only when you've exhausted all
possible files.  You may find you prefer that to omitting them.

} - I only want the part of the filename up until the first literal "."
} (and each file has at least one ".")

At this point you've gone beyond what can be done with configurations
of the existing completions, because omitting part of the matching
name (as opposed to the leading path) is a special condition that's
not generally passed through all the layers of helper functions.

(If you wanted to remove specific substrings like ".jpg" it could be
done with a matcher-list zstyle, but I don't believe there's any way
to configure a matcher-list for "anything following a dot".)

As in PWS's example, it's usual to start by defining a function using
the command name preceded by an underscore.  I suggest only a single
improvement to PWS's function, which is to apply :t to the $found glob
to get the effect of the -W option in removing the leading path.

  _get_app() {
    local -a found
    local expl

    found=(~/Dropbox/get_app/rcs/*(.:t))
    found=(${found%%.*})
    _wanted apps expl 'app' compadd -a found
  }

Then of course you also need:

  compdef _get_app get_app

You can get this automatically by placing in your $fpath a file named
_get_app that looks like this (remove the "snip" lines obviously):

-- 8< -- snip -- 8< --
#compdef get_app
local -a found
local expl

found=(~/Dropbox/get_app/rcs/*(.:t))
found=(${found%%.*})
_wanted apps expl 'app' compadd -a found
-- 8< -- snip -- 8< --



Messages sorted by: Reverse Date, Date, Thread, Author