2

I'm trying to figure out how to get vim to correctly indent the next line in a JSX block.

Currently when I press enter, the cursor goes slightly behind where it should be. In the example below, my cursor starts after <Switch>. Then, when I press enter, the cursor is on the next line, but 4 spaces before where it should be.

// This is in a class, in a file foo.js.
render() {
  return (
    <Fragment>
      <Switch>|start
    |got
        |want
      </Switch>
    </Fragment>
  );
}

These are the settings in my vimrc file.

" Global settings.
set autoindent
set shiftwidth=4
set smartindent
set tabstop=4
filetype plugin indent on
syntax off

" Javascript specific settings.
autocmd FileType javascript setlocal tabstop=2 softtabstop=2 shiftwidth=2 expandtab

If I'm not in a JSX block, then the indentation seems to work fine.

constructor(props) {
  super(props);|start
  |got
}

P.D. I'd like to avoid installing a plugin, if possible.

2
  • 2
    I'm not sure I completely follow your desired v. happening behavior, but try not enabling smartindent—it's only good for C-style (brace) languages. You don't want it on globally (and ftplugin indent on should enable it automatically when you need it).
    – D. Ben Knoble
    Oct 8, 2019 at 2:10
  • filetype plugin indent on disables smartindent in this case anyway.
    – romainl
    Jan 14 at 10:52

2 Answers 2

0

You can use the treesitter plugin for this behaviour. Add the following to your configuration.

 require'nvim-treesitter.configs'.setup {
   indent = {
     enable = true,
   },
 }
0

Your foo.js is assigned the javascript filetype while its content is not actually JavaScript. Ideally, your JSX file should have the .jsx extension, which would make Vim assign the theoretically correct javascriptreact filetype.

Now, I wrote "theoretically correct" because Vim indeed has specific filetypes for .jsx and .tsx, javscriptreact and typescriptreact, but those are only stubs that source their javascript and typescript buddies. This has been the case for quite some time and it will stay that way as long as no one steps forward.

Ironically, the getJavascriptIndent() function defined in $VIMRUNTIME/indent/javascript.vim has some logic for JSX, but that logic is only triggered if the current highlight group stack matches the pattern xml\|jsx. Since none of the highlight groups defined in $VIMRUNTIME/syntax/javascript.vim contains the string jsx or xml, the function never takes the jsx path.

From there, you have two paths:

  • report the problem in Vim's issue tracker,
  • look around for an alternative indent script for JSX.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.