Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Solution for indentation? #4

Open
dakom opened this issue Apr 20, 2018 · 13 comments
Open

Solution for indentation? #4

dakom opened this issue Apr 20, 2018 · 13 comments

Comments

@dakom
Copy link

dakom commented Apr 20, 2018

Hi ... I see this plugin is all about highlighting, but I'm wondering if you have a recommended solution for indentation too?

@peitalin
Copy link
Owner

peitalin commented Apr 30, 2018

Are you talking about the indent lines? https://github.com/nathanaelkane/vim-indent-guides

Otherwise I'm just using default indenting rules in .vimrc:
filetype plugin indent on

@vjsingh
Copy link

vjsingh commented Jun 27, 2018

I think he means that vim-jsx supports indenting rules. It appears that this package doesn't?

And indeed, I'm not getting correct indentation levels for my JSX inside typescript.

EDIT: This seems to work fairly well after simply copying the indent file from vim-jsx

@peitalin
Copy link
Owner

Thanks @vjsingh good to know.

@gbishop
Copy link

gbishop commented Jul 6, 2018

@vjsingh where did you put that indent file? Down in ~/.vim/bundle/vim-jsx-typescript/after?

@vjsingh
Copy link

vjsingh commented Jul 7, 2018

@gbishop I put it in ~/.vim/bundle/vim-jsx-typescript/after/indent/jsx.vim

Using it for a bit though, my indenting has gotten a bit wonky. I think that may be the issue so I'm not sure I can recommend it.

@gbishop
Copy link

gbishop commented Jul 7, 2018 via email

@vjsingh
Copy link

vjsingh commented Jul 7, 2018

Yep. A stable solution would be super nice. Unfortunately I don't know very much about vim indentation configuration. It seems like that indent file is almost working. It seems to detect JSX well, but messes with the indentation elsewhere in the file, somewhat randomly

@garybernhardt
Copy link

It's been almost a year since the last comment here, so... has anyone come up with a solution for tsx indentation in vim? It's still quite a sore point when using them together.

@thejohnfreeman
Copy link

I started using Prettier in all my projects. 🤷‍♂

@skylarmb
Copy link

skylarmb commented Oct 3, 2019

Bump on this, wonky indentation is very annoying. Running Prettier just to fix all this bad indentation

@chemzqm
Copy link
Contributor

chemzqm commented Dec 11, 2019

If you want better indentexpr for tsx files, replace after/indent/tsx.vim with:

let b:did_indent = 1

if !exists('*GetTypescriptIndent') | finish | endif

setlocal indentexpr=GetTsxIndent()
setlocal indentkeys=0{,0},0),0],0\,,!^F,o,O,e,*<Return>,<>>,<<>,/

if exists('*shiftwidth')
  function! s:sw()
    return shiftwidth()
  endfunction
else
  function! s:sw()
    return &sw
  endfunction
endif

let s:real_endtag = '\s*<\/\+[A-Za-z]*>'
let s:return_block = '\s*return\s\+('
function! s:SynSOL(lnum)
  return map(synstack(a:lnum, 1), 'synIDattr(v:val, "name")')
endfunction

function! s:SynEOL(lnum)
  let lnum = prevnonblank(a:lnum)
  let col = strlen(getline(lnum))
  return map(synstack(lnum, col), 'synIDattr(v:val, "name")')
endfunction

function! s:SynAttrJSX(synattr)
  return a:synattr =~ "^tsx"
endfunction

function! s:SynXMLish(syns)
  return s:SynAttrJSX(get(a:syns, -1))
endfunction

function! s:SynJSXDepth(syns)
  return len(filter(copy(a:syns), 'v:val ==# "tsxRegion"'))
endfunction

function! s:SynJSXCloseTag(syns)
  return len(filter(copy(a:syns), 'v:val ==# "tsxCloseTag"'))
endfunction

function! s:SynJsxEscapeJs(syns)
  return len(filter(copy(a:syns), 'v:val ==# "tsxJsBlock"'))
endfunction

function! s:SynJSXContinues(cursyn, prevsyn)
  let curdepth = s:SynJSXDepth(a:cursyn)
  let prevdepth = s:SynJSXDepth(a:prevsyn)

  return prevdepth == curdepth ||
      \ (prevdepth == curdepth + 1 && get(a:cursyn, -1) ==# 'tsxRegion')
endfunction

function! GetTsxIndent()
  let cursyn  = s:SynSOL(v:lnum)
  let prevsyn = s:SynEOL(v:lnum - 1)
  let nextsyn = s:SynEOL(v:lnum + 1)
  let currline = getline(v:lnum)

  if ((s:SynXMLish(prevsyn) && s:SynJSXContinues(cursyn, prevsyn)) || currline =~# '\v^\s*\<')
    let preline = getline(v:lnum - 1)

    if currline =~# '\v^\s*\/?\>' " /> > 
      return preline =~# '\v^\s*\<' ? indent(v:lnum - 1) : indent(v:lnum - 1) - s:sw()
    endif

    if preline =~# '\v\{\s*$' && preline !~# '\v^\s*\<'
      return currline =~# '\v^\s*\}' ? indent(v:lnum - 1) : indent(v:lnum - 1) + s:sw()
    endif

    " return (      | return (     | return (
    "   <div></div> |   <div       |   <div
    "     {}        |     style={  |     style={
    "   <div></div> |     }        |     }
    " )             |     foo="bar"|   ></div>
    if preline =~# '\v\}\s*$'
      if currline =~# '\v^\s*\<\/'
        return indent(v:lnum - 1) - s:sw()
      endif
      let ind = indent(v:lnum - 1)
      if preline =~# '\v^\s*\<'
        let ind = ind + s:sw()
      endif
      if currline =~# '\v^\s*\/?\>'
        let ind = ind - s:sw()
      endif
      return ind
    endif

    " return ( | return (
    "   <div>  |   <div>
    "   </div> |   </div>
    " ##);     | );
    if preline =~# '\v(\s?|\k?)\($' || preline =~# '\v^\s*\<\>'
      return indent(v:lnum - 1) + s:sw()
    endif

    let ind = s:XmlIndentGet(v:lnum)

    " <div           | <div
    "   hoge={       |   hoge={
    "   <div></div>  |   ##<div></div>
    if s:SynJsxEscapeJs(prevsyn) && preline =~# '\v\{\s*$'
      let ind = ind + s:sw()
    endif

    " />
    if preline =~# '\v^\s*\/?\>$' || currline =~# '\v^\s*\<\/\>'
      "let ind = currline =~# '\v^\s*\<\/' ? ind : ind + s:sw()
      let ind = ind + s:sw()
    " }> or }}\> or }}>
    elseif preline =~# '\v^\s*\}?\}\s*\/?\>$'
      let ind = ind + s:sw()
    " ></a
    elseif preline =~# '\v^\s*\>\<\/\a'
      let ind = ind + s:sw()
    elseif preline =~# '\v^\s*}}.+\<\/\k+\>$'
      let ind = ind + s:sw()
    endif

    " <div            | <div
    "   hoge={        |   hoge={
    "     <div></div> |     <div></div>
    "     }           |   }##
    if currline =~# '}$' && !(currline =~# '\v\{')
      let ind = ind - s:sw()
    endif

    if currline =~# '^\s*)' && s:SynJSXCloseTag(prevsyn)
      let ind = ind - s:sw()
    endif
  else
    let ind = GetTypescriptIndent()
  endif
  return ind
endfunction

let b:xml_indent_open = '.\{-}<\a'
let b:xml_indent_close = '.\{-}</'

function! s:XmlIndentWithPattern(line, pat)
  let s = substitute('x'.a:line, a:pat, "\1", 'g')
  return strlen(substitute(s, "[^\1].*$", '', ''))
endfunction

" [-- return the sum of indents of a:lnum --]
function! s:XmlIndentSum(lnum, style, add)
  let line = getline(a:lnum)
  if a:style == match(line, '^\s*</')
    return (&sw *
          \  (s:XmlIndentWithPattern(line, b:xml_indent_open)
          \ - s:XmlIndentWithPattern(line, b:xml_indent_close)
          \ - s:XmlIndentWithPattern(line, '.\{-}/>'))) + a:add
  else
    return a:add
  endif
endfunction

function! s:XmlIndentGet(lnum)
  " Find a non-empty line above the current line.
  let lnum = prevnonblank(a:lnum - 1)

  " Hit the start of the file, use zero indent.
  if lnum == 0 | return 0 | endif

  let ind = s:XmlIndentSum(lnum, -1, indent(lnum))
  let ind = s:XmlIndentSum(a:lnum, 0, ind)
  return ind
endfunction

@SamCB
Copy link

SamCB commented Jan 11, 2020

@peitalin, would you consider using @chemzqm's solution? The existing indenting is not behaving well.

Some simple problems to demonstrate behavior:

Example 1

const example = (
  <div></div>
);

Hitting return between the two <div> tags results in this:

const example = (
  <div>
    </div>
);

When i would expect it to behave like this:

const example = (
  <div>
  </div>
);

Example 2

const example = (
  <div></div>);

A return before the closing bracket leads to:

const example = (
  <div></div>
    );

When I would expect:

const example = (
  <div></div>
);

I haven't looked to deeply myself, but it does appear that @chemzqm's solution does fix these cases.

@peitalin
Copy link
Owner

@SamCB
I've tested and merged @chemzqm's solution for indentation in the latest commit.
Thanks for the suggestions @chemzqm.

I'll keep this thread open in case theres any other issues to do with indentation.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

9 participants