From 5f2f21640e04f6b7e5b5190093bf047c6d0c1747 Mon Sep 17 00:00:00 2001 From: Kevin Atkinson Date: Sat, 23 Mar 2024 13:38:56 -0400 Subject: [PATCH 01/12] Mark aspell_(dict|module)_info_list_(empty|size) as unimplemented. Closes #155. --- auto/mk-src.in | 34 ++++++++++++++++++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) diff --git a/auto/mk-src.in b/auto/mk-src.in index 4aa5b606..d13fbc87 100644 --- a/auto/mk-src.in +++ b/auto/mk-src.in @@ -1008,7 +1008,22 @@ class: module info list / config: config - list methods + method: empty + const + desc => UNIMPLEMENTED. Always returns false (i.e. 0). + / + bool + + method: size + const + desc => UNIMPLEMENTED. Always returns 0. + / + unsigned int + + method: elements + const + / + module info enumeration class: dict info list / @@ -1016,7 +1031,22 @@ class: dict info list / config: config - list methods + method: empty + const + desc => UNIMPLEMENTED. Always returns false (i.e. 0). + / + bool + + method: size + const + desc => UNIMPLEMENTED. Always returns 0. + / + unsigned int + + method: elements + const + / + dict info enumeration class: module info enumeration / From fc1c0b1642c581fee1cc3d739102eec3c0095b22 Mon Sep 17 00:00:00 2001 From: Kevin Atkinson Date: Sat, 16 Mar 2024 15:41:58 -0400 Subject: [PATCH 02/12] Gitignore some more files. --- .gitignore | 2 ++ test/.gitignore | 7 +++++++ 2 files changed, 9 insertions(+) diff --git a/.gitignore b/.gitignore index 72da70cf..23a85da4 100644 --- a/.gitignore +++ b/.gitignore @@ -57,6 +57,8 @@ Makefile /manual/aspell.html/ /manual/aspell.info /manual/texinfo.tex +/manual/stamp-vti +/manual/version.texi /missing /myspell/Makefile.in /po/Makefile.in diff --git a/test/.gitignore b/test/.gitignore index 4382f1d4..3e27fd51 100644 --- a/test/.gitignore +++ b/test/.gitignore @@ -5,3 +5,10 @@ aspell6-en-2018.04.16-0/ test-res aspell6-en-2018.04.16-0.tar.bz2 + +wide_test_invalid +wide_test_invalid-but_ok +wide_test_valid + +warning-settings +warning-settings.mk From a59c6890c382ce3f8c4f245bea8cfc325d21323a Mon Sep 17 00:00:00 2001 From: Kevin Atkinson Date: Sat, 16 Mar 2024 16:15:21 -0400 Subject: [PATCH 03/12] fix config-debug --- config-debug | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config-debug b/config-debug index 74d28f2c..d5be5b5f 100755 --- a/config-debug +++ b/config-debug @@ -4,5 +4,5 @@ mkdir -p build cd build ../configure --enable-maintainer-mode \ --disable-shared --disable-pspell-compatibility\ - --enable-w-all-error + --enable-w-all-error\ --prefix="`pwd`/../inst" CFLAGS='-g' CXXFLAGS='-g' "$@" From f72033abd1edb021f5c201e2b445c2b0ea30bfe2 Mon Sep 17 00:00:00 2001 From: Matthias Date: Thu, 2 Jun 2022 17:05:48 -0400 Subject: [PATCH 04/12] improve TeX mode --- manual/aspell.1 | 3 + manual/aspell.texi | 81 ++++++++++- modules/filter/context.cpp | 1 + modules/filter/modes/tex.amf | 5 +- modules/filter/tex-filter.info | 56 ++++++-- modules/filter/tex.cpp | 246 +++++++++++++++++++-------------- 6 files changed, 276 insertions(+), 116 deletions(-) diff --git a/manual/aspell.1 b/manual/aspell.1 index 86c70b8a..2c99027f 100644 --- a/manual/aspell.1 +++ b/manual/aspell.1 @@ -209,6 +209,9 @@ Check TeX comments. \fB\-\-add\-tex\-command=\fR\fI\fR, \fB\-\-rem\-tex\-command=\fR\fI\fR Add or remove a list of TeX commands. .TP +\fB\-\-add\-tex\-ignore\-env=\fR\fI\fR, \fB\-\-rem\-tex\-ignore\-env=\fR\fI\fR +Add or remove a list of LaTeX environments to skip while spell checking. +.TP \fB\-\-add\-texinfo\-ignore=\fR\fI\fR, \fB\-\-rem\-texinfo\-ignore=\fR\fI\fR Add or remove a list of Texinfo commands. .TP diff --git a/manual/aspell.texi b/manual/aspell.texi index c8d5260c..6210c419 100644 --- a/manual/aspell.texi +++ b/manual/aspell.texi @@ -1220,10 +1220,18 @@ The @option{tex} (all lowercase) filter hides @TeX{}/LaTeX commands and corresponding parameters that are not readable text in the output from Aspell. It also skips over @TeX{} comments by default. +Discretionary hyphens and italic corrections are ignored. For example, +@samp{hy\-phen} and @samp{shelf\/ful} are recognized as single words. + @c This filter mode is also available via the @c @option{latex} alias name. @table @b + +@item tex-check-comments +@i{(boolean)} +Check @TeX{} comments. Defaults to false. + @item tex-command @i{(list)} Controls which @TeX{} commands should have certain parameters and/or @@ -1232,13 +1240,15 @@ all their parameters and/or options checked. The format for each item is @example - + @end example The first item is simply the command name. The second item controls which parameters to skip over. A 'p' skips over a parameter while a 'P' doesn't. Similarly an 'o' will skip over an optional parameter -while an 'O' doesn't. The first letter on the list will apply to the +while an 'O' doesn't. A 'T' will force spell-checking of a parameter +even if the command occurs within a parameter or an environment Aspell +is told to skipped over. The first letter on the list will apply to the first parameter, the second letter will apply to the second parameter etc. If there are more parameters than letters Aspell will simply check them as normal. For example the option @@ -1261,6 +1271,25 @@ over the next optional parameter, if it is present, and will skip over the second parameter --- even if the optional parameter is not present --- and will check any additional parameters. +@example +add-tex-command foo T +@end example + +@noindent +will @emph{check} the first parameter of the @code{foo} command even +if Aspell is currently skipping over an argument or environment. For +example, if Aspell has been told to skip over the @code{bar} +environment (@pxref{Ignoring LaTeX Environments}), then in the text + +@example +\begin@{bar@} don't check \foo@{check@} don't check \end@{bar@} +@end example + +@noindent +it will nevertheless @emph{check} the argument to @code{foo}. This is +useful to force checking of arguments to text-related commands like +@code{hbox}, @code{text} or @code{intertext} inside math environments. + A @samp{*} at the end of the command is simply ignored. For example the option @@ -1287,15 +1316,56 @@ current defaults. @c will remove the command foo, if present, from the list of @TeX{} @c commands. -@item tex-check-comments -@i{(boolean)} -Check @TeX{} comments. Defaults to false. +@anchor{Ignoring LaTeX Environments} +@item tex-ignore-env +@i{(list)} +This controls which @TeX{} environments are skipped over. By default, +Aspell will skip over math formulas inside @code{$...$}, @code{$$...$$}, +@code{\(...\)} and @code{\[...\]} and over several common LaTeX and +AMS-LaTeX math environments like @code{equation} and @code{gather}. +For example, + +@example +add-tex-ignore-env thebibliography +@end example + +@noindent +will tell Aspell to skip over the bibliography as well (which may or +may not be a good idea). As with commands, skipping applies to the +starred form of the environment as well. + +@example +rem-tex-ignore-env equation +@end example + +@noindent +will make Aspell spell-check the contents of @code{equation} and +@code{equation*} environments. Skipping the contents of @code{$...$}, +@code{$$...$$}, @code{\(...\)} and @code{\[...\]} cannot be turned off. + +Note that one can force spell-checking of arguments to TeX commands +inside ignored environments with the 'T' parameter to the +@option{add-tex-command} option. @c @item tex-multi-byte @c (@i{list}) TeX multi byte letter en|decoding @end table +As a last resort, spell checking can be switched off by putting the +text @code{aspell:off} into the file. Similarly, with @code{aspell:on} +one can turn it on again. This can be useful for macro definitions, +for example + +@example +% aspell:off +\def\doi#1@{\href@{http://doi.org/#1@}@{doi:#1@}@} +% aspell:on +@end example + +@noindent +This feature is implemented via the @ref{Context Filter}. + @c The TeXfilter mode also contains a decoding and an encoding filter for @c @emph{babel} character codes like the German Umlauts: @@ -1404,6 +1474,7 @@ escapes (@code{\(}) and extended (@code{\[comp1 comp2 @dots{}]}) form. @end itemize +@anchor{Context Filter} @subsubsection Context Filter The @option{context} filter can be used to spell check source codes, diff --git a/modules/filter/context.cpp b/modules/filter/context.cpp index 0d0f6051..afe01aec 100644 --- a/modules/filter/context.cpp +++ b/modules/filter/context.cpp @@ -63,6 +63,7 @@ namespace { PosibErr ContextFilter::setup(Config * config){ name_ = "context-filter"; + order_num_ = 0.15; StringList delimiters; StackPtr delimiterpairs; const char * delimiterpair=NULL; diff --git a/modules/filter/modes/tex.amf b/modules/filter/modes/tex.amf index beb32dc3..758fcc00 100644 --- a/modules/filter/modes/tex.amf +++ b/modules/filter/modes/tex.amf @@ -6,5 +6,8 @@ MAGIC /0:256:^[ \t]*\\documentclass\[[^\[\]]*\]\{[^\{\}]*\}/tex DESCRIPTION mode for checking TeX/LaTeX documents -FILTER url +FILTER context +OPTION clear-context-delimiters +OPTION add-context-delimiters aspell:off aspell:on +OPTION enable-context-visible-first FILTER tex diff --git a/modules/filter/tex-filter.info b/modules/filter/tex-filter.info index 81d9c5b2..14d1e935 100644 --- a/modules/filter/tex-filter.info +++ b/modules/filter/tex-filter.info @@ -16,15 +16,35 @@ DESCRIPTION check TeX comments DEFAULT false ENDOPTION +OPTION ignore-env +TYPE list +DESCRIPTION LaTeX environments to be ignored +# LaTeX +#DEFAULT thebibliography +DEFAULT equation +DEFAULT eqnarray +# AMS-LaTeX +DEFAULT gather +DEFAULT multline +DEFAULT align +DEFAULT flalign +DEFAULT alignat +# Babel +DEFAULT otherlanguage +ENDOPTION + OPTION command TYPE list DESCRIPTION TeX commands +# plain TeX / LaTeX DEFAULT addtocounter pp DEFAULT addtolength pp -DEFAULT alpha p +DEFAULT alph p +DEFAULT Alph p DEFAULT arabic p DEFAULT fnsymbol p DEFAULT roman p +DEFAULT Roman p DEFAULT stepcounter p DEFAULT setcounter pp DEFAULT usecounter p @@ -42,7 +62,8 @@ DEFAULT newtheorem poPo DEFAULT newfont pp DEFAULT documentclass op DEFAULT usepackage op -DEFAULT begin po +# DO NOT change the next line! +DEFAULT begin so DEFAULT end p DEFAULT setlength pp DEFAULT addtolength pp @@ -54,15 +75,17 @@ DEFAULT hyphenation p DEFAULT pagenumbering p DEFAULT pagestyle p DEFAULT addvspace p -DEFAULT framebox ooP +DEFAULT framebox ooT DEFAULT hspace p DEFAULT vspace p -DEFAULT makebox ooP -DEFAULT parbox ooopP -DEFAULT raisebox pooP +DEFAULT hbox T +DEFAULT vbox T +DEFAULT makebox ooT +DEFAULT parbox ooopT +DEFAULT raisebox pooT DEFAULT rule opp DEFAULT sbox pO -DEFAULT savebox pooP +DEFAULT savebox pooT DEFAULT usebox p DEFAULT include p DEFAULT includeonly p @@ -76,13 +99,30 @@ DEFAULT fontshape p DEFAULT fontsize pp DEFAULT usefont pppp DEFAULT documentstyle op -DEFAULT cite p +DEFAULT cite Op DEFAULT nocite p DEFAULT psfig p DEFAULT selectlanguage p DEFAULT includegraphics op DEFAULT bibitem op +DEFAULT bibliography p +DEFAULT bibliographystyle p DEFAULT geometry p +# AMS-LaTeX +DEFAULT address p +DEFAULT email p +DEFAULT mathbb p +DEFAULT mathfrak p +DEFAULT eqref p +DEFAULT text T +DEFAULT intertext T +DEFAULT DeclareMathOperator pp +DEFAULT DeclareMathAlphabet ppppp +# hyperref +DEFAULT href pP +DEFAULT autoref p +DEFAULT url p +DEFAULT texorpdfstring Pp ENDOPTION #OPTION multi-byte diff --git a/modules/filter/tex.cpp b/modules/filter/tex.cpp index 19ab63ce..9809c3e2 100644 --- a/modules/filter/tex.cpp +++ b/modules/filter/tex.cpp @@ -32,17 +32,17 @@ namespace { class TexFilter : public IndividualFilter { private: - enum InWhat {Name, Opt, Parm, Other, Swallow}; + enum InWhat {Text, Name, Comment, InlineMath, DisplayMath, EnvName}; struct Command { InWhat in_what; String name; - const char * do_check; + bool skip; + int size; + const char * args; Command() {} - Command(InWhat w) : in_what(w), do_check("P") {} + Command(InWhat w, bool s, const char *a) : in_what(w), skip(s), args(a), size(0) {} }; - bool in_comment; - bool prev_backslash; Vector stack; class Commands : public StringMap { @@ -53,11 +53,11 @@ namespace { Commands commands; bool check_comments; - - inline void push_command(InWhat); - inline void pop_command(); - bool end_option(char u, char l); + StringMap ignore_env; + + inline bool push_command(InWhat, bool, const char *); + inline bool pop_command(); inline bool process_char(FilterChar::Chr c); @@ -71,14 +71,17 @@ namespace { // // - inline void TexFilter::push_command(InWhat w) { - stack.push_back(Command(w)); + inline bool TexFilter::push_command(InWhat w, bool skip, const char *args = "") { + stack.push_back(Command(w, skip, args)); + return skip; } - inline void TexFilter::pop_command() { - stack.pop_back(); - if (stack.empty()) - push_command(Parm); + inline bool TexFilter::pop_command() { + bool skip = stack.back().skip; + if (stack.size() > 1) { + stack.pop_back(); + } + return skip; } // @@ -96,133 +99,167 @@ namespace { check_comments = opts->retrieve_bool("f-tex-check-comments"); + opts->retrieve_list("f-tex-ignore-env", &ignore_env); + reset(); return true; } void TexFilter::reset() { - in_comment = false; - prev_backslash = false; stack.resize(0); - push_command(Parm); + push_command(Text, false); } # define top stack.back() +# define next_arg if (*top.args) { ++top.args; if (!*top.args) pop_command(); } +# define skip_opt_args if (*top.args) { while (*top.args == 'O' || *top.args == 'o') { ++top.args; } if (!*top.args) pop_command(); } + // yes this should be inlined, it is only called once inline bool TexFilter::process_char(FilterChar::Chr c) { - // deal with comments - if (c == '%' && !prev_backslash) in_comment = true; - if (in_comment && c == '\n') in_comment = false; - - prev_backslash = false; - - if (in_comment) return !check_comments; + top.size++; if (top.in_what == Name) { if (asc_isalpha(c)) { top.name += c; - return true; + return top.skip; } else { - - if (top.name.empty() && (c == '@')) { - top.name += c; - return true; - } - - top.in_what = Other; + bool in_name; if (top.name.empty()) { - top.name.clear(); top.name += c; - top.do_check = commands.lookup(top.name.c_str()); - if (top.do_check == 0) top.do_check = ""; - return !asc_isspace(c); + in_name = true; + } else { + top.size--; + in_name = false; } - top.do_check = commands.lookup(top.name.c_str()); - if (top.do_check == 0) top.do_check = ""; + String name = top.name; - if (asc_isspace(c)) { // swallow extra spaces - top.in_what = Swallow; - return true; - } else if (c == '*') { // ignore * at end of commands - return true; + pop_command(); + + const char *args = commands.lookup(name.c_str()); + + if (name == "begin") + push_command(top.in_what, top.skip); + // args = "s"; + else if (name == "end") + pop_command(); + + // we might still be waiting for arguments + skip_opt_args; + if (*top.args) { + next_arg; + } else if (name == "[") { + // \[ + push_command(DisplayMath, true); + } else if (name == "]") { + // \] + pop_command(); // pop DisplayMath + } else if (name == "(") { + // \( + push_command(InlineMath, true); + } else if (name == ")") { + // \) + pop_command(); // pop InlineMath + } else if (args && *args) { + push_command(top.in_what, top.skip, args); } - // continue o... + if (in_name || c == '*') // better way to deal with "*"? + return true; + else + return process_char(c); // start over } - } else if (top.in_what == Swallow) { - - if (asc_isspace(c)) - return true; - else - top.in_what = Other; } - if (c == '{') - while (*top.do_check == 'O' || *top.do_check == 'o') - ++top.do_check; - - if (*top.do_check == '\0') - pop_command(); - - if (c == '{') { - - if (top.in_what == Parm || top.in_what == Opt || *top.do_check == '\0') - push_command(Parm); + if (top.in_what == Comment) { + if (c == '\n') { + pop_command(); + return false; // preserve newlines + } else { + return top.skip; + } + } - top.in_what = Parm; + if (c == '%') { + push_command(Comment, !check_comments); return true; } - if (top.in_what == Other) { - - if (c == '[') { - - top.in_what = Opt; - return true; - - } else if (asc_isspace(c)) { - - return true; - + if (c == '$') { + if (top.in_what != InlineMath) { + // $ begin + return push_command(InlineMath, true); + } else if (top.size > 1) { + // $ end + return pop_command(); } else { - - pop_command(); - + // $ -> $$ + pop_command(); // pop InlineMath + if (top.in_what == DisplayMath) + // $$ end + return pop_command(); + else + // $$ start + return push_command(DisplayMath, true); } - - } + } if (c == '\\') { - prev_backslash = true; - push_command(Name); - return true; + return push_command(Name, true); } - if (top.in_what == Parm) { + if (c == '}' || c == ']') { + if (top.in_what == EnvName) { + String env = top.name; + if (env.back() == '*') + env.pop_back(); + bool skip = pop_command(); + next_arg; + if (ignore_env.have(env)) { + stack[stack.size()-2].skip = true; + } + return skip; + } else { + bool skip = pop_command(); + next_arg; + return skip; + } + } - if (c == '}') - return end_option('P','p'); + if (c == '{') { + skip_opt_args; + if (*top.args == 'T') + return push_command(Text, false); + else if (*top.args == 's') + return push_command(EnvName, true); else - return *top.do_check == 'p'; + return push_command(top.in_what, top.skip || *top.args == 'p'); + } - } else if (top.in_what == Opt) { + if (c == '[') { + if (*top.args == 'O' || *top.args == 'o' || !*top.args) { + return push_command(top.in_what, top.skip || *top.args == 'o'); + } + // else: fall-through to treat it as a one-letter argument + } - if (c == ']') - return end_option('O', 'o'); - else - return *top.do_check == 'o'; + if (top.in_what == EnvName) + top.name += c; + // we might still be waiting for arguments + if (!asc_isspace(c)) { + skip_opt_args; + next_arg; } - return false; + return top.skip; } void TexFilter::process(FilterChar * & str, FilterChar * & stop) @@ -230,19 +267,24 @@ namespace { FilterChar * cur = str; while (cur != stop) { - if (process_char(*cur)) + bool hyphen = top.in_what == Name && top.size == 0 + && (*cur == '-' || *cur == '/') && cur-str >= 2; + if (process_char(*cur)) { *cur = ' '; + } + if (hyphen) { + FilterChar *i = cur-2, *j = cur+1; + *i = FilterChar(*i, FilterChar::sum(i, j)); + i++; + while (j != stop) + *(i++) = *(j++); + *(stop-2) = *(stop-1) = FilterChar(0, 0); + cur--; + } ++cur; } } - bool TexFilter::end_option(char u, char l) { - top.in_what = Other; - if (*top.do_check == u || *top.do_check == l) - ++top.do_check; - return true; - } - // // TexFilter::Commands // @@ -252,14 +294,14 @@ namespace { while (!asc_isspace(value[p1])) { if (value[p1] == '\0') return make_err(bad_value, value,"", - _("a string of 'o','O','p',or 'P'")); + _("a string of 'o', 'O', 'p', 'P', 's' or 'T'")); ++p1; } int p2 = p1 + 1; while (asc_isspace(value[p2])) { if (value[p2] == '\0') return make_err(bad_value, value,"", - _("a string of 'o','O','p',or 'P'")); + _("a string of 'o', 'O', 'p', 'P', 's' or 'T'")); ++p2; } String t1; t1.assign(value,p1); From f17a50125a0d55663115fb0218f58b6f312ed8a5 Mon Sep 17 00:00:00 2001 From: Kevin Atkinson Date: Sat, 16 Mar 2024 15:44:56 -0400 Subject: [PATCH 05/12] tex filter: fix compiler warning --- modules/filter/tex.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/filter/tex.cpp b/modules/filter/tex.cpp index 9809c3e2..16b78fe9 100644 --- a/modules/filter/tex.cpp +++ b/modules/filter/tex.cpp @@ -40,7 +40,7 @@ namespace { int size; const char * args; Command() {} - Command(InWhat w, bool s, const char *a) : in_what(w), skip(s), args(a), size(0) {} + Command(InWhat w, bool s, const char *a) : in_what(w), skip(s), size(0), args(a) {} }; Vector stack; From b7aae1ef1aac0513ec0e031213cae0054a040602 Mon Sep 17 00:00:00 2001 From: Kevin Atkinson Date: Sat, 16 Mar 2024 16:09:00 -0400 Subject: [PATCH 06/12] Restore original TeX filter as tex_v1. --- Makefile.am | 9 +- modules/filter/modes/tex_v1.amf | 8 + modules/filter/tex_v1-filter.info | 105 ++++ modules/filter/tex_v1.cpp | 767 ++++++++++++++++++++++++++++++ 4 files changed, 888 insertions(+), 1 deletion(-) create mode 100644 modules/filter/modes/tex_v1.amf create mode 100644 modules/filter/tex_v1-filter.info create mode 100644 modules/filter/tex_v1.cpp diff --git a/Makefile.am b/Makefile.am index 466d22bf..c7e29659 100644 --- a/Makefile.am +++ b/Makefile.am @@ -176,6 +176,7 @@ dynamic_optfiles = optfiles = \ modules/filter/email-filter.info\ modules/filter/tex-filter.info\ + modules/filter/tex_v1-filter.info\ modules/filter/sgml-filter.info\ modules/filter/markdown-filter.info\ modules/filter/html-filter.info\ @@ -189,6 +190,7 @@ fltfiles = \ modules/filter/modes/sgml.amf \ modules/filter/modes/markdown.amf \ modules/filter/modes/tex.amf \ + modules/filter/modes/tex_v1.amf \ modules/filter/modes/email.amf \ modules/filter/modes/ccpp.amf \ modules/filter/modes/none.amf \ @@ -208,6 +210,7 @@ static_optfiles += ${optfiles} libaspell_la_SOURCES +=\ modules/filter/email.cpp\ modules/filter/tex.cpp\ + modules/filter/tex_v1.cpp\ modules/filter/sgml.cpp\ modules/filter/markdown.cpp\ modules/filter/context.cpp\ @@ -221,7 +224,7 @@ filter_ldflags = -module -avoid-version ### Add name of filter library containing your filter. Name always ### must look like lib-filter.la see development manual -filter_LTLIBRARIES = email-filter.la tex-filter.la\ +filter_LTLIBRARIES = email-filter.la tex-filter.la tex_v1-filter.la \ sgml-filter.la markdown-filter.la context-filter.la\ nroff-filter.la texinfo-filter.la @@ -233,6 +236,10 @@ tex_filter_la_SOURCES = modules/filter/tex.cpp tex_filter_la_LIBADD = libaspell.la tex_filter_la_LDFLAGS = ${filter_ldflags} +tex_v1_filter_la_SOURCES = modules/filter/tex_v1.cpp +tex_v1_filter_la_LIBADD = libaspell.la +tex_v1_filter_la_LDFLAGS = ${filter_ldflags} + sgml_filter_la_SOURCES = modules/filter/sgml.cpp sgml_filter_la_LIBADD = libaspell.la sgml_filter_la_LDFLAGS = ${filter_ldflags} diff --git a/modules/filter/modes/tex_v1.amf b/modules/filter/modes/tex_v1.amf new file mode 100644 index 00000000..c6def295 --- /dev/null +++ b/modules/filter/modes/tex_v1.amf @@ -0,0 +1,8 @@ +MODE tex_v1 + +ASPELL >=0.60 + +DESCRIPTION old TeX mode + +FILTER url +FILTER tex_v1 diff --git a/modules/filter/tex_v1-filter.info b/modules/filter/tex_v1-filter.info new file mode 100644 index 00000000..9b2c8596 --- /dev/null +++ b/modules/filter/tex_v1-filter.info @@ -0,0 +1,105 @@ +# TeX filter option file + +#This Filter is usable with the following version(s) of Aspell +ASPELL >=0.51 + +#This line will be printed when typing `Aspell help TeX' +DESCRIPTION old TeX filter + +STATIC filter +#STATIC encoder +#STATIC decoder + +OPTION check-comments +TYPE bool +DESCRIPTION check TeX comments +DEFAULT false +ENDOPTION + +OPTION command +TYPE list +DESCRIPTION TeX commands +DEFAULT addtocounter pp +DEFAULT addtolength pp +DEFAULT alpha p +DEFAULT arabic p +DEFAULT fnsymbol p +DEFAULT roman p +DEFAULT stepcounter p +DEFAULT setcounter pp +DEFAULT usecounter p +DEFAULT value p +DEFAULT newcounter po +DEFAULT refstepcounter p +DEFAULT label p +DEFAULT pageref p +DEFAULT ref p +DEFAULT newcommand poOP +DEFAULT renewcommand poOP +DEFAULT newenvironment poOPP +DEFAULT renewenvironment poOPP +DEFAULT newtheorem poPo +DEFAULT newfont pp +DEFAULT documentclass op +DEFAULT usepackage op +DEFAULT begin po +DEFAULT end p +DEFAULT setlength pp +DEFAULT addtolength pp +DEFAULT settowidth pp +DEFAULT settodepth pp +DEFAULT settoheight pp +DEFAULT enlargethispage p +DEFAULT hyphenation p +DEFAULT pagenumbering p +DEFAULT pagestyle p +DEFAULT addvspace p +DEFAULT framebox ooP +DEFAULT hspace p +DEFAULT vspace p +DEFAULT makebox ooP +DEFAULT parbox ooopP +DEFAULT raisebox pooP +DEFAULT rule opp +DEFAULT sbox pO +DEFAULT savebox pooP +DEFAULT usebox p +DEFAULT include p +DEFAULT includeonly p +DEFAULT input p +DEFAULT addcontentsline ppP +DEFAULT addtocontents pP +DEFAULT fontencoding p +DEFAULT fontfamily p +DEFAULT fontseries p +DEFAULT fontshape p +DEFAULT fontsize pp +DEFAULT usefont pppp +DEFAULT documentstyle op +DEFAULT cite p +DEFAULT nocite p +DEFAULT psfig p +DEFAULT selectlanguage p +DEFAULT includegraphics op +DEFAULT bibitem op +DEFAULT geometry p +ENDOPTION + +#OPTION multi-byte +#TYPE list +#DESCRIPTION multi character coded letters (,[,[...]]) +#DEFAULT Ä,\\"A,"A +#DEFAULT ä,\\"a,"a +#DEFAULT Ö,\\"O,"O +#DEFAULT ö,\\"o,"o +#DEFAULT Ü,\\"U,"U +#DEFAULT ü,\\"u,"u +#DEFAULT ß,\\"s,"s +#FLAGS utf-8 +#ENDOPTION + +#OPTION hyphen +#TYPE list +#DESCRIPTION characters used to encode hyphenation locations +#DEFAULT \\- +#ENDOPTION diff --git a/modules/filter/tex_v1.cpp b/modules/filter/tex_v1.cpp new file mode 100644 index 00000000..6f2d8f82 --- /dev/null +++ b/modules/filter/tex_v1.cpp @@ -0,0 +1,767 @@ +// This file is part of The New Aspell +// Copyright (C) 2001 by Kevin Atkinson under the GNU LGPL license +// version 2.0 or 2.1. You should have received a copy of the LGPL +// license along with this library if you did not you can find +// it at http://www.gnu.org/. + +#include "asc_ctype.hpp" +#include "config.hpp" +#include "string.hpp" +#include "indiv_filter.hpp" +#include "mutable_container.hpp" +#include "string_map.hpp" +#include "clone_ptr-t.hpp" +#include "vector.hpp" +#include "errors.hpp" +#include "convert.hpp" + +//#define FILTER_PROGRESS_CONTROL "tex-filter-debug.log" +//#include "filter_debug.hpp" +//#include +//#include +#include "filter_char_vector.hpp" +#include "string_list.hpp" +#include "string_enumeration.hpp" + +#include "gettext.h" + +namespace { + + using namespace acommon; + + class TexFilter : public IndividualFilter + { + private: + enum InWhat {Name, Opt, Parm, Other, Swallow}; + struct Command { + InWhat in_what; + String name; + const char * do_check; + Command() {} + Command(InWhat w) : in_what(w), do_check("P") {} + }; + + bool in_comment; + bool prev_backslash; + Vector stack; + + class Commands : public StringMap { + public: + PosibErr add(ParmStr to_add); + PosibErr remove(ParmStr to_rem); + }; + + Commands commands; + bool check_comments; + + inline void push_command(InWhat); + inline void pop_command(); + + bool end_option(char u, char l); + + inline bool process_char(FilterChar::Chr c); + + public: + PosibErr setup(Config *); + void reset(); + void process(FilterChar * &, FilterChar * &); + }; + + // + // + // + + inline void TexFilter::push_command(InWhat w) { + stack.push_back(Command(w)); + } + + inline void TexFilter::pop_command() { + stack.pop_back(); + if (stack.empty()) + push_command(Parm); + } + + // + // + // + + PosibErr TexFilter::setup(Config * opts) + { + name_ = "tex-filter"; + order_num_ = 0.35; + //fprintf(stderr,"name %s \n",name_); + + commands.clear(); + opts->retrieve_list("f-tex-command", &commands); + + check_comments = opts->retrieve_bool("f-tex-check-comments"); + + reset(); + return true; + } + + void TexFilter::reset() + { + in_comment = false; + prev_backslash = false; + stack.resize(0); + push_command(Parm); + } + +# define top stack.back() + + // yes this should be inlined, it is only called once + inline bool TexFilter::process_char(FilterChar::Chr c) + { + // deal with comments + if (c == '%' && !prev_backslash) in_comment = true; + if (in_comment && c == '\n') in_comment = false; + + prev_backslash = false; + + if (in_comment) return !check_comments; + + if (top.in_what == Name) { + if (asc_isalpha(c)) { + + top.name += c; + return true; + + } else { + + if (top.name.empty() && (c == '@')) { + top.name += c; + return true; + } + + top.in_what = Other; + + if (top.name.empty()) { + top.name.clear(); + top.name += c; + top.do_check = commands.lookup(top.name.c_str()); + if (top.do_check == 0) top.do_check = ""; + return !asc_isspace(c); + } + + top.do_check = commands.lookup(top.name.c_str()); + if (top.do_check == 0) top.do_check = ""; + + if (asc_isspace(c)) { // swallow extra spaces + top.in_what = Swallow; + return true; + } else if (c == '*') { // ignore * at end of commands + return true; + } + + // continue o... + } + + } else if (top.in_what == Swallow) { + + if (asc_isspace(c)) + return true; + else + top.in_what = Other; + } + + if (c == '{') + while (*top.do_check == 'O' || *top.do_check == 'o') + ++top.do_check; + + if (*top.do_check == '\0') + pop_command(); + + if (c == '{') { + + if (top.in_what == Parm || top.in_what == Opt || *top.do_check == '\0') + push_command(Parm); + + top.in_what = Parm; + return true; + } + + if (top.in_what == Other) { + + if (c == '[') { + + top.in_what = Opt; + return true; + + } else if (asc_isspace(c)) { + + return true; + + } else { + + pop_command(); + + } + + } + + if (c == '\\') { + prev_backslash = true; + push_command(Name); + return true; + } + + if (top.in_what == Parm) { + + if (c == '}') + return end_option('P','p'); + else + return *top.do_check == 'p'; + + } else if (top.in_what == Opt) { + + if (c == ']') + return end_option('O', 'o'); + else + return *top.do_check == 'o'; + + } + + return false; + } + + void TexFilter::process(FilterChar * & str, FilterChar * & stop) + { + FilterChar * cur = str; + + while (cur != stop) { + if (process_char(*cur)) + *cur = ' '; + ++cur; + } + } + + bool TexFilter::end_option(char u, char l) { + top.in_what = Other; + if (*top.do_check == u || *top.do_check == l) + ++top.do_check; + return true; + } + + // + // TexFilter::Commands + // + + PosibErr TexFilter::Commands::add(ParmStr value) { + int p1 = 0; + while (!asc_isspace(value[p1])) { + if (value[p1] == '\0') + return make_err(bad_value, value,"", + _("a string of 'o','O','p',or 'P'")); + ++p1; + } + int p2 = p1 + 1; + while (asc_isspace(value[p2])) { + if (value[p2] == '\0') + return make_err(bad_value, value,"", + _("a string of 'o','O','p',or 'P'")); + ++p2; + } + String t1; t1.assign(value,p1); + String t2; t2.assign(value+p2); + return StringMap::replace(t1, t2); + } + + PosibErr TexFilter::Commands::remove(ParmStr value) { + int p1 = 0; + while (!asc_isspace(value[p1]) && value[p1] != '\0') ++p1; + String temp; temp.assign(value,p1); + return StringMap::remove(temp); + } +#if 0 + // + // + class Recode { + Vector code; + int minlength; + public: + Recode(); + Recode(const Recode & recode) {*this=recode;} + void reset(); + bool setExpansion(const char * expander); + virtual int encode(FilterChar * & begin,FilterChar * & end, + FilterCharVector * external); + virtual int decode(FilterChar * & begin,FilterChar * & end, + FilterCharVector * internal); + bool operator == (char test) ; + bool operator != (char test) ; + Recode & operator = (const Recode & rec); + virtual ~Recode(); + }; + + Recode::Recode() + : code(0) + { + minlength=0; + reset(); + } + + Recode & Recode::operator = (const Recode & rec) { + reset(); + code.resize(rec.code.size()); + + int countrec=0; + + for (countrec=0; + countrec < code.size(); + countrec++) { + code[countrec]=NULL; + if (!rec.code[countrec]) { + continue; + } + int length=strlen(rec.code[countrec]); + + code[countrec]= new char[length+1]; + strncpy(code[countrec],rec.code[countrec],length); + code[countrec][length]='\0'; + } + return *this; + } + + + bool Recode::operator == (char test) { + return (code.size() && (code[0][0] == test)); + } + + bool Recode::operator != (char test) { + return (!code.size() || (code[0][0] != test)); + } + + void Recode::reset() { + + unsigned int countcode=0; + + for (countcode=0; + countcode < code.size(); + countcode++) { + if (code[countcode]) { + delete[] code[countcode]; + } + code[countcode] = NULL; + } + code.resize(0); + minlength=0; + } + + bool Recode::setExpansion(const char * expander) { + + char * begin=(char *)expander; + char * end=begin; + char * start=begin; + int keylen=0; + + + if (code.size() > 0) { + keylen=strlen(code[0]); + } + while (begin && end && *begin) { + while (end && *end && (*end != ',')) { + end++; + } + if (end && (begin != end)) { + + char hold = *end; + + *end='\0'; + + int length=strlen(begin); + + if ((begin == start) && (keylen || (length != 1))) { + if ((length != 1) || (keylen != length) || + strncmp(code[0],begin,length)) { + *end=hold; + return false; + } + *end=hold; + if (*end) { + end++; + } + begin=end; + continue; + } + else if (minlength < length) { + minlength=0; + } + + code.resize(code.size()+1); + code[code.size()-1] = new char[length+1]; + strncpy(code[code.size()-1],begin,length); + code[code.size()-1][length]='\0'; + *end=hold; + if (*end) { + end++; + } + begin=end; + } + } + return true; + } + + int Recode::encode(FilterChar * & begin,FilterChar * & end, + FilterCharVector * external) { + if ((code.size() < 2) || + (begin == NULL) || + (begin == end) || + (begin->width < (unsigned int) minlength )) { + return 0; + } + + if (code[0][0] != (char)*begin) { + return 0; + } + external->append(code[1],1); + return strlen(code[0]); + } + + int Recode::decode(FilterChar * & begin,FilterChar * & end, + FilterCharVector * internal) { + + FilterChar * i = begin; + char * codepointer = NULL; + char * codestart = NULL; + + if (code.size() < 2) { + return 0; + } + while((i != end) && + ((codepointer == NULL) || (*codepointer))) { + if (codepointer == NULL) { + + int countcodes=0; + + for (countcodes=1; + countcodes < (int) code.size(); + countcodes++) { + if (*i == code[countcodes][0]) { + codestart=codepointer=code[countcodes]; + break; + } + } + if (codepointer == NULL) { + return 0; + } + } + if (*codepointer != *i) { + return 0; + } + i++; + codepointer++; + } + if ((codepointer == NULL) || (*codepointer)) { + return 0; + } + + int length=strlen(codestart); + internal->append(code[0],length); + return length; + } + + + Recode::~Recode() { + reset(); + } + + class TexEncoder : public IndividualFilter { + Vector multibytes; + FilterCharVector buf; + + public: + TexEncoder(); + virtual PosibErr setup(Config * config); + virtual void process(FilterChar * & start, FilterChar * & stop); + virtual void reset() ; + virtual ~TexEncoder(); + }; + + TexEncoder::TexEncoder() + : multibytes(0), + buf() + { + } + + PosibErr TexEncoder::setup(Config * config) { + name_ = "tex-encoder"; + order_num_ = 0.40; + + StringList multibytechars; + + config->retrieve_list("f-tex-multi-byte", &multibytechars); + + Conv conv; // this a quick and dirty fix witch will only work for + // iso-8859-1. Full unicode support needs to be + // implemented + conv.setup(*config, "utf-8", "iso-8859-1", NormNone); + + StringEnumeration * multibytelist=multibytechars.elements(); + const char * multibyte0=NULL; + const char * multibyte=NULL; + + while ((multibyte0=multibytelist->next())) { + + multibyte = conv(multibyte0); + + if (strlen(multibyte) < 3) { + fprintf(stderr,"Filter: %s ignoring multi byte encoding `%s'\n", + name_,multibyte); + continue; + } + + int countmulti=0; + + while ((countmulti < multibytes.size()) && + !multibytes[countmulti].setExpansion(multibyte)) { + countmulti++; + } + if (countmulti >= multibytes.size()) { + multibytes.resize(multibytes.size()+1); + if (!multibytes[multibytes.size()-1].setExpansion(multibyte)) { + fprintf(stderr,"Filter: %s ignoring multi byte encoding `%s'\n",name_,multibyte); + continue; + } + } + } + return true; + } + + void TexEncoder::process(FilterChar * & start, FilterChar * & stop) { + buf.clear(); + + FilterChar * i=start; + + while (i && (i != stop)) { + + FilterChar * old = i; + int count=0; + + for (count=0; + count < multibytes.size(); + count++) { + + + i+=multibytes[count].encode(i,stop,&buf); + } + if (i == old) { + buf.append(*i); + i++; + } + } + buf.append('\0'); + start = buf.pbegin(); + stop = buf.pend() - 1; + } + + + void TexEncoder::reset() { + multibytes.resize(0); + buf.clear(); + } + + TexEncoder::~TexEncoder(){ + } + + + class TexDecoder : public IndividualFilter { + Vector multibytes; + FilterCharVector buf; + Vectorhyphens; + + public: + TexDecoder(); + virtual PosibErr setup(Config * config); + virtual void process(FilterChar * & start, FilterChar * & stop); + virtual void reset() ; + virtual ~TexDecoder(); + }; + + TexDecoder::TexDecoder() + : multibytes(0), + buf(), + hyphens() + { + FDEBUGNOTOPEN; + } + + PosibErr TexDecoder::setup(Config * config) { + name_ = "tex-decoder"; + order_num_ = 0.3; + + StringList multibytechars; + + config->retrieve_list("f-tex-multi-byte", &multibytechars); + + Conv conv; // this a quick and dirty fix witch will only work for + // iso-8859-1. Full unicode support needs to be + // implemented + conv.setup(*config, "utf-8", "iso-8859-1", NormNone); + + StringEnumeration * multibytelist=multibytechars.elements(); + const char * multibyte0=NULL; + const char * multibyte=NULL; + + multibytes.resize(0); + + while ((multibyte0=multibytelist->next())) { + + multibyte = conv(multibyte0); + + if (strlen(multibyte) < 3) { + fprintf(stderr,"Filter: %s ignoring multi byte encoding `%s'\n", + name_,multibyte); + continue; + } + FDEBUGPRINTF("next multibyte chars `"); + FDEBUGPRINTF(multibyte); + FDEBUGPRINTF("'\n"); + + int countmulti=0; + + while ((countmulti < multibytes.size()) && + !multibytes[countmulti].setExpansion(multibyte)) { + countmulti++; + } + FDEBUGPRINTF("next multibyte chars `"); + FDEBUGPRINTF(multibyte); + FDEBUGPRINTF("'\n"); + if (countmulti >= multibytes.size()) { + multibytes.resize(multibytes.size()+1); + if (!multibytes[multibytes.size()-1].setExpansion(multibyte)) { + fprintf(stderr,"Filter: %s ignoring multi byte encoding `%s'\n",name_,multibyte); + continue; + } + } + FDEBUGPRINTF("next multibyte chars `"); + FDEBUGPRINTF(multibyte); + FDEBUGPRINTF("'\n"); + } + StringList hyphenChars; + + config->retrieve_list("f-tex-hyphen", &hyphenChars); + + StringEnumeration * hyphenList=hyphenChars.elements(); + const char * hyphen=NULL; + + hyphens.resize(0); + while ((hyphen=hyphenList->next())) { + FDEBUGPRINTF("next hyphen char `"); + FDEBUGPRINTF(hyphen); + FDEBUGPRINTF("'\n"); + hyphens.push_back(strdup(hyphen)); + } + return true; + } + + void TexDecoder::process(FilterChar * & start, FilterChar * & stop) { + buf.clear(); + + FilterChar * i=start; + + FDEBUGPRINTF("filtin `"); + while (i && (i != stop)) { + + FilterChar * old = i; + int count=0; + + for (count=0; + count < multibytes.size(); + count++) { + + FilterChar * j = i; + + i+=multibytes[count].decode(i,stop,&buf); + + while (j != i) { + char jp[2]={'\0','\0'}; + + jp[0]=*j; + FDEBUGPRINTF(jp); + j++; + } + } + for(count=0; + count < hyphens.size(); + count++) { + if (!hyphens[count]) { + continue; + } + char * hp = &hyphens[count][0]; + char * hpo = hp; + FilterChar * j = i; + while (*hp && (j != stop) && + (*hp == *j)) { + hp++; + j++; + } + if (!*hp) { + FDEBUGPRINTF("{"); + FilterChar * k = i; + while (k != j) { + char kp[2]={'\0','\0'}; + + kp[0]=*k; + FDEBUGPRINTF(kp); + k++; + } + FDEBUGPRINTF("}"); + if (buf.size()) { + buf[buf.size()-1].width+=strlen(hpo); +// buf.append(*i,strlen(hpo)+1); + } + else { +//FIXME better solution for illegal hyphenation at begin of line +// illegal as new line chars are whitespace for latex + buf.append(*i,strlen(hpo)); + char ip[2]={'\0','\0'}; + ip[0]=*i; + FDEBUGPRINTF(ip); + } + i=j; + } + } + if (i == old) { + char ip[2]={'\0','\0'}; + ip[0]=*i; + FDEBUGPRINTF(ip); + buf.append(*i); + i++; + } + } + buf.append('\0'); + start = buf.pbegin(); + stop = buf.pend() - 1; + FDEBUGPRINTF("'\nfiltout `"); + i = start; + while (i != stop) { + char ip[2]={'\0','\0'}; + ip[0]=*i; + FDEBUGPRINTF(ip); + i++; + } + FDEBUGPRINTF("'\n"); + } + + + void TexDecoder::reset() { + multibytes.resize(0); + buf.clear(); + } + + TexDecoder::~TexDecoder(){ + FDEBUGCLOSE; + } +#endif +} + +C_EXPORT +IndividualFilter * new_aspell_tex_v1_filter() {return new TexFilter;} + +#if 0 +C_EXPORT +IndividualFilter * new_aspell_tex_v1_decoder() {return new TexDecoder;} +C_EXPORT +IndividualFilter * new_aspell_tex_v1_encoder() {return new TexEncoder;} +#endif From b82a035c4933e33c0d10765b291dbcf6093be3c6 Mon Sep 17 00:00:00 2001 From: Kevin Atkinson Date: Sat, 16 Mar 2024 13:43:05 -0400 Subject: [PATCH 07/12] context filter: add order-num option --- modules/filter/context-filter.info | 6 ++++++ modules/filter/context.cpp | 13 ++++++++++++ test/Makefile | 10 ++++++++-- test/context.dat | 32 ++++++++++++++++++++++++++++++ 4 files changed, 59 insertions(+), 2 deletions(-) create mode 100644 test/context.dat diff --git a/modules/filter/context-filter.info b/modules/filter/context-filter.info index d5063415..3d94b493 100644 --- a/modules/filter/context-filter.info +++ b/modules/filter/context-filter.info @@ -21,3 +21,9 @@ TYPE bool DESCRIPTION swaps visible and invisible text DEFAULT false ENDOPTION + +OPTION order-num +TYPE string +DEFAULT 0.5 +DESCRIPTION between 0 and 1, defaults to 0.5 +ENDOPTION diff --git a/modules/filter/context.cpp b/modules/filter/context.cpp index afe01aec..190e1810 100644 --- a/modules/filter/context.cpp +++ b/modules/filter/context.cpp @@ -8,7 +8,10 @@ // interface. // This was added to Aspell by Christoph Hintermüller +#include + #include "settings.h" +#include "gettext.h" #include "can_have_error.hpp" #include "config.hpp" @@ -22,6 +25,8 @@ #include "string_list.hpp" #include "vector.hpp" + + using namespace acommon; namespace { @@ -78,6 +83,14 @@ namespace { return true; } + String order_num_str = config->retrieve("f-context-order-num"); + char * endptr; + errno = 0; + order_num_ = strtod(order_num_str.str(), &endptr); + if (errno != 0 || *endptr != '\0' || !(0.0 <= order_num_ && order_num_ <= 1.0)) + return make_err(bad_value, "context-order-num", order_num_str, + _("a number between 0 and 1")); + if (config->retrieve_bool("f-context-visible-first")) { state=visible; } diff --git a/test/Makefile b/test/Makefile index 9f709ddb..1a3b9fd3 100644 --- a/test/Makefile +++ b/test/Makefile @@ -8,7 +8,7 @@ ifdef SLOPPY EXTRA_CONFIG_FLAGS += --enable-sloppy-null-term-strings endif -.PHONY: all prep sanity filter-test suggest wide cxx_warnings +.PHONY: all prep sanity filter-test suggest wide cxx_warnings context-filter-test markdown-filter-test all: prep sanity filter-test suggest wide cxx_warnings cat test-res @@ -28,10 +28,16 @@ sanity: prep ./sanity echo "all ok (sanity)" >> test-res -filter-test: prep +filter-test: markdown-filter-test context-filter-test + +markdown-filter-test: prep ./filter-test "${ASPELL_WRAP} ${ASPELL}" < markdown.dat echo "all ok (markdown filter-test)" >> test-res +context-filter-test: prep + ./filter-test "${ASPELL_WRAP} ${ASPELL}" < context.dat + echo "all ok (context filter-test)" >> test-res + inst/bin/aspell: build/Makefile phony $(MAKE) -C build aspell && ( cmp -s build/aspell inst/bin/aspell || $(MAKE) -s -C build install ) diff --git a/test/context.dat b/test/context.dat new file mode 100644 index 00000000..cb7078d3 --- /dev/null +++ b/test/context.dat @@ -0,0 +1,32 @@ +--mode=ccpp + +ccpp mode test +--- +skip me +// check me +skip me +/* check me */ +skip me +/* check me +also check me */ +skip me +"check me" +skip me +"check + me" +skip me +--- + + check me + + check me + + check me +also check me + + check me + + check + me + +--- From a9138f62bb096732519226dd736074d6d732f402 Mon Sep 17 00:00:00 2001 From: Kevin Atkinson Date: Sat, 16 Mar 2024 17:00:54 -0400 Subject: [PATCH 08/12] testing: fix running different filter tests in parallel --- test/Makefile | 4 ++-- test/filter-test | 15 ++++++++------- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/test/Makefile b/test/Makefile index 1a3b9fd3..24eb3d64 100644 --- a/test/Makefile +++ b/test/Makefile @@ -31,11 +31,11 @@ sanity: prep filter-test: markdown-filter-test context-filter-test markdown-filter-test: prep - ./filter-test "${ASPELL_WRAP} ${ASPELL}" < markdown.dat + ./filter-test markdown "${ASPELL_WRAP} ${ASPELL}" < markdown.dat echo "all ok (markdown filter-test)" >> test-res context-filter-test: prep - ./filter-test "${ASPELL_WRAP} ${ASPELL}" < context.dat + ./filter-test context "${ASPELL_WRAP} ${ASPELL}" < context.dat echo "all ok (context filter-test)" >> test-res inst/bin/aspell: build/Makefile phony diff --git a/test/filter-test b/test/filter-test index 515977c0..a939eef2 100755 --- a/test/filter-test +++ b/test/filter-test @@ -7,11 +7,12 @@ use autodie qw(:all); my $parms; my @tests; -if (@ARGV != 1) { - die("usage $0 \n"); +if (@ARGV != 2) { + die("usage $0 \n"); } -my $ASPELL=$ARGV[0]; +my $PREFIX=$ARGV[0]; +my $ASPELL=$ARGV[1]; sub sys($) { #print "@_\n"; @@ -68,13 +69,13 @@ while () { next; } - open F, ">tmp/test-data.in"; + open F, ">tmp/$PREFIX-test-data.in"; print F $in; - open F, ">tmp/test-data.expect"; + open F, ">tmp/$PREFIX-test-data.expect"; print F $out; eval { - sys "$ASPELL filter --mode=none $parms < tmp/test-data.in > tmp/test-data.out"; - sys "diff -u -Z tmp/test-data.expect tmp/test-data.out"; + sys "$ASPELL filter --mode=none $parms < tmp/$PREFIX-test-data.in > tmp/$PREFIX-test-data.out"; + sys "diff -u -Z tmp/$PREFIX-test-data.expect tmp/$PREFIX-test-data.out"; }; if ($@) { $failed++; From fa95bdff3c8a4682e413d71f19f3dbe497c8758d Mon Sep 17 00:00:00 2001 From: Kevin Atkinson Date: Sat, 16 Mar 2024 16:24:34 -0400 Subject: [PATCH 09/12] tex mode: use new context-order-num option --- modules/filter/context.cpp | 1 - modules/filter/modes/tex.amf | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/filter/context.cpp b/modules/filter/context.cpp index 190e1810..83a8d44e 100644 --- a/modules/filter/context.cpp +++ b/modules/filter/context.cpp @@ -68,7 +68,6 @@ namespace { PosibErr ContextFilter::setup(Config * config){ name_ = "context-filter"; - order_num_ = 0.15; StringList delimiters; StackPtr delimiterpairs; const char * delimiterpair=NULL; diff --git a/modules/filter/modes/tex.amf b/modules/filter/modes/tex.amf index 758fcc00..f2d37da2 100644 --- a/modules/filter/modes/tex.amf +++ b/modules/filter/modes/tex.amf @@ -7,6 +7,7 @@ MAGIC /0:256:^[ \t]*\\documentclass\[[^\[\]]*\]\{[^\{\}]*\}/tex DESCRIPTION mode for checking TeX/LaTeX documents FILTER context +OPTION context-order-num 0.15 OPTION clear-context-delimiters OPTION add-context-delimiters aspell:off aspell:on OPTION enable-context-visible-first From 5a07e6c2af775870848345b272755382c8762707 Mon Sep 17 00:00:00 2001 From: Kevin Atkinson Date: Sat, 16 Mar 2024 16:28:07 -0400 Subject: [PATCH 10/12] tex mode: add back url filter --- modules/filter/modes/tex.amf | 3 +++ 1 file changed, 3 insertions(+) diff --git a/modules/filter/modes/tex.amf b/modules/filter/modes/tex.amf index f2d37da2..aef8d49e 100644 --- a/modules/filter/modes/tex.amf +++ b/modules/filter/modes/tex.amf @@ -6,9 +6,12 @@ MAGIC /0:256:^[ \t]*\\documentclass\[[^\[\]]*\]\{[^\{\}]*\}/tex DESCRIPTION mode for checking TeX/LaTeX documents +FILTER url + FILTER context OPTION context-order-num 0.15 OPTION clear-context-delimiters OPTION add-context-delimiters aspell:off aspell:on OPTION enable-context-visible-first + FILTER tex From cc8ad28fa90ec6cc0e4391bdbf39279ce4e8fdad Mon Sep 17 00:00:00 2001 From: Kevin Atkinson Date: Sat, 16 Mar 2024 18:27:52 -0400 Subject: [PATCH 11/12] docs: tweak documentation for new tex mode, add entry to ChangeLog --- manual/aspell.texi | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/manual/aspell.texi b/manual/aspell.texi index 6210c419..aceff23a 100644 --- a/manual/aspell.texi +++ b/manual/aspell.texi @@ -1216,7 +1216,7 @@ to 'script' and 'style'. @subsubsection @TeX{}/LaTeX Filter -The @option{tex} (all lowercase) filter hides @TeX{}/LaTeX commands and +The @option{tex} (all lowercase) filter/mode hides @TeX{}/LaTeX commands and corresponding parameters that are not readable text in the output from Aspell. It also skips over @TeX{} comments by default. @@ -1352,10 +1352,11 @@ inside ignored environments with the 'T' parameter to the @end table -As a last resort, spell checking can be switched off by putting the -text @code{aspell:off} into the file. Similarly, with @code{aspell:on} -one can turn it on again. This can be useful for macro definitions, -for example +As a last resort, when the @option{tex} mode (and not just the filter) +is used, spell checking can be switched off by putting the text +@code{aspell:off} into the file. Similarly, with @code{aspell:on} one +can turn it on again. This can be useful for macro definitions, for +example @example % aspell:off @@ -3647,6 +3648,13 @@ increase. @node ChangeLog @appendix ChangeLog +@heading Changes from 0.60.8.1 to 0.60.9 (???) +@itemize @bullet +@item +Improved @option{tex} filter/mode thanks to work of Matthias. The +original filter/mode is available under the name @option{tex_v1}. +@end itemize + @heading Changes 0.60.8 to 0.60.8.1 (December 19, 2023) @itemize @bullet @item From 83356ed264162677be6a8f3b4b3c3f3ea60c3321 Mon Sep 17 00:00:00 2001 From: Kevin Atkinson Date: Sun, 31 Mar 2024 12:51:00 -0400 Subject: [PATCH 12/12] Checkpoint. FIXME: Update commit. --- manual/aspell.texi | 3 +++ modules/filter/tex.cpp | 10 ++++++---- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/manual/aspell.texi b/manual/aspell.texi index aceff23a..855e912b 100644 --- a/manual/aspell.texi +++ b/manual/aspell.texi @@ -5147,6 +5147,9 @@ Wrote the Nroff filter. Enhanced the SGML filter to also support skipping sgml tags such as "script" blocks. +@item Matthias Franz +Enhanced the @TeX{}/LaTeX Filter. + @item Kevin B. Hendricks (and Contributors) Wrote MySpell which is a simple spell checker library that supports affix compression. Aspell affix compression code is based on his code. diff --git a/modules/filter/tex.cpp b/modules/filter/tex.cpp index 16b78fe9..0ce29c38 100644 --- a/modules/filter/tex.cpp +++ b/modules/filter/tex.cpp @@ -1,8 +1,10 @@ // This file is part of The New Aspell -// Copyright (C) 2001 by Kevin Atkinson under the GNU LGPL license -// version 2.0 or 2.1. You should have received a copy of the LGPL -// license along with this library if you did not you can find -// it at http://www.gnu.org/. +// Copyright (C) 2001, 2016 Kevin Atkinson under the GNU LGPL license +// version 2.0 or 2.1. +// Copyright (C) 2011, 2022 Matthias Franz under the GNU LGPL license +// version 2.1 or (at your option) any later version. +// You should have received a copy of the LGPL license along with this library +// if you did not you can find it at http://www.gnu.org/. #include "asc_ctype.hpp" #include "config.hpp"