Giter Club home page Giter Club logo

vim-sh-indent's Introduction

vim-sh-indent Say Thanks!

Official Vim indent script for the shell.

License

The Vim License applies. See :h license

vim-sh-indent's People

Contributors

aswild avatar chrisbra avatar dmitrivereshchagin avatar nhooyr avatar sh1r4s3 avatar wwalker avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

vim-sh-indent's Issues

Comments break indention of associative arrays

Indention in an associative array fails on "local varname=(". That is fixed in PR #28, which is applied before the output shown below.

More importantly, comments, preceded by a blank line, break indention.

stc(){
  local attrs=(
  ["Bold"]="1"    # Bold text only, keep colors
        # this
        ["Bold"]="1"    # Bold text only, keep colors
# Basic         High Intensity   Background        High Intensity Background
["Black"]="30"  ["IBlack"]="90"  ["OnBlack"]="40"  ["OnIBlack"]="100"
)
}

std(){
  local attrs=(
  ["Bold"]="1"    # Bold text only, keep colors

        # this
        ["Bold"]="1"    # Bold text only, keep colors

# Basic         High Intensity   Background        High Intensity Background
["Black"]="30"  ["IBlack"]="90"  ["OnBlack"]="40"  ["OnIBlack"]="100"
)
}

ste(){
  local attrs
  attrs=(
    ["Bold"]="1"    # Bold text only, keep colors

        # this
        ["Bold"]="1"    # Bold text only, keep colors

  # Basic         High Intensity   Background        High Intensity Background
  ["Black"]="30"  ["IBlack"]="90"  ["OnBlack"]="40"  ["OnIBlack"]="100"
)
}

Should render as this:

stc(){
  local attrs=(
    ["Bold"]="1"    # Bold text only, keep colors
    # this
    ["Bold"]="1"    # Bold text only, keep colors
    # Basic         High Intensity   Background        High Intensity Background
    ["Black"]="30"  ["IBlack"]="90"  ["OnBlack"]="40"  ["OnIBlack"]="100"
  )
}

std(){
  local attrs=(
    ["Bold"]="1"    # Bold text only, keep colors

    # this
    ["Bold"]="1"    # Bold text only, keep colors

    # Basic         High Intensity   Background        High Intensity Background
    ["Black"]="30"  ["IBlack"]="90"  ["OnBlack"]="40"  ["OnIBlack"]="100"
  )
}

ste(){
  local attrs
  attrs=(
    ["Bold"]="1"    # Bold text only, keep colors

    # this
    ["Bold"]="1"    # Bold text only, keep colors

    # Basic         High Intensity   Background        High Intensity Background
    ["Black"]="30"  ["IBlack"]="90"  ["OnBlack"]="40"  ["OnIBlack"]="100"
  )
}

However renders like this (this assumes that PR 28 is already applied or it would be worse) :

stc(){
  local attrs=(
    ["Bold"]="1"    # Bold text only, keep colors
    # this
    ["Bold"]="1"    # Bold text only, keep colors
    # Basic         High Intensity   Background        High Intensity Background
    ["Black"]="30"  ["IBlack"]="90"  ["OnBlack"]="40"  ["OnIBlack"]="100"
  )
}

std(){
  local attrs=(
    ["Bold"]="1"    # Bold text only, keep colors

        # this
        ["Bold"]="1"    # Bold text only, keep colors

# Basic         High Intensity   Background        High Intensity Background
["Black"]="30"  ["IBlack"]="90"  ["OnBlack"]="40"  ["OnIBlack"]="100"
)
}

ste(){
  local attrs
  attrs=(
    ["Bold"]="1"    # Bold text only, keep colors

        # this
        ["Bold"]="1"    # Bold text only, keep colors

  # Basic         High Intensity   Background        High Intensity Background
  ["Black"]="30"  ["IBlack"]="90"  ["OnBlack"]="40"  ["OnIBlack"]="100"
)
}

wrong indentation when a command contains the `if`

Formatting breaks with use if keyword sub commands

#!/usr/bin/env bash
if [[ -z "somecondition" ]]; then
  if [[ -z "thircondition" ]]; then
    # below command will also break formatting as it has if keyword
    echo "if in string"
    fi # <--
  fi # <--

Expected
Should ignore if in commands while formatting

Workaround
Add additional fi in comments for getting around if in commands

#!/usr/bin/env bash
if [[ -z "somecondition" ]]; then
  if [[ -z "thircondition" ]]; then
    # below command will also break formatting as it has if keyword
    echo "if in string"
    # fi
    # work around add above comment
  fi
fi

Heredocs unindent all subsequent lines until `}` is consumed

About

When using heredocs, vim-sh-indent unindents all subsequent lines until it sees an end brace (or perhaps some other tokens).

Context

From my NixOS install, in Vim 9.0, I am using /nix/store/5bpa0ciapxw2a05p22finkvsr29rhm05-vim-full-9.0.1441/share/vim/vim90/indent/sh.vim

Steps to Reproduce

  1. Grab the actual result sample code from below
  2. Throw it in a file and format

Actual Result

foo() {
    cat <<EOS
This will break the lines below
EOS

echo "This should be indented properly, but isn't"
echo "All lines until the brace are flushed left"
}

bar() {
    echo "this will work again"
}

Expected Result (diff)

Indentation is resumed after the heredoc delimiting identifier (terminator).

@@ -1,12 +1,12 @@
 foo() {
     cat <<EOS
 This will break the lines below
 EOS
 
-echo "This should be indented properly, but isn't"
-echo "All lines until the brace are flushed left"
+    echo "This should be indented properly, but isn't"
+    echo "All lines until the brace are flushed left"
 }
 
 bar() {
     echo "this will work again"
 }

preserve indentation within heredocs?

Right now, indentation within heredocs appears to be collapsed to 0, e.g. something like this will lose its indentation:

read -r -d '' VARIABLE <<- EOF
(this is
 (some text
  (with funky
   (indentation))))
EOF

Within the heredoc, GetShIndent() returns 0 for each line; however, I think it would be better to just preserve pre-existing indentation within these cases.

We could possibly piggy back on the syntax highlight rules, e.g. something like this could work

" Preserve indentation for heredoc
let Syntax = synIDattr(synID(line("."), col("."), 1), "name")
if Syntax =~ "HereDoc"
    return indent(line("."))
endif

Thoughts?

autoindent during typing un-indents "fi" too far

Regression from ef2e050 which changed to using the searchpair function.

This seems to happen whenever I type fi to end an if statement that's indented.

1 if a; then
2     b
3     if c; then
4         d
5     fi
6 fi

When I type the fi on line 5, it's un-indented back to column 1 (matching the if on line 1) rather than to column 5 (matching the if on line 3).

When typing the fi on line 5, the cursor is in the column with the i character and the backwards searchpair finds the if on line 1 rather than line 3. This is because since the cursor is after the fi, it's found and assumed to be a nested if/fi pair.

The searchpair documentation suggests When searching backwards and {end} is more than one character, it may be useful to put "\zs" at the end of the pattern...
In my tests, it looks like this works, though I'm not totally clear what the \zs does. Somehow it's moving where the start of the pattern is so that the searchpair is able to consider the fi right before cursor not included in the first match.

Here's a patch which I believe fixes the issue.

diff --git a/indent/sh.vim b/indent/sh.vim
index 520d3ee..de88663 100644
--- a/indent/sh.vim
+++ b/indent/sh.vim
@@ -127,7 +127,7 @@ function! GetShIndent()
   " Current line is a endif line, so get indent from start of "if condition" line
   " TODO: should we do the same for other "end" lines?
   if curline =~ '^\s*\%(fi\);\?\s*\%(#.*\)\=$'
