I have some boilerplate code in one of my vimscript functions:

" Save register 'a' so we don't clobber it
let savereg = @a

" Yank the current WORD into register 'a' and save it to 'input'
normal "ayiW
let input = @a

" Restore register 'a' so we don't clobber it
let @a = l:savereg

" ... Do work on 'l:input'

Is there a better way to do what I want? That is, to operate on a WORD (or any text object, really) without clobbering a register?

  • If I knew how to operate on the range '<,'> then my problem would be solved, I believe. But I'm not sure how to get text from between 2 marks. I'm reading the documentation but I'm quite lost... I am looking for a starting point or a hint. – Ari Sweedler Jan 29 at 6:41
  • 1
    yes, but it is clumsy. Use the getline() functions and in combination with the cursor position, select the needed part of the line – Christian Brabandt Jan 29 at 7:03
  • 1
    @AriSweedler Since you sound eager to learn but maybe not grokking the help docs this is a widely praised route to enlightenment: Learn Vimscript the Hard Way (Not for newbies but doesn't look like that's you. At the very least bookmark it for the future.) – B Layer Jan 29 at 20:37

First, if your script runs from a mapping than you probably should support v:register - let the user decide what to use.

Next, if your operation is a sort of "visual replacement" (get selection, modify and put it back) it makes sense to model it after :h v_p (maybe even end it with gvp or such).

In this case either @- (for "less-than-a-line" selection) or @9 (for a multiline selection) will be overwritten anyway, so you can make use of one of them in your script.

Otherwise, I prefer simply to clobber @0 as it seems like a natural choice. Anyway, it gets overwritten quite often, and it could also be a good idea to spare "original input" for the user.

|improve this answer|||||
  • Thank you for the tips about best practice! I consider that invaluable. What I am really trying to accomplish a macro that reads a WORD under the cursor and does work on it. Specifically, I want to be able to append "(due in 5 days)" with a single keystroke when my cursor is over a date that's 5 days in the future. That wouldn't be a very good question to ask here, tho. What I wrote can be found here, if you're curious: github.com/AriSweedler/dotfiles/blob/master/.vim/plugin/due.vim – Ari Sweedler Jan 29 at 7:40
  • 4
    @AriSweedler In your specific case it's probably sufficient to do simply expand('<cWORD>') – Matt Jan 29 at 7:44
  • I am so stoked to be learning this stuff. You are right, and thank you for the improvement. – Ari Sweedler Jan 29 at 7:58

Is there a better way to do what I want? That is, to operate on a WORD (or any text object, really) without clobbering a register?

If you want the current WORD in specific, then this works:

let input = expand('<cWORD>')

It's not a general solution, but it seems to fit what you're after in this particular instance.

|improve this answer|||||
  • 1
    Matt have this answer as a comment already, but this is the best answer. I won’t change who I gave the green check to, but this answer should stay here as it definitely adds value – Ari Sweedler Jan 29 at 16:17
  • 1
    Agreed. I did notice the comment but I thought this definitely deserved to be an answer. Matt does a great job at addressing the general case of any text object or visual region. – filbranden Jan 29 at 16:57

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.