0

User commands can be given the -complete=shellcmd option. This turns out to be quite disappointing, since instead of working in the same way as vim's built-in completion for its :! command, it just repeatedly completes the names of shell commands in the path.

I'd like to write a command that completes command names and then files. Is there a convenient way to do this, either with built-in vim functionality or via an addon?

intuited
  • 23,174
  • 7
  • 66
  • 88

2 Answers2

1

Why not leverage bash-completion while you're at it? You should be able to fork a bash shell with /etc/bash_completion sourced and talk to it over pipes to interrogate it. That way you'd have all the shell goodies.

Of course, you could do as I do and C-z suspend Vim to drop back to your shell instead.

sehe
  • 374,641
  • 47
  • 450
  • 633
  • Forking seems like it would work, but I'm hoping for something that would be cross-platform compatible. Certainly this can be done using vim's built-in globbing functionality; the trickiest part seems to be splitting the existing line properly. Well, that and getting over my annoyance at the fact that vim apparently doesn't expose its own completion for `:!`. An addon that would optionally take advantage of bash-completion and fall back to using vim functionality would be really cool.. – intuited Apr 17 '11 at 01:11
  • Also: `^Z` is not useful here because the shell command itself is to be executed by a vim function which uses its output. – intuited Apr 17 '11 at 01:13
  • Ok I get it then. This might actually be a good feature request (either to make it pluggable (expose API) or to just implement the improvements you want). See [vim-dev](http://groups.google.com/group/vim_dev) or [vote](http://www.vim.org/sponsor/vote_results.php) – sehe Apr 17 '11 at 21:27
  • @sehe: I guess there's some sort of unspoken rule against exposing programmatic completion functionality: bash doesn't support this either. There seems to be a partial solution at http://stackoverflow.com/questions/3520936/accesssing-bash-completions-for-specific-commands-programmatically#answer-3640096 which seems like it will work for completion which is done by functions, but doesn't provide fallback to filename completion. Communicating with the subprocess with pipes doesn't seem like it will work, since piping in a TAB will just result in it being incorporated literally into the command. – intuited Apr 18 '11 at 00:51
  • Good find: That's exactly my proposed solution strategy. I never said anything like using pipes to emulate keystrokes ? `` I mention pipes to dos this, _but_ without having to fork every single time (make it a 'daemon'). Using pipes is an optimization, mainly (no need to that prematurely) – sehe Apr 18 '11 at 06:26
  • 1
    @sehe: I considered using pipes that way, but it seemed like changing directories and doing any other environment-related stuff — so that changes in vim's environment variables would be reflected in the completion results — would be extra complicated, and there wouldn't be much gained by it. It does depend on bash startup time, though. Maybe it would ideally be an option. Anyway I'm going pretty KISS on this one. – intuited Apr 20 '11 at 08:42
  • Good points, intuited. I hope to see the end result on this one. Should be pretty slick – sehe Apr 20 '11 at 08:44
0

I ended up writing a vim addon called shell_complete. It's not really super-megazord-awesome, but it does do pretty much what I was looking for, which is to more or less emulate the completion used by :!. This is to say that it's sort of "pseudo shell completion": it completes commands for the first "word", and files from there out. Basic \ escaping of spaces seems to work okay.

pseudo shell completion

Installation of shell_complete is sort of complicated, especially for those not familiar with vim-addon-manager. The addon has a couple of dependencies, and none of them are "published", which is to say that VAM doesn't know about them yet. You can let VAM know about them by installing (via git clone; see the docs for more info) another addon I've called tt_addons. Anyway, once you've done this, you should be able to just :ActivateAddons tt_addons and then :ActivateAddons shell_complete.

If you're not using VAM, you'll have to download (or git clone, more likely) all of the related modules, and then mix them into your vim directory, or make them pathogen bundles, or what have you. If you actually end up wanting to do this, it's likely worth your while to start using VAM. If you're some sort of curmudgeonly Luddite who refuses to do so, let me know and I might put the thing up on vim.org if there's decent interest.

I think it's pretty obvious (at least from the docs) how to use shell_complete, but if you would like to see it In Action you can check out my reput addon, which uses it to do completion on its :RePutShell command. reput is also currently only available through github, and the same caveats apply with respect to installation via VAM.

Actual shell completion using the shell

For the record, I think sehe's suggestion about using the shell itself to do completion is totally flash. I actually spent quite a while figuring out how to do this, and have determined that it's possible, at least in theory. I initially thought it would be easier to do it this way than by doing what shell_complete does, but it turns out that bash (like vim) doesn't provide any programmatic way to access its completion facilities, so you end up basically having to reimplement them in bash, after scraping the configuration using grep and friends. Bash sucks a lot for this sort of thing, so I'm cowardly refusing to fight that battle, at least for the moment.

Should someone be so brave/foolish as to take up this standard, they may avail themselves of the chronicles of my travails. I managed to get it to do completions that are handled by custom completion functions. However, this is only a small part of the puzzle, because bash also provides about 6½ other ways to do completion. It does sort of complement the functionality provided by shell_complete, so it might be worthwhile to synergistically merge the two into a sort of awkward, drunken Voltron of vim shell completion.

intuited
  • 23,174
  • 7
  • 66
  • 88