Mercurial > vim
view runtime/indent/hare.vim @ 34493:1fa23ccd6d9a v9.1.0153
patch 9.1.0153: Text properties corrupted with fo+=aw and backspace
Commit: https://github.com/vim/vim/commit/7ac1145fbebb66dfee325dc5265309877d941c4e
Author: zeertzjq <zeertzjq@outlook.com>
Date: Wed Mar 6 20:54:22 2024 +0100
patch 9.1.0153: Text properties corrupted with fo+=aw and backspace
Problem: Text properties corrupted with fo+=aw and backspace
Solution: Allocate line and move text properties
(zeertzjq)
closes: #14147
Signed-off-by: zeertzjq <zeertzjq@outlook.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
author | Christian Brabandt <cb@256bit.org> |
---|---|
date | Wed, 06 Mar 2024 21:00:11 +0100 |
parents | 5c220cf30f1f |
children | ea0402ba92f6 |
line wrap: on
line source
" Vim indent file " Language: Hare " Maintainer: Amelia Clarke <me@rsaihe.dev> " Last Change: 2022 Sep 22 " 2023 Aug 28 by Vim Project (undo_indent) if exists("b:did_indent") finish endif let b:did_indent = 1 if !has("cindent") || !has("eval") finish endif setlocal cindent " L0 -> don't deindent labels " (s -> use one indent after a trailing ( " m1 -> if ) starts a line, indent it the same as its matching ( " ks -> add an extra indent to extra lines in an if expression or for expression " j1 -> indent code inside {} one level when in parentheses " J1 -> see j1 " *0 -> don't search for unclosed block comments " #1 -> don't deindent lines that begin with # setlocal cinoptions=L0,(s,m1,ks,j1,J1,*0,#1 " Controls which keys reindent the current line. " 0{ -> { at beginning of line " 0} -> } at beginning of line " 0) -> ) at beginning of line " 0] -> ] at beginning of line " !^F -> <C-f> (not inserted) " o -> <CR> or `o` command " O -> `O` command " e -> else " 0=case -> case setlocal indentkeys=0{,0},0),0],!^F,o,O,e,0=case setlocal cinwords=if,else,for,switch,match setlocal indentexpr=GetHareIndent() let b:undo_indent = "setl cin< cino< cinw< inde< indk<" function! FloorCindent(lnum) return cindent(a:lnum) / shiftwidth() * shiftwidth() endfunction function! GetHareIndent() let line = getline(v:lnum) let prevlnum = prevnonblank(v:lnum - 1) let prevline = getline(prevlnum) let prevprevline = getline(prevnonblank(prevlnum - 1)) " This is all very hacky and imperfect, but it's tough to do much better when " working with regex-based indenting rules. " If the previous line ended with =, indent by one shiftwidth. if prevline =~# '\v\=\s*(//.*)?$' return indent(prevlnum) + shiftwidth() endif " If the previous line ended in a semicolon and the line before that ended " with =, deindent by one shiftwidth. if prevline =~# '\v;\s*(//.*)?$' && prevprevline =~# '\v\=\s*(//.*)?$' return indent(prevlnum) - shiftwidth() endif " TODO: The following edge-case is still indented incorrectly: " case => " if (foo) { " bar; " }; " | // cursor is incorrectly deindented by one shiftwidth. " " This only happens if the {} block is the first statement in the case body. " If `case` is typed, the case will also be incorrectly deindented by one " shiftwidth. Are you having fun yet? " Deindent cases. if line =~# '\v^\s*case' " If the previous line was also a case, don't do any special indenting. if prevline =~# '\v^\s*case' return indent(prevlnum) end " If the previous line was a multiline case, deindent by one shiftwidth. if prevline =~# '\v\=\>\s*(//.*)?$' return indent(prevlnum) - shiftwidth() endif " If the previous line started a block, deindent by one shiftwidth. " This handles the first case in a switch/match block. if prevline =~# '\v\{\s*(//.*)?$' return FloorCindent(v:lnum) - shiftwidth() end " If the previous line ended in a semicolon and the line before that wasn't " a case, deindent by one shiftwidth. if prevline =~# '\v;\s*(//.*)?$' && prevprevline !~# '\v\=\>\s*(//.*)?$' return FloorCindent(v:lnum) - shiftwidth() end let l:indent = FloorCindent(v:lnum) " If a normal cindent would indent the same amount as the previous line, " deindent by one shiftwidth. This fixes some issues with `case let` blocks. if l:indent == indent(prevlnum) return l:indent - shiftwidth() endif " Otherwise, do a normal cindent. return l:indent endif " Don't indent an extra shiftwidth for cases which span multiple lines. if prevline =~# '\v\=\>\s*(//.*)?$' && prevline !~# '\v^\s*case\W' return indent(prevlnum) endif " Indent the body of a case. " If the previous line ended in a semicolon and the line before that was a " case, don't do any special indenting. if prevline =~# '\v;\s*(//.*)?$' && prevprevline =~# '\v\=\>\s*(//.*)?$' && line !~# '\v^\s*}' return indent(prevlnum) endif let l:indent = FloorCindent(v:lnum) " If the previous line was a case and a normal cindent wouldn't indent, indent " an extra shiftwidth. if prevline =~# '\v\=\>\s*(//.*)?$' && l:indent == indent(prevlnum) return l:indent + shiftwidth() endif " If everything above is false, do a normal cindent. return l:indent endfunction " vim: tabstop=2 shiftwidth=2 expandtab