-    let previous_line = searchpair('\<if\>', '', '\<fi\>', 'bnW')
+    let previous_line = searchpair('\<if\>', '', '\<fi\>\zs', 'bnW')
     if previous_line > 0
       let ind = indent(previous_line)
     endif

indent misidentifies a command name as an indent expression

If a program name starts with a expression start word ( (if\|then\|do\|else\|elif\|case\|while\|until\|for\|select\|foreach\)\> ) followed by a non word character ( [-,.:/] ) the program name is treated as an indent start:

myfunc(){
  for filename in a b c
  do
    for.script $filename
  done
}

This will improperly indent if then . above is changed to any of these characters at least [-,.:/] admittedly this is uncommon, but I use some other's scripts that start with for- .

I'm a newb at viml.

It looks like a simple fix.

I'll open a PR immediately.

File output redirect after a backslash breaks indentation

About

If you break a line with backslash to, for example, keep line lengths in order, and then follow that with a file output redirect (>), then the vim-sh-indent plugin stays a level too high on the following indents.

I've prepared a small example below, but this is messing up a very large file, so it doesn't really "iron itself out" at any point.

Context

From my NixOS install, in Vim 9.0, I am using /nix/store/5bpa0ciapxw2a05p22finkvsr29rhm05-vim-full-9.0.1441/share/vim/vim90/indent/sh.vim which appears to be this repo (:wave: hello!)

Steps to Reproduce

  1. Grab the actual result sample code from below
  2. Throw it in a file and format

Actual Result

breakIndentation() {
    echo hello \
        > /dev/null
    }

    wrong(){
        echo "Wrong formatting"
    }

Expected Result

 breakIndentation() {
     echo hello \
         > /dev/null
-    }
+}
 
 wrong(){
     echo "Wrong formatting"
 }

Wrong indentation after nested curly brackets

Hi,

in shell scripts curly brackets are used to group commands (the body of a function is a particular case of a group), and they can be nested.

It looks like vim-sh-indent does not handle indentation after nested braces correctly, see this example:

#!/bin/sh

test() {
  echo "something"

  {
    echo "more"
    echo "even more"
  } | tee /dev/null

  echo "last"
}

It gets indented as:

#!/bin/sh

test() {
  echo "something"

  {
    echo "more"
    echo "even more"
  } | tee /dev/null

echo "last"
}

Commands after the nested braces have wrong indentation.

Ciao,
Antonio

Slow indentation for case statement

I experience very slow indentation especially when there is a case statement with many branches. Is there any performance bug in vim-sh-indent? Thanks.

Indentation issue with if statements that have a semicolon on their closing 'fi'

Looks like ef2e050 didnt 100% fix the indentation issue for if statements that have a semicolon on their closing 'fi'.
Example:
Before indent:

#!/bin/bash
if [ "$1" == "test" ];
then
echo "$1";
fi;
if [ "$1" == "1" ];
then
echo "test";
fi;
if [ "$2" == "2" ];
then
echo "test";
fi;

After indent with closing semicolons on 'fi'.

#!/bin/bash
if [ "$1" == "test" ];
then
  echo "$1";
  fi;
  if [ "$1" == "1" ];
  then
    echo "test";
    fi;
    if [ "$2" == "2" ];
    then
      echo "test";
      fi;

After indent without closing semicolons on 'fi'.

#!/bin/bash
if [ "$1" == "test" ];
then
  echo "$1";
fi
if [ "$1" == "1" ];
then
  echo "test";
fi
if [ "$2" == "2" ];
then
  echo "test";
fi

Let me know if you need any other information.

sh-indent affecting indentation in C code.

## Can you please guide how we could restrict the effect to shell [sh,ksh,bash,zsh,tcsh] scripts only ?

When I put sh.vim in ~/.vimrc/plugin/, indentation for sh files works perfect.
However indentation in C files goes on toss.

Steps:

  1. Open file in vim
  2. gg Shit+V Shitf+G =

Expected file:

#include <unistd.h>
int main()
{
    pid_t pid, sid;

    /* Fork off the parent process */
    pid = fork();
    if (pid <= -1)
    {
        /* exit(EXIT_FAILURE); */
    }
}
// vi: ft=c

What I get:

#include <unistd.h>
int main()
{
    pid_t pid, sid;

    /* Fork off the parent process */
    pid = fork();
    if (pid <= -1)
        {
            /* exit(EXIT_FAILURE); */
        }
    }
    // vi: ft=c

Bash function with a one-letter name are wrongly indented

Hi,

function names can be also one-letter.

In case of a bash-style function definition, vim-sh-indent indents the function body incorrectly, see this example:

#!/bin/bash

function g {
  grep --color=always -nre "$1" ./*
}

It gets indented as:

#!/bin/bash

function g {
grep --color=always -nre "$1" ./*
}

The function body is wrongly indented, maybe the indent script fails to recognize that this is a function definition?

The standard syntax for function definition does not present this problem:

#!/bin/sh

g() {
  grep --color=always -nre "$1" ./*
}

I was wondering, are function bodies handled explicitly or are they treated as general groups of commands?

Thanks, Antonio

subshells in functions are indented improperly

Expected indention:

# make the actual i3 config file from pieces
#
mki3conf(){
  (
    cd ~/.config/i3 || return
    make && i3-msg reload
  )
}

(
  cd ~/.config/i3 || return
  make && i3-msg reload
)

(
  (
    cd ~/.config/i3 || return
    make && i3-msg reload
  )
)

Actual indention

# make the actual i3 config file from pieces
#
mki3conf(){
  (
  cd ~/.config/i3 || return
  make && i3-msg reload
)
}

(
cd ~/.config/i3 || return
make && i3-msg reload
)

(
(
cd ~/.config/i3 || return
make && i3-msg reload
)
)

Multi-line array variable in bash with filetype sh does not indent correctly

I have the following bash array after automatic indentation, both on pressing carriage return when was editing in :h Insert mode and doing =ip on the block in :h Normal-mode

DOTFILES=(
".bashrc"
".bash_profile"
".gitconfig"
".profile"
)

Trying with nvim -u NORC yielded the same result, so I'm guessing it's the default /usr/share/nvim/runtime/indent/sh.vim indent file in action. Output of :set ft? is filetype=sh.

I would like to have the aforementioned array with the following indentation:

DOTFILES=(
	".bashrc"
	".bash_profile"
	".gitconfig"
	".profile"
)

How do I do that?

[Wrong indent for keyword like 'do']

After type word like docker which have the keyword do, the indent will deleted incorrectly.

hello() {
docker
}

Maybe the keyword like do indention should be checked after newline inserted.

Indention broken

This is using the tag 20190202.

Create a file with the following, and re-indent with gg=G:

#!/bin/sh

if [[ /bin/true ]]; then
        echo "true"
else
        echo "false"
        if [[ /bin/false ]]; then
                echo "false"
        else
                echo "true"
        fi
        fi
        if [[ /bin/true ]]
        then
                echo "true"
        else
                echo "false"
                if [[ /bin/false ]]
                then
                        echo "false"
                else
                        echo "true"
        fi
        fi

Bad "if" indent when a command option contains the word "if"

It seems that having options containing the word if breaks the indentation :

if true; then
    if false; then
        cmd with --if-option
    fi
fi

indents as :

if true; then
    if false; then
        cmd with --if-option
        fi
    fi

It is related to the previous issue #20 , and from what I tested, tweaking the regex in the call to searchpair to something like '[^-]\<if\>' instead of '\<if\>' fixes the issue. I do not know if it breaks things elsewhere though.

To be more precise, I am not sure if the difference between the character set of '\<' and the token separators used by the shell parser is restricted to -, otherwise, the issue would arise for all characters in that set.

EDIT: as we could have expected, it also fails with options containing --fi :

if true; then
    if false; then
        cmd with --fi-option
fi
fi

Using the same trick on the end part of searchpair() ('\<fi\>\zs' --> '[^-]\<fi\>\zs') fixes this behaviour.

EDIT 2: I also noticed that the same behaviour appears when a comment ends with fi :

if true; then
    if false; then
        # fi
fi
fi

This seems to be caused by the use of the '\zs' character at the end of the end string, which puts the cursor at the end instead of the beginning. I think it causes the cursor to be positioned after the last character of the line, thus the syntax name is not retrieved correctly, and the comment is not detected.

wrong indentation when a comment contains the `if` keyword inside an `if` block

Consider this bash script written in /tmp/sh.sh:

#!/bin/bash

func() {
  if 1; then
    # a comment containing the if keyword
    echo
  else
    echo
  fi
}

If I start Vim like this:

$ vim -Nu NONE --cmd 'filetype indent on' /tmp/sh.sh

And press =G while the cursor is on the first line, the buffer becomes:

#!/bin/bash

func() {
        if 1; then
                # a comment containing the if keyword
                echo
        else
                echo
                fi
        }

If I remove the if keyword in the comment:

#!/bin/bash

func() {
  if 1; then
    # a comment containing the keyword
    echo
  else
    echo
  fi
}

Pressing =G while the cursor is on the first line indents the buffer like this:

#!/bin/bash

func() {
        if 1; then
                # a comment containing the keyword
                echo
        else
                echo
        fi
}

I would expect the indentation to be identical in both cases.
The last one seems better.
The first one gives 2 levels of indentation for the fi line (instead of 1), and 1 level of indentation for the closing bracket (instead of 0).

On master and 20191024 , Test 01 fails

This is what I have so far...

This failure:

2020-07-31 00:21:16 - wwalker@polonium:~/mine/vim-sh-indent (issue-33 % u= upstream/master) โœ“ $ make test
cd test && ./test.sh -v && cd .. && echo "cleaning output" && make clean > /dev/null
/home/wwalker/mine/vim-sh-indent/test
/home/wwalker/mine/vim-sh-indent/test/01
Test 01:                [Failed]
--- output.sh   2020-07-31 00:21:19.158664748 -0500
+++ reference.sh        2020-07-31 00:19:49.970400183 -0500
@@ -93,7 +93,7 @@

 cd build || {
   echo "Failed to move to build directory"
-exit 1
+  exit 1
 }

 echo this example below works
/home/wwalker/mine/vim-sh-indent/test/02
Test 02:                [OK]

Is caused by this change:

--- indent/sh.vim
+++ indent/sh.vim
@@ -120,7 +120,7 @@ function! GetShIndent()
     while !s:is_empty(getline(i)) && i > pnum
       let i -= 1
     endw
-    if i == pnum
+    if i == pnum && s:is_continuation_line(line)
       let ind += ind2
     else
       let ind = ind2

Undoing that change breaks test 14.

indentation within braced expressions?

With bash, it can be useful to handle expressions that return a non-zero exit code with something like (silly but illustrative example):

cd build || {
    echo "Failed to move to build directory"
    exit 1
}

However, this is currently indented as (using two examples)

cd build || {
    echo "Failed to move to build directory"
exit 1
}

Can the indentation be made uniform for this case?

On master and 20191024 , Test 04 fails

Test 04 fails, but I believe the behavior is correct, and that the test is broken:

/home/wwalker/mine/vim-sh-indent/test/04
Test 04:                [Failed]
--- output.sh   2020-07-30 23:34:19.902698009 -0500
+++ reference.sh        2020-07-30 19:47:52.447082642 -0500
@@ -1,10 +1,10 @@
 #!/bin/sh

 DOTFILES=(
-  ".bashrc"
-  ".bash_profile"
-  ".gitconfig"
-  ".profile"
+".bashrc"
+".bash_profile"
+".gitconfig"
+".profile"
 )

 if true; then
/home/wwalker/mine/vim-sh-indent/test/05
Test 05:                [OK]

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.