vim-jsx-typescript icon indicating copy to clipboard operation
vim-jsx-typescript copied to clipboard

Solution for indentation?

Open dakom opened this issue 6 years ago • 13 comments

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

dakom avatar Apr 20 '18 07:04 dakom

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

peitalin avatar Apr 30 '18 04:04 peitalin

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

vjsingh avatar Jun 27 '18 23:06 vjsingh

Thanks @vjsingh good to know.

peitalin avatar Jun 29 '18 10:06 peitalin

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

gbishop avatar Jul 06 '18 14:07 gbishop

@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.

vjsingh avatar Jul 07 '18 14:07 vjsingh

Thanks. I'm still looking for a stable solution. I'd go back to plain old autoindent if I could figure out how to disable all the smartness.

On Sat, Jul 7, 2018 at 10:32 AM Varun Singh [email protected] wrote:

@gbishop https://github.com/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.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/peitalin/vim-jsx-typescript/issues/4#issuecomment-403219703, or mute the thread https://github.com/notifications/unsubscribe-auth/AAMFfHDWUArv9siFyS4ijid-om-a9Vydks5uEMZ6gaJpZM4TdBmd .

gbishop avatar Jul 07 '18 14:07 gbishop

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

vjsingh avatar Jul 07 '18 14:07 vjsingh

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.

garybernhardt avatar Jun 12 '19 23:06 garybernhardt

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

thejohnfreeman avatar Jun 12 '19 23:06 thejohnfreeman

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

skylarmb avatar Oct 03 '19 23:10 skylarmb

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

chemzqm avatar Dec 11 '19 12:12 chemzqm

@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.

SamCB avatar Jan 11 '20 13:01 SamCB

@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.

peitalin avatar Jan 12 '20 05:01 peitalin