aboutsummaryrefslogtreecommitdiff
path: root/vim
diff options
context:
space:
mode:
authorTom Ryder <tom@sanctum.geek.nz>2022-05-05 01:31:29 +1200
committerTom Ryder <tom@sanctum.geek.nz>2022-05-05 01:31:29 +1200
commit7809f6447b49be28e2cdaae02da66d79f6598146 (patch)
treebd901e25bdab99e2f519d63eb3ebdbee17220943 /vim
parentAdd checking, tidying, and linting for Python (diff)
downloaddotfiles-7809f6447b49be28e2cdaae02da66d79f6598146.tar.gz
dotfiles-7809f6447b49be28e2cdaae02da66d79f6598146.zip
Add lang=-to-'spelllang' hooks for HTML filetype
Diffstat (limited to 'vim')
-rw-r--r--vim/after/ftplugin/html.vim18
-rw-r--r--vim/autoload/html/spelllang.vim57
2 files changed, 75 insertions, 0 deletions
diff --git a/vim/after/ftplugin/html.vim b/vim/after/ftplugin/html.vim
index 21a84a42..741f7b65 100644
--- a/vim/after/ftplugin/html.vim
+++ b/vim/after/ftplugin/html.vim
@@ -32,6 +32,24 @@ augroup END
let b:undo_ftplugin .= '|execute ''autocmd! html_timestamp'''
\ . '|augroup! html_timestamp'
+" Set up hooks for divining 'spelllang' from lang= attributes
+augroup html_spelllang
+ if exists('##TextChanged')
+ autocmd TextChanged *
+ \ if &modified
+ \| call html#spelllang#Set()
+ \|endif
+ else
+ autocmd InsertLeave *
+ \ if &modified
+ \| call html#spelllang#Set()
+ \|endif
+ endif
+augroup END
+call html#spelllang#Set()
+let b:undo_ftplugin .= '|execute ''autocmd! html_spelllang'''
+ \ . '|augroup! html_spelllang'
+
" Stop here if the user doesn't want ftplugin mappings
if exists('no_plugin_maps') || exists('no_html_maps')
finish
diff --git a/vim/autoload/html/spelllang.vim b/vim/autoload/html/spelllang.vim
new file mode 100644
index 00000000..c01a57b2
--- /dev/null
+++ b/vim/autoload/html/spelllang.vim
@@ -0,0 +1,57 @@
+" Crude regular expression to match an <html> or <body> tag on one line with
+" a lang= attribute set. This isn't exact, by any means, but I don't want to
+" write an actual HTML parser for a mere 'spelllang' hook nicety that fails
+" silently anyway.
+"
+" The first submatch is the language code, e.g. "en", "es". The second
+" submatch is optional and follows a hyphen and is for the regional code,
+" e.g. "US", "GB", "AR".
+"
+let s:pattern = '\m\c<\%(html\|body\)\>[^>]*\<lang=["'']\='
+ \ . '\([a-z-]\{2,}\)\%(-\([a-z]\{2,}\)\)'
+
+" The line count limit for looking for the pattern; no sense churning through
+" the whole document every time it's changed.
+"
+let s:lines = 128
+
+" Look for a language code in the first lines of the current buffer, and if it
+" looks understandable, adopt an appropriate spelling language.
+"
+function! html#spelllang#Set() abort
+
+ " Loop through the first s:lines of the buffer
+ for line in getline(1, s:lines)
+
+ " Check if this line has an <html lang=""> tag, or skip it
+ let matches = matchlist(line, s:pattern)
+ if empty(matches)
+ continue
+ endif
+
+ " The line seems to match our pattern, and so we have a language code in
+ " matches[1], and possibly a region code in matches[2].
+ "
+ " Next we need to check whether we'll attempt to use this to set
+ " a spelling language. Build the expected path for a spellfile; looks
+ " like `$VIMRUNTIME/spell/en.utf-8.spl`. Note that this path doesn't
+ " include any language region, per documentation.
+ "
+ let spellfile = 'spell/' . join([
+ \ tolower(matches[1]),
+ \ &encoding,
+ \ 'spl',
+ \], '.')
+
+ " If a spelling list file of the expected name exists in &runtimepath, try
+ " setting the local value of 'spelllang' to reflect what was in the lang=
+ " attribute; force it to lowercase and separate the region with an
+ " underscore rather than a hyphen (if there is a region).
+ "
+ if strlen(globpath(&runtimepath, spellfile))
+ let &l:spelllang = tolower(join(matches[1:2], '_'))
+ endif
+
+ endfor
+
+endfunction