0

In VIM, for every letter of the English alphabet, I want to insert a line in the following format:

fragment {upper(letter)}: '{lower(letter)}' | '{upper(letter)'};

So, for example, for the letter a, it would be:

fragment A: 'a' | 'A';

Writing 26 lines like this is tedious, and you shouldn't repeat yourself. How can I do that?

Amir A. Shabani
  • 2,701
  • 3
  • 21
  • 46

2 Answers2

3

In vim:

for i in range(65,90) " ASCII codes
  let c = nr2char(i)  " Character
  echo "fragment" c ": '"tolower(c)"' | '" c "';"
endfor

Or as a oneliner:

:for i in range(65,90) | let c = nr2char(i) | echo "fragment" c ": '"tolower(c)"' | '" c "';" | endfor
fragment A : ' a ' | ' A ';
fragment B : ' b ' | ' B ';
fragment C : ' c ' | ' C ';
...
fragment X : ' x ' | ' X ';
fragment Y : ' y ' | ' Y ';
fragment Z : ' z ' | ' Z ';

Use :redir @a to copy that output to register a.

steffen
  • 13,255
  • 2
  • 36
  • 69
1

Here's one way.

First, I'm gonna create the text in bash with a single command, then I'll tell VIM to insert the output of that command into the file.

I need to iterate through English alphabets, and for every letter, echo one line in the specified format. So at first, let's just echo each letter in a single line (By using a for loop):

❯ alphabets="abcdefghijklmnopqrstuvwxyz"
❯ for ((i=0; i<${#alphabets}; i++)); do echo "${alphabets:$i:1}"; done
a
b
...
z

The way this works is:

  • ${#alphabets} is equal to the length of the variable alphabets.
  • ${alphabets:$i:1} extracts the letter at position i from the variable alphabets (zero-based).

Now we need to convert these letters to upper case. Here's one way we can achieve this:

❯ echo "a" | tr a-z A-Z
A

Now if we apply this to the for loop we had, we get this:

❯ for ((i=0; i<${#alphabets}; i++)); do echo "${alphabets:$i:1}" | tr a-z A-Z; done 
A
B
...
Z

From here, it's quite easy to produce the text we wanted:

❯ for ((i=0; i<${#alphabets}; i++)); do c="${alphabets:$i:1}"; cap=$(echo "${c}" | tr a-z A-Z); echo "fragment ${cap}: '${c}' | '${cap}';"; done 
fragment A: 'a' | 'A';
fragment B: 'b' | 'B';
...
fragment Z: 'z' | 'Z';

Now that we generated the text, we can simply use :r !command to insert the text into vim:

:r !alphabets="abcdefghijklmnopqrstuvwxyz"; for ((i=0; i<${\#alphabets}; i++)); do c="${alphabets:$i:1}"; cap=$(echo "${c}" | tr a-z A-Z); echo "fragment ${cap}: '${c}' | '${cap}';"; done

Note that # is a special character in vim and should be spaced using \.

Here's another one-liner that does the same thing, and I believe is more intuitive:

for c in {a..z}; do u=$(echo ${c} | tr a-z A-Z); echo "fragment ${u}: '${c}' | '${u}';"; done
Amir A. Shabani
  • 2,701
  • 3
  • 21
  • 46