0

I've been trying to write a vimscript that reads the output of a shell command (figlet) and comments every line of it. I want to use the &commentstring variable since I want this script to work with any filetype.

So far I have achieved only inconsistent results. Here is and example:

  1. Prompt the user to enter his/her initials and pass that to the shell command figlet to print ascii art at the top of the file:
let g:initials = input('Authors initials: ')
execute '0r! figlet -W ' . toupper(g:initials)

The output is the following (e.g. g:initials = JT):

      _   _____ 
     | | |_   _|
  _  | |   | |  
 | |_| |   | |  
  \___/    |_|  
  1. Get the amount of lines of the output:
let s:line_count = system("figlet -W " . g:signit_initials . "| wc -l")
  1. Use the vim function substitute() to comment every line:
let s:i = 1
while s:i < s:line_count
execute 'silent' . s:i . 's/^.*$/\=substitute(&commentstring, "%s", "\t" . getline(".") . "\t", "")'
let s:i += 1
endwhile

The output is the following:

/*      _   _____ */
/*     | | |_   _|*/
/*  _  | |   | |  */
/* | |_| |   | |  */
/*  ___/    |_|  */

As you can see, it works well until the last line and I dont understand why. Maybe there is a better way to aproach this. Anyways, I would really appriciate if someone would provide me with some help on how to solve this little issue.

1 Answers1

1

it works well until the last line and I dont understand why

The last line contains a backslash. And it gets modified according to :h sub-replace-special. So, at the very least, you must escape it with another one. Sort of escape(getline('.'), '\'). However, for this particular case I'd rather go with printf, as it looks easier and more natural: printf(&cms, "\t"..getline(".").."\t")

Also there's no need for "while" loop, as many commands and functions accept line range: it's both more effective and easier to write.

Maybe there is a better way to aproach this.

IMO this looks better:

call append(0, map(systemlist("figlet -W "..toupper(g:initials)),
    \ {_, v -> printf(&cms, "\t" .. v .. "\t")}))
Matt
  • 13,674
  • 1
  • 18
  • 27
  • Printf works perfect! Thank you! Nevertheless I would like to try your suggested solution. It seems more efficient to map trough a list. However, I dont understand the last line: ```\ {_, v -> printf(&cms, "\t" .. v .. "\t")}))``` Could you maybe explain it? –  Jul 26 '20 at 09:24
  • @johannesthyssen See `:h lambda` – Matt Jul 26 '20 at 09:59
  • got it! Thanks! One last question: Why do you use two dots for concatenation instead of one? –  Jul 26 '20 at 11:02
  • @JohannesThyssen Both work. But one-dot may be ambiguous. This is why `x . y` is strongly preferred over `x.y`. With two-dots you're free to choose between `x..y` and `x .. y`. See also `:h expr5`. – Matt Jul 26 '20 at 11:49