Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to change JSX indentation rules in VIM?

Tags:

vim

jsx

Currently, I'm using two plugins to format my JS(X) code in VIM:

  • pangloss/vim-javascript
  • mxw/vim-jsx

Our team has elected that, when we have React Components whose props spill on to multiple lines, we want those properties to line up with the property on the first line, like so:

Desired:

<Toggle label={dragString} toggled={this.props.canDrag} onToggle={this.toggleDrag}
        thumbStyle={toggleStyles.thumbOff}
        thumbSwitchedStyle={toggleStyles.thumbOn}
        trackStyle={toggleStyles.trackOff}
        trackSwitchedStyle={toggleStyles.trackOn}
/>

Instead, it looks like vim-jsx will always indent props on new lines just two spaces (which is what we have our tab size set to):

What actually happens:

<Toggle label={dragString} toggled={this.props.canDrag} onToggle={this.toggleDrag}
  thumbStyle={toggleStyles.thumbOff}
  thumbSwitchedStyle={toggleStyles.thumbOn}
  trackStyle={toggleStyles.trackOff}
  trackSwitchedStyle={toggleStyles.trackOn}
/>

Is there a change I can make in my .vimrc or to the vim-jsx plugin code to make React component props on new lines line up with the prop on the first line?

like image 789
piercebot Avatar asked Sep 19 '25 12:09

piercebot


2 Answers

In my case, I already had indentation working as expected for .js files with this line in my .vimrc:

autocmd FileType javascript setlocal shiftwidth=2 tabstop=2

To get similar behavior in .jsx files, I needed to also add:

autocmd FileType javascriptreact setlocal shiftwidth=2 tabstop=2

You can run :set filetype in vim to display the filetype according to vim; in this case javascriptreact.

like image 124
soulshake Avatar answered Sep 23 '25 12:09

soulshake


Unfortunately, there's no easy way to do this. In Vim, indentation works by invoking an "indent expression" stored in the indentexpr setting. The file that does this for JSX in your plugin is here: https://github.com/mxw/vim-jsx/blob/eb656ed96435ccf985668ebd7bb6ceb34b736213/after/indent/jsx.vim

They define a function, called GetJsxIndent, which either delegates to the XML indent, or to the JS indent, or it does something slightly different. Their particular overrides are here: https://github.com/mxw/vim-jsx/blob/eb656ed96435ccf985668ebd7bb6ceb34b736213/after/indent/jsx.vim#L92-L102

Theoretically, you could make your own changes in that area, check where the properties start in the <Toggle line and align to those, but it might end up being much more complicated than it seems at first glance. For instance, they decrease the indent by a single shiftwidth, if the current line is />. With a change like you're proposing, this won't work -- the /> couldn't look at the previous line, it has to find its starting <.

My suggestion would be to open an issue on the vim-jsx project and ask them to implement this, possibly with a setting to turn it on or off. The alternative would be to fork it yourself and try to apply your workaround, but be prepared for it to take some time and effort.