From 242dc9dc12b11f38ee3128ff5b30d682c4faa91f Mon Sep 17 00:00:00 2001 From: Alex Vear Date: Fri, 28 Apr 2023 15:17:12 +0100 Subject: [PATCH] Yet more string detection fixes and slight code clean up --- indent/clojure.vim | 47 +++++++++++++++++++++++----------------------- 1 file changed, 24 insertions(+), 23 deletions(-) diff --git a/indent/clojure.vim b/indent/clojure.vim index 1294d0f..42df1de 100644 --- a/indent/clojure.vim +++ b/indent/clojure.vim @@ -45,28 +45,26 @@ function! s:Conf(opt, default) return get(b:, a:opt, get(g:, a:opt, a:default)) endfunction -function! s:ShouldAlignMultiLineStrings() - " Possible Values: (default is 0) - " -1: Indent of 0, along left edge, like traditional Lisps. - " 0: Indent in alignment with string start delimiter. - " 1: Indent in alignment with end of the string start delimiter. - return s:Conf('clojure_align_multiline_strings', 0) +function! s:EqualsOperatorInEffect() + " Returns 1 when the previous operator used is "=" and is currently in + " effect (i.e. "state" includes "o"). + return v:operator ==# '=' && state('o') ==# 'o' endfunction function! s:GetStringIndent(delim_pos, regex) " Mimic multi-line string indentation behaviour in VS Code and Emacs. let m = mode() - if m ==# 'i' || (m ==# 'n' && ! (v:operator ==# '=' && state('o') ==# 'o')) - " If in insert mode, or (in normal mode and last operator is - " not "=" and is not currently active. - let rule = s:ShouldAlignMultiLineStrings() + if m ==# 'i' || (m ==# 'n' && ! s:EqualsOperatorInEffect()) + " If in insert mode, or normal mode but "=" is not in effect. + let rule = s:Conf('clojure_align_multiline_strings', 0) if rule == -1 - return 0 " No indent. + " Indent along left edge, like traditional Lisps. + return 0 elseif rule == 1 - " Align with start of delimiter. + " Indent in alignment with end of the string start delimiter. return a:delim_pos[1] else - " Align with end of delimiter. + " Indent in alignment with string start delimiter. return a:delim_pos[1] - (a:regex ? 2 : 1) endif else @@ -86,27 +84,30 @@ function! s:CheckPair(name, start, end, SkipFn) endif endfunction -function! s:GetClojureIndent() - " Move cursor to the first column of the line we want to indent. - call cursor(v:lnum, 1) - - if empty(getline(v:lnum)) +function! s:GetCurrentSynName(lnum) + if empty(getline(a:lnum)) " Improves the accuracy of string detection when a newline is " entered while in insert mode. - let strline = v:lnum - 1 - let synname = s:GetSynIdName(strline, strlen(getline(strline))) + let strline = a:lnum - 1 + return s:GetSynIdName(strline, strlen(getline(strline))) else - let synname = s:GetSynIdName(v:lnum, 1) + return s:GetSynIdName(a:lnum, 1) endif +endfunction + +function! s:GetClojureIndent() + " Move cursor to the first column of the line we want to indent. + call cursor(v:lnum, 1) let s:best_match = ['top', [0, 0]] + let synname = s:GetCurrentSynName(v:lnum) if synname =~? 'string' + call s:CheckPair('str', '"', '"', function('NotStringDelimiter')) " Sometimes, string highlighting does not kick in correctly, " until after this first "s:CheckPair" call, so we have to " detect and attempt an automatic correction. - call s:CheckPair('str', '"', '"', function('NotStringDelimiter')) - let new_synname = s:GetSynIdName(v:lnum, 1) + let new_synname = s:GetCurrentSynName(v:lnum) if new_synname !=# synname echoerr 'Misdetected string! Retrying...' let s:best_match = ['top', [0, 0]]