Thursday, January 19, 2012

Re: Retrieve the argument of a prior Ex mode command

On Wed, Jan 18, 2012 at 08:42:51PM EST, Tim Chase wrote:

[..]

> I think the biggest impediment to making a simple mapping to do this
> would be that in bash, commands are almost always of the form
> "<command> [optional args]". In Vim, you have a variety of patterns,
> so extracting the "args" portion or the "last arg" portion becomes
> more complex. Not that it can't be done. In at least an xterm, Vim
> can see alt+period for the purposes of mapping. So this can easily be
> exploited to do *some* form of last-command-expansion.

Good point. I noticed that when I am actually _editing_ .. I tend to use
a lot of commands where there is either no argument (:w :bd :ls :tabe,
:qc.. etc.) or where the argument can be attached to the command without
intervening white space -- :b1, :b2, for instance. There are some some
commands of the ':cmd+argument' type, but they are not the most often
used (:tabe /path/to/file, :vne ~/.vimrc, :saveas /tmp/vimrc...)

On the other hand, when I am working on my Vim environment (customizing,
scripting..), the commands are usually of the 'cmd+argument' form (:h
map, :set lcs?, :let g:var..)

As you pointed out, Vim's ex-mode command syntax appears to be more
complex than I had reallized.

>> As to the workarounds you suggest, I'll take a look at the cmdline
>> register, but I am skeptical I could integrate this particular
>> strategy to my workflow.

> So I'd exploit it something like
>
> =================================================
> function! PreviousTail()
> let item = histget(getcmdtype(), -1)
> let patterns = [
> \
> '^\%([GvV]\|g\%[lobal]\|s\%[ubstitute]\)\(\W\)\%(\1\@!.\|\\\1\)\1\(.*\)',
> \ '^.* \(.*\)',
> \ ]
> for pat in patterns
> let matches = matchlist(@:, pat)
> if len(matches)
> for i in range(1,9)
> if len(matches[-i])
> return matches[-i]
> endif
> endfor
> endif
> endfor
> return item
> endfunction
>
> cnoremap <expr> <m-.> PreviousTail()
> =================================================

Wow..! This is a lot more sophisticated than what I had in mind.

Incidentally, I rather like the 'cnoremap <expr>...' syntax and I need
to evaluate it against the 'cnoremap .... <C-\>eMyFunc()<CR>' form. In
my case they do the same -- including the fact that the value passed
back by the function overwrites the entire line including what I had
already typed (cf. my earlier reply to Paul) :-(

> You can add patterns to find particular subsets of the last command.
> This should work (mostly) for both Ex and search command-lines. You
> can tweak the logic accordingly, adding other patterns, or having
> different pattern-sets based on getcmdtype().

> One might have to work up smart quoting/parsing (perhaps using
> something like Python's "shlex" module if your Vim is built with
> Python support) to handle cases like

> :echo "hello world"
> :let greeting = <m-.>

> With the current code, it would just pull in

> :let greeting = world"

> but with proper quoting-smarts applied in certain contexts, it would
> correctly give you

> :let greeting = "hello world"

> I'll leave such adventures as an exercise for the reader

I think my use case is pretty much limited to handling paths (navigating
the file system) and file names (loading & saving buffers), so I think
I'll stick with the basic functionality I initially had in mind.

But I'll analyze your PreviousTail() function nonetheless, if only to
understand how it works -- especially the fact that you do no have an
initialization routine, which suggests that you let Vim keep track of
where it is pointing in the history.

Thanks,

CJ

--
You received this message from the "vim_use" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

No comments: