0

I have this code intended to:

  1. read current line
  2. extract variable from end of line, looking for text like #ad04e482
  3. search for filename that begins with the string ad04e482
  4. open that file to edit in vim
  5. bind this to a few keystrokes <leader>tn

I'm struggling to define and use these variables inside the execute function calls...

function TaskSearch()
  let line = getline('.')
  let task_id = split(line, "#")[1]
  let task_note = execute('find ~/.task/notes/ -name "task_id*"')
  execute('edit ~/.task/notes/$task_note')
endfunction
command! TaskSearch :call TaskSearch()
nnoremap <leader>tn :TaskSearch <Enter>

I've tried many different variatlions of the let task_note... and execute(...) statements without any success.

I've looked through various posts on the stack network but I haven't seen any examples using a vimscript variable (like task_id in my case) inside a shell command's arguments.

I need to take the results of that command, which should be just a single file, and then open that file in a new buffer to edit it. How can I achieve this?

1

1 Answer 1

3

Here's one way that works...

function! TaskSearch()
  ..snip...
  let task_note = system('find ~/.task/notes -name "' . task_id . '"\*')
  exe 'e ' . task_note
endfunction

Call with :call TaskSearch().

Some of the key changes...

  1. Escaping of glob (*) in the find call.
  2. Use of system() which is a vim function that returns result of executing external processes.
  3. Use of Ex commands rather than function(s) to open the file, i.e. using exe and e[dit].
  4. find should return a full path so there shouldn't be a need to repeat ~/.task/notes in the exe line.

Might need a little fine tuning to get it to work for your exact problem (e.g. this isn't controlling for a scenario where find returns more than one file...make sure your query is specific/explicit enough to prevent that or use additional shell commands to narrow it down, if needed). Let me know if you have any problems or questions about how it works.

An important point is that when you want to include the value of a variable in a command you usually need to use something like exe, i.e. something that will treat its arguments as an expression to be evaluated.

17
  • that works, thank you! Now I realize I had the wrong approach because sometimes the file does not exist yet.... so my lines now look like let task_note = system('task ' . task_id . ' | grep UUID | sed "s/UUID //"') and exe 'e ' . '~/.task/notes/' . task_note . '\.mkd' which gives me the error: Error detected while processing function TaskSearch: line 5: E16: Invalid range: 59d8fd85-f117-49c3-a14a-4474af492825^@\.mkd
    – alec
    Commented Aug 26, 2020 at 14:18
  • 1
    I have no idea what you're trying to do with your shell command but the system() call looks syntactically correct. Just print the result before trying to open it until you are sure it's correct. Then you could do this: exe printf("e ~/.task/notes/%s.mkd", task_note)
    – B Layer
    Commented Aug 26, 2020 at 14:41
  • 1
    No that must be from task...whatever that is.
    – B Layer
    Commented Aug 26, 2020 at 14:49
  • 1
    I already did. exe printf(....
    – B Layer
    Commented Aug 26, 2020 at 14:56
  • 1
    The command is fine. Maybe you have some garbage in task_note like escape characters or something. Or a NEWLINE.
    – B Layer
    Commented Aug 26, 2020 at 15:09

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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