4

Hey how can I open vim inside a script?
I need to grade coding assignments and wrote a script to open code and note files, but vim does not open.

The script is essentially a fancier version of this:

#!/bin/bash
echo -e "$student_files" | while read student do
   vim -o $student
done

#each "$student" looks like: "file1 file2 [...] notes"

But vim complains about:

Vim: Warning: Input is not from a terminal
Vim: Error reading input, exiting...
Vim: preserving files...
Vim: Finished.

Can anyone tell me why this is happening and how I could work around it? Thanks in advance :)

note: I tried running vim in a script without a loop, which works, but I don't know why. I suppose its because I'm piping into while

4
  • Yes it's because you are piping to while ... vim is responding to the pipeline as well.
    – bxm
    Nov 6, 2019 at 13:59
  • Is $student_files a variable containing newlines?
    – bxm
    Nov 6, 2019 at 14:08
  • @bxm now I see it. the -e was missing. But the real script contains a sed command, so it works there.
    – iaquobe
    Nov 6, 2019 at 14:35
  • Amended my answer to reflect this new info
    – bxm
    Nov 6, 2019 at 14:41

3 Answers 3

7

Because of the pipeline, standard input is redirected for the while loop; that includes any command that is launched from it, like vim.

As you always want to get input from the terminal there, you can just re-connect to the terminal, /dev/tty:

< /dev/tty vim -o "$student"

Alternatively, stdin could be saved to a file descriptor before going into the pipeline (exec 6<&0) and that passed to Vim (<&6 vim -o ...). (That would also handle the case where a "macro recording" of Vim commands is saved in a file and you wanted to automate Vim itself by piping the recorded input back into it.)

Or you could try to get rid of the pipeline completely, by first reading the entire file contents into a Bash array (readarray), and then using a simple for loop. This would consume more memory, but that shouldn't be a problem here as the limiting factor rather is how many Vim sessions you're willing to handle sequentially :-) Actually, you're not reading from a file here, but from variable contents (which as I understand have space-separated students on potentially multiple lines - the default IFS parsing will split those into individual students), so all you need to do is simple word splitting into a Bash array:

declare -a students=($student_files)
for student in "${students[@]}"
do
    vim -o "$student"
done

or completely skipping the intermediate array:

for student in $student_files
do
    vim -o "$student"
done
1
  • Thanks I really liked your explanation. :) reconnecting to the tty worked.
    – iaquobe
    Nov 6, 2019 at 14:48
0
]# cat filelist 
fsc
out
]# vim -o $(<filelist)
2 files to edit
]# 

...and in between I had these two files "fsc" and "out" stacked in vim.

I used man vim for once.

I had to give up my xterm window after I had tested your script. Even after reset the BS key would only do "^H". So I radically changed.

2
  • This opens the files of all students simultaneously, which is why I need the while loop to edit student by student.
    – iaquobe
    Nov 6, 2019 at 15:03
  • OK...I started out by checking 'vim -o'. I think I see the point now, with ingo's last solution -- it's two-level. thanks!
    – user373503
    Nov 6, 2019 at 15:23
0
declare -a student_array=()
while read line ; do student_array+=("$line") ; done < <(echo -e "$student_array")
for student in "${student_array[@]}" ; do
  vim -o $student
done
3
  • 1
    eval is not needed here (and is best avoided); rather, $student should be quoted. And in Bash 4 you can replace the while loop with readarray Nov 6, 2019 at 14:16
  • I wasn't 100% sure if eval was warranted (you are indeed correct, have removed), but I think if $student were quoted, it would not work. From the limited information given, I'm surmising the pseudo-array being used as input is newline delimited, with space separated items per line. Quoting $student would try to open them as a single file.
    – bxm
    Nov 6, 2019 at 14:25
  • I made some typos which became apparent in testing, edited answer.
    – bxm
    Nov 6, 2019 at 14:31

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .