Open dpc opened 5 years ago
I agree we should have a :spell-selection
that would only spell check the selection (and :spell
would just select the whole buffer and run that).
I got an implementation going, but the issue is that aspell
returns coordinates within a selection, and adding the right offsets to align those coordinates within the buffer space is tricky.
diff --git a/rc/base/spell.kak b/rc/base/spell.kak
index 10c0f915..574d2e39 100644
--- a/rc/base/spell.kak
+++ b/rc/base/spell.kak
@@ -1,25 +1,26 @@
declare-option -hidden range-specs spell_regions
declare-option -hidden str spell_lang
-declare-option -hidden str spell_tmp_file
+declare-option -hidden str spell_tmp_dir
+
+define-command -params ..1 -docstring %{
+spell-selection [<language>]: spell-check the current selection
+The first optional argument is the language against which the check will be performed, as described by the `:spell` command
+ } spell-selection %{
+ set-option window spell_regions %val{timestamp}
+ try %{ add-highlighter window/ ranges spell_regions }
-define-command -params ..1 \
- -docstring %{spell [<language>]: spell check the current buffer
-The first optional argument is the language against which the check will be performed
-Formats of language supported:
- - ISO language code, e.g. 'en'
- - language code above followed by a dash or underscore with an ISO country code, e.g. 'en-US'} \
- spell %{
- try %{ add-highlighter window/ ranges 'spell_regions' }
evaluate-commands %sh{
- file=$(mktemp -d "${TMPDIR:-/tmp}"/kak-spell.XXXXXXXX)/buffer
- printf 'eval -no-hooks write -sync %s\n' "${file}"
- printf 'set-option buffer spell_tmp_file %s\n' "${file}"
+ path=$(mktemp -d "${TMPDIR:-/tmp}"/kak-spell.XXXXXXXX)
+ printf 'set-option buffer spell_tmp_dir "%s"\n' "${path}"
}
+
+ execute-keys "<a-|>tee ""%opt{spell_tmp_dir}/${kak_main_reg_hash}""<ret>"
+
evaluate-commands %sh{
if [ $# -ge 1 ]; then
if [ ${#1} -ne 2 ] && [ ${#1} -ne 5 ]; then
echo "echo -markup '{Error}Invalid language code (examples of expected format: en, en_US, en-US)'"
- rm -rf "$(dirname "$kak_opt_spell_tmp_file")"
+ rm -rf "${kak_opt_spell_tmp_dir}"
exit 1
else
options="-l '$1'"
@@ -28,35 +29,49 @@ Formats of language supported:
fi
{
- sed 's/^/^/' "$kak_opt_spell_tmp_file" | eval "aspell --byte-offsets -a $options" 2>&1 | {
- line_num=1
- regions=$kak_timestamp
- read line # drop the identification message
- while read -r line; do
- case "$line" in
- [\#\&]*)
- if expr "$line" : '^&' >/dev/null; then
- pos=$(printf %s\\n "$line" | cut -d ' ' -f 4 | sed 's/:$//')
- else
- pos=$(printf %s\\n "$line" | cut -d ' ' -f 3)
- fi
- word=$(printf %s\\n "$line" | cut -d ' ' -f 2)
- len=$(printf %s "$word" | wc -c)
- regions="$regions $line_num.$pos+${len}|Error"
- ;;
- '') line_num=$((line_num + 1));;
- \*) ;;
- *) printf 'echo -markup %%{{Error}%s}\n' "${line}" | kak -p "${kak_session}";;
- esac
- done
- printf 'set-option "buffer=%s" spell_regions %s' "${kak_bufname}" "${regions}" \
- | kak -p "${kak_session}"
- }
- rm -rf $(dirname "$kak_opt_spell_tmp_file")
- } </dev/null >/dev/null 2>&1 &
+ find "${kak_opt_spell_tmp_dir}" -type f | while read -r path_selection; do
+ sed 's/^/^/' "${path_selection}" | eval "aspell --byte-offsets -a $options" 2>&1 | {
+ line_num=1
+ regions=""
+ read line # drop the identification message
+ while read -r line; do
+ case "$line" in
+ [\#\&]*)
+ if printf %s "${line}" | grep -q '^&' >/dev/null; then
+ pos=$(printf %s\\n "$line" | cut -d ' ' -f 4 | sed 's/:$//')
+ else
+ pos=$(printf %s\\n "$line" | cut -d ' ' -f 3)
+ fi
+ word=$(printf %s\\n "$line" | cut -d ' ' -f 2)
+ len=$(printf %s "$word" | wc -c)
+ regions="$regions $line_num.$pos+${len}|Error"
+ ;;
+ '') line_num=$((line_num + 1));;
+ \*) ;;
+ *) printf 'echo -markup %%{{Error}%s}\n' "${line}" | kak -p "${kak_session}";;
+ esac
+ done
+ printf 'eval -client "%s" set-option -add window spell_regions %s\n' "${kak_client}" "${regions}" \
+ | kak -p "${kak_session}"
+ }
+ done
+
+ rm -rf "${kak_opt_spell_tmp_dir}"
+ } >/dev/null 2>&1 &
}
}
+define-command -params ..1 \
+ -docstring %{spell [<language>]: spell check the current buffer
+The first optional argument is the language against which the check will be performed
+Formats of language supported:
+ - ISO language code, e.g. 'en'
+ - language code above followed by a dash or underscore with an ISO country code, e.g. 'en-US'} \
+ spell %{ evaluate-commands -draft %{
+ execute-keys \%
+ spell-selection %arg{@}
+} }
+
define-command spell-clear %{
unset-option buffer spell_regions
}
Perhaps before dealing with :spell-selection
(which could be a good idea), Aspell does have filters and modes, which can deal with cases like "only spellcheck comments".
$ aspell dump modes
url mode to skip URL like constructs (default mode)
html mode for checking HTML documents
markdown mode for checking Markdown/CommonMark documents
texinfo mode for checking Texinfo documents
none mode to disable all filters
sgml mode for checking generic SGML/XML documents
comment mode to check any lines starting with a #
tex mode for checking TeX/LaTeX documents
email mode for skipping quoted text in email messages
perl mode for checking Perl comments and string literals
ccpp mode for checking C++ comments and string literals
nroff mode for checking Nroff documents
If we could expose an option to pass a mode (or even a filter?) That would make :spell
a lot more useful, I think. Plus it would be leveraging the system more, rather than putting more into a kak file.
:spell-selection
would be very useful, and so would @tylercecil's suggestion for manual options, for which it is trivial to add basic support. I gave it a go by adding an option for passing any list of strings to the aspell call. Works wonders for TeX by passing --mode=tex
and extra command filters.
Spell-checking in code is not very practical, except for comments.
If
:spell
could be made that it only check the current selection, then maybe it would be possible to have a little plugin that selects only comments, and then calls:spell
on such selection. Just a thought.