Search code examples
vimindentation

Make vim properly indent piped while loop


I have been using this line of code for reading ip 1.1.1.1 in ip_list.txt, store in variable line then print out:

if [ true == false ]; then # Example
ip="1.1.1.1"
grep -r $ip ip_list.txt | while read -r line ; do
echo "Line is: $line"
done
fi

Code is working great but vim doesn't indent this code properly. When I do, g=GG, you can see the done syntax should be lined up below grep syntax but it went to the left with if statement. It will indent like this in vim:

if [ true == false ]; then
    ip="1.1.1.1"
    grep -r $ip ip_list.txt | while read -r line ; do
    echo "Line is: $line"
done # Went to the left. Not lined up with grep
fi

Even if I removed the ; , and let the do at the bottom like this:

if [ true == false ]; then # Example
ip="1.1.1.1"
grep -r $ip ip_list.txt | while read -r line
do
echo "Line is: $line"
done
fi

the done syntax still not indent properly in vim code editor (now if I do g=GG):

if [ true == false ]; then
        ip="1.1.1.1"
        grep -r $ip ip_list.txt | while read -r line
do
        echo "Line is: $line"
done # not lined up with grep syntax
fi

Any way to edit this code so vim can indent it properly ?

The expected output should be:

if [ true == false ]; then
    ip="1.1.1.1"
    grep -r $ip ip_list.txt | while read -r line ; do
        echo "Line is: $line"
    done
fi

OR it should be

if [ true == false ]; then
    ip="1.1.1.1"
    grep -r $ip ip_list.txt | while read -r line
    do
        echo "Line is: $line"
    done
fi

Solution

  • vim's indenting regex isn't smart enough for that. You can edit the syntax file yourself if you'd like: use :scriptnames to see the files that get loaded by vim to see the full path of the syntax/sh.vim file.

    A simpler method would be changing your bash syntax:

    if [ true == false ]; then # Example
    ip="1.1.1.1"
    while read -r line; do
    echo "Line is: $line"
    done < <(grep -r $ip ip_list.txt )
    fi
    

    gets correctly indented to

    if [ true == false ]; then # Example
      ip="1.1.1.1"
      while read -r line; do
        echo "Line is: $line"
      done < <(grep -r $ip ip_list.txt )
    fi