From 4dd8a4ed0ad7e8ef49b7c40cd96cc6d98b8410f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20P=C3=B6nitz?= Date: Fri, 24 May 2002 08:29:16 +0000 Subject: [PATCH] First shot at "auto correction" feature in mathed git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@4195 a592a061-630c-0410-9148-cb99ea01b6c8 --- lib/ChangeLog | 5 + lib/autocorrect | 352 ++++++++++++++++++++++++++++++++++ src/mathed/ChangeLog | 8 + src/mathed/Makefile.am | 2 + src/mathed/math_autocorrect.C | 168 ++++++++++++++++ src/mathed/math_autocorrect.h | 9 + src/mathed/math_cursor.C | 26 ++- src/mathed/math_cursor.h | 3 +- src/mathed/math_inset.C | 11 +- src/mathed/math_inset.h | 1 + src/mathed/math_parser.C | 9 +- 11 files changed, 587 insertions(+), 7 deletions(-) create mode 100644 lib/autocorrect create mode 100644 src/mathed/math_autocorrect.C create mode 100644 src/mathed/math_autocorrect.h diff --git a/lib/ChangeLog b/lib/ChangeLog index ee0a7b798c..96213a0747 100644 --- a/lib/ChangeLog +++ b/lib/ChangeLog @@ -1,3 +1,8 @@ + +2002-05-23 André Pönitz + + * lib/autocorrect: new file + 2002-05-03 Claus Hindsgaul * examples/da_splash.lyx: revised diff --git a/lib/autocorrect b/lib/autocorrect new file mode 100644 index 0000000000..14526f79bf --- /dev/null +++ b/lib/autocorrect @@ -0,0 +1,352 @@ + +# +# Idea of "autocorrection" and parts of this file are shamelessly stolen +# from TeXMacs (they give vdhoeven@texmacs.org as contact) +# +# We do it a bit differently and allow corrections only to combine a symbol +# and a char to a new symbol. +# +# + +| , \lfloor +\lfloor * |, +| ' \lceil +\lceil * |' +, | \rfloor +\rfloor * ,| +' | \rceil +\rceil * '| +\llbracket * [[* +\rrbracket * ]]* + +\cap * \sqcap +\cup * \sqcup +\vee * \curlyvee +\curlyvee * \curlyveeuparrow +\curlyveeuparrow * \curlyveedownarrow + +< / \nless +> / \ngtr +< = \leqslant +> = \geqslant +\leqslant / \nleqslant +\geqslant / \ngeqslant +\leqslant * \leq +\geslant * \geq +\leq / \nleq +\geq / \ngeq +< < \ll +\ll < \lll +> > \gg +\gg > \ggg +\ll = \lleq +\lll = \llleq +\gg = \ggeq +\ggg = \gggeq +\ll / \nll +\lll / \nlll +\gg / \ngg +\ggg / \nggg +\lleq / \nlleq +\llleq / \nllleq +\ggeq / \nggeq +\gggeq / \ngggeq +< . \lessdot +. > \gtrdot +\leqslant . \lesseqdot +\gtrdot = \gtreqdot + +< * \prec +> * \succ +\prec / \nprec +\succ / \nsucc +\prec = \preccurlyeq +\succ = \succcurlyeq +\preccurlyeq / \npreccurlyeq +\succcurlyeq / \nsucccurlyeq +\preccurlyeq * \preceq +\succcurlyeq * \succeq +\preceq / \npreceq +\succeq / \nsucceq +\npreceq * \precneqq +\nsucceq * \succneqq +\ll * \precprec +\precprec * \precprecprec +\gg * \succsucc +\succsucc * \succsuccsucc +\precprec = \precpreceq +\lll * \precprecprec +\precprecprec = \precprecpreceq +\succsucc = \succsucceq +\ggg = \succsuccsucc +\succsuccsucc = \succsuccsucceq +\precprec / \nprecprec +\precprecprec / \nprecprecprec +\succsucc / \nsuccsucc +\succsuccsucc / \nsuccsuccsucc +\precpreceq / \nprecpreceq +\precprecpreceq / \nprecprecpreceq +\succsucceq / \nsuccsucceq +\succsuccsucceq / \nsuccsuccsucceq + +\prec . \precdot +\succ . \dotsucc +\precdot . \preceqdot +\dotsucc . \dotsucceq +\precprec * \llangle +\succsucc * \rrangle + +< > \lessgtr +> < \gtrless +< ~ \lesssim +\lesssim ~ \lessapprox +\prec ~ \precsim +\precsim ~ \precapprox +> ~ \gtrsim +\gtrsim ~ \gtrapprox +\succ ~ \gtrsim +\gtrsim ~ \gtrapprox +\leq * \leqq +\geq * \geqq +\leq > \lesseqgtr +\geq < \gtrqless + +- > \rightarrow +< - \leftarrow +\leftarrow > \leftrightarrow +\rightarrow - \longrightarrow +\leftarrow - \longleftarrow +\longleftarrow > \longleftrightarrow += > \Rightarrow + + +@ * \circ +\circ / \varnothing +\circ + \oplus +\circ - \ominus +@ x \otimes +\circ : \oover +\circ . \odot +@ R \circledR +@ S \circledS +\varnothing * \oslash +@ \ \obslash +@ @ \infty +\circ < \olessthan +\circ > \ogreaterthan +\circ & \owedge +\circ | \obar +\obar * \ovee +\circ v \ovee +\circ @ \infty +@@ * \varocircle +-@ @ \infty +\circ * \box +\box + \boxplus +\box - \boxminus +\box x \boxtimes +\box . \boxdot +\box / \boxslash +\box \ \boxbslash +\box @ \boxcircle +\boxcircle * \boxbox +\box | \boxbar +\box * \bullet +\bullet * \blacksquare + += * \asymp +\asymp * \equiv +\equiv * \asympasymp +\asympasymp * \simsim +~ * \sim +\sim ~ \approx +\approx - \approxeq +\sim - \simeq +\sim = \cong += / \neq +\asymp / \nasymp +\equiv / \nequiv +\asympasymp / \nasympasymp +\simsim / \nsimsim +\sim / \nsim +\approx / \napprox +\simeq / \nsimeq +\cong / \ncong + +#| \| +| * \shortmid +\shortmid * \varshortmid +| | \|| +\|| | \interleave +\|| * \shortparallel +| - \vdash +\vdash - \longvdash +\|| - \Vdash +\Vdash - \longVdash +\interleave - \Vvdash +\Vvdash - \longVvdash +- | \dashv + +< | \vartriangleleft +\vartriangleleft * \blacktriangleleft +\vartriangleleft / \ntriangleleft +\vartriangleleft = \trianglelefteqslant +\trianglelefteqslant / \ntrianglelefteqslant +\trianglelefteqslant * \trianglelefteq +\trianglelefteq / \ntriangleqleft +| > \vartriangleright +\vartriangleright * \blacktriangleright +\vartriangleright / \ntriangleright +\vartriangleright = \trianglerighteq +\trianglerighteq / \ntriangleqright +\trianglerighteq * \trianglerighteqslant +\trianglerighteqslant / \ntrianglerighteqslant + +- * \um ++ - \pm +\pm * \upm +- + \mp +\mp * \ump +@ = \circeq += @ \eqcirc +- @ \multimap +. = \doteq +. . \ldots +\ldots * \cdots +\cdots * \hdots +\hdots * \vdots +\ddots * \ddots +\udots * \udots +: = \assign ++ = \plusassign +- = \minusassign +/ * \div +* * \ast +\ast * \times +\times * \cdot + +< * \subset +\subset * \in +\ / \nsubset +\in * \sqsubset +\subset = \subseteq +\subseteq / \nsubseteq +\subseteq * \subseteqq +\sqsubset * \langle +\langle * \leftslice +\leftslice * \subset + +\subseteq / \nsubseteq +\subseteqq / \nsubseteqq +\nsubseteqq * \subsetneq +\subsetneq * \varsubsetneq +\varsubsetneq * \subsetneqq +\subsetneqq * \varsubsetneqq +\subset + \subsetplus +\subsetplus = \subsetpluseq +\subseteq + \subsetpluseq +\in / \nin +> * \supset +\supset / \nsupset +\supset = \supseteq +\supseteq / \nsupseteq +\supseteq * \supseteqq +\supseteq / \nsupseteq + + +\supseteqq / \nsupseteqq +\supseteq / \supsetneq +\supset + \supsetplus +\supsetplus = \supsetpluseq +\supseteq + \supsetpluseq +\supset * \ni +\ni / \nni + +# +# The following is available in TeXMacs, but not (yet) in LyX +# + +#--| \longdashv +#| = \vDash +#\vDash = \longvDash +#||= \VDash +#||== \longVDash +#| / \nmid +#||/ \nparallel +#|*/ \nshortmid +#||*/ \nshortparallel +#|-/ \nvdash +#||-/ \nVdash +#-|/ \ndashv +#-||/ \ndashV +#|=/ \nvDash +#||=/ \nVDash +#=|/ \nDashv +#=||/ \nDashV +# +#<=**> \lesseqqgtr +#>=**< \gtreqqless +#<>/ \nlessgtr +#>~/ \ngtrsim +#>~/* \gnsim +#>~~/ \ngtrapprox +#>~~/* \gnapprox +#>*~/ \nsuccsim +#>*~/* \succnsim +#>*~~/ \nsuccapprox +#>*~~/* \succnapprox +#<=**/ \nleqq +#>=**/ \ngeqq +#<=*>/ \nlesseqgtr +#>=*/ \nlesseqqgtr +#>=**=*/* \gneq +#>=**/* \gneqq +#>=**/** \gvertneqq +#[[ * \llbracket +#]] * \rrbracket +#EE a \amalg +#EE d \partial +#EE p \wp +#EE n \cap +#EE u \cup +#EE w \wedge +#\wedge * \curlywedge +#\curlywedge * \curlywedgeuparrow +#\curlywedgeuparrow * \curlywedgedownarrow +#\curlywedgedownarrow * \wedges +#EE v \vee +#EE x \times + +# <***/ \nsqsubset +# <***= \sqsubseteq +# <***=/ \nsqsubseteq +# >*=/** \varsupsetneq +# >*=*/* \supsetneqq +# >*=*/** \varsupsetneqq +# >*** \sqsupset +# >***/ \nsqsupset +# >***= \sqsupseteq +# >***=/ \nsqsupseteq + +# >**** \rangle +# \rangle * \rightslice + +# EE l \bigl +# EE m \bigm +# EE r \bigr +# EE @ \bigop +# EE L \int diff --git a/src/mathed/ChangeLog b/src/mathed/ChangeLog index 245fbae75f..5e7dfffe2f 100644 --- a/src/mathed/ChangeLog +++ b/src/mathed/ChangeLog @@ -1,3 +1,11 @@ + +2002-05-23 André Pönitz + + * math_autocorrect.[Ch]: new "auto correction" feature + * math_cursor.[Ch]: subsequent changes + * math_parser.C: somewhat better error reporting + + 2002-05-23 John Levon * formula.C: diff --git a/src/mathed/Makefile.am b/src/mathed/Makefile.am index 2013797755..ef3b14b3d2 100644 --- a/src/mathed/Makefile.am +++ b/src/mathed/Makefile.am @@ -19,6 +19,8 @@ libmathed_la_SOURCES = \ math_arrayinset.h \ math_atom.C \ math_atom.h \ + math_autocorrect.C \ + math_autocorrect.h \ math_biginset.C \ math_biginset.h \ math_binominset.C \ diff --git a/src/mathed/math_autocorrect.C b/src/mathed/math_autocorrect.C new file mode 100644 index 0000000000..5d371a6ee8 --- /dev/null +++ b/src/mathed/math_autocorrect.C @@ -0,0 +1,168 @@ +#include + +#include "LString.h" +#include "Lsstream.h" +#include "debug.h" +#include "support/filetools.h" // LibFileSearch +#include "math_data.h" +#include "math_inset.h" +#include "math_parser.h" + +#include +#include + +using std::ifstream; +using std::istream; +using std::ostream; +using std::endl; + + +namespace { + +class Correction { +public: + /// + Correction() {} + /// + bool correct(MathAtom & at, char c) const; + /// + bool read(istream & is); + /// + void write(ostream & os) const; +private: + /// + MathAtom from1_; + /// + char from2_; + /// + MathAtom to_; +}; + + +bool Correction::read(istream & is) +{ + string s1, s2, s3; + is >> s1 >> s2 >> s3; + if (!is) + return false; + MathArray ar1, ar3; + mathed_parse_cell(ar1, s1); + mathed_parse_cell(ar3, s3); + if (ar1.size() != 1 || s2.size() != 1 || ar3.size() !=1) + return false; + from1_ = ar1.front(); + from2_ = s2[0]; + to_ = ar3.front(); + return true; +} + + +void Correction::write(ostream & os) const +{ + os << "from: '" << from1_ << "' and '" << from2_ + << "' to '" << to_ << "'" << endl; +} + + +bool Correction::correct(MathAtom & at, char c) const +{ + //lyxerr[Debug::MATHED] + // << "trying to correct ar: " << at << " from: '" << from1_ << "'" << endl; + if (from2_ != c) + return false; + if (!at->match(from1_.nucleus())) + return false; + lyxerr[Debug::MATHED] + << "match found! subst in " << at + << " from: '" << from1_ << "' to '" << to_ << "'" << endl; + at = to_; + return true; +} + + +istream & operator>>(istream & is, Correction & corr) +{ + corr.read(is); + return is; +} + + +ostream & operator<<(ostream & os, Correction & corr) +{ + corr.write(os); + return os; +} + + + + +class Corrections { +public: + /// + typedef vector::const_iterator const_iterator; + /// + Corrections() {} + /// + void insert(const Correction & corr) { data_.push_back(corr); } + /// + bool correct(MathAtom & at, char c) const; +private: + /// + vector data_; +}; + + +bool Corrections::correct(MathAtom & at, char c) const +{ + for (const_iterator it = data_.begin(); it != data_.end(); ++it) + if (it->correct(at, c)) + return true; + return false; +} + + +Corrections theCorrections; + +void initAutoCorrect() +{ + lyxerr[Debug::MATHED] << "reading autocorrect file" << endl; + string const file = LibFileSearch(string(), "autocorrect"); + if (file.empty()) { + lyxerr << "Could not find autocorrect file" << endl; + return; + } + + string line; + ifstream is(file.c_str()); + while (getline(is, line)) { + if (line.size() == 0 || line[0] == '#') { + //lyxerr[Debug::MATHED] << "ignoring line '" << line << "'" << endl; + continue; + } + istringstream il(line); + //lyxerr[Debug::MATHED] << "line '" << line << "'" << endl; + Correction corr; + if (corr.read(il)) { + //lyxerr[Debug::MATHED] << "parsed: '" << corr << "'" << endl; + theCorrections.insert(corr); + } + } + + lyxerr[Debug::MATHED] << "done reading autocorrections." << endl; +} + + +} // namespace anon + + +bool math_autocorrect(MathAtom & at, char c) +{ + static bool initialized = false; + + if (!initialized) { + initAutoCorrect(); + initialized = true; + } + + return theCorrections.correct(at, c); +} diff --git a/src/mathed/math_autocorrect.h b/src/mathed/math_autocorrect.h new file mode 100644 index 0000000000..30495d05b0 --- /dev/null +++ b/src/mathed/math_autocorrect.h @@ -0,0 +1,9 @@ +#ifndef MATHAUTOCORRECT_H +#define MATHAUTOCORRECT_H + +class MathAtom; + +// make "corrections" according to file lib/autocorrect +bool math_autocorrect(MathAtom & at, char c); + +#endif diff --git a/src/mathed/math_cursor.C b/src/mathed/math_cursor.C index 36834e7612..2f6b608b46 100644 --- a/src/mathed/math_cursor.C +++ b/src/mathed/math_cursor.C @@ -29,6 +29,7 @@ #include "frontends/Painter.h" #include "math_cursor.h" #include "formulabase.h" +#include "math_autocorrect.h" #include "math_arrayinset.h" #include "math_braceinset.h" #include "math_boxinset.h" @@ -182,7 +183,8 @@ Selection theSelection; MathCursor::MathCursor(InsetFormulaBase * formula, bool left) - : formula_(formula), lastcode_(LM_TC_MIN), selection_(false) + : formula_(formula), lastcode_(LM_TC_MIN), + autocorrect_(false), selection_(false) { left ? first() : last(); } @@ -299,6 +301,7 @@ bool MathCursor::posRight() bool MathCursor::left(bool sel) { dump("Left 1"); + autocorrect_ = false; if (inMacroMode()) { macroModeClose(); lastcode_ = LM_TC_MIN; @@ -319,6 +322,7 @@ bool MathCursor::left(bool sel) bool MathCursor::right(bool sel) { dump("Right 1"); + autocorrect_ = false; if (inMacroMode()) { macroModeClose(); lastcode_ = LM_TC_MIN; @@ -351,7 +355,7 @@ void MathCursor::last() bool positionable(MathCursor::cursor_type const & cursor, - MathCursor::cursor_type const & anchor) + MathCursor::cursor_type const & anchor) { // avoid deeper nested insets when selecting if (cursor.size() > anchor.size()) @@ -386,6 +390,7 @@ void MathCursor::setPos(int x, int y) void MathCursor::home(bool sel) { dump("home 1"); + autocorrect_ = false; selHandle(sel); macroModeClose(); lastcode_ = LM_TC_MIN; @@ -398,6 +403,7 @@ void MathCursor::home(bool sel) void MathCursor::end(bool sel) { dump("end 1"); + autocorrect_ = false; selHandle(sel); macroModeClose(); lastcode_ = LM_TC_MIN; @@ -498,6 +504,7 @@ void MathCursor::paste(MathArray const & ar) void MathCursor::backspace() { + autocorrect_ = false; if (pos() == 0) { pullArg(false); return; @@ -523,6 +530,7 @@ void MathCursor::backspace() void MathCursor::erase() { + autocorrect_ = false; if (inMacroMode()) return; @@ -556,6 +564,7 @@ void MathCursor::erase() void MathCursor::delLine() { + autocorrect_ = false; macroModeClose(); if (selection_) { @@ -586,6 +595,7 @@ bool MathCursor::up(bool sel) if (goUpDown(true)) return true; Cursor_ = save; + autocorrect_ = false; return selection_; } @@ -599,6 +609,7 @@ bool MathCursor::down(bool sel) if (goUpDown(false)) return true; Cursor_ = save; + autocorrect_ = false; return selection_; } @@ -1490,6 +1501,12 @@ bool MathCursor::interpret(char c) return true; } + // leave autocorrect mode if necessary + if (autocorrect_ && c == ' ') { + autocorrect_ = false; + return true; + } + // just clear selection on pressing the space par if (selection_ && c == ' ') { selClear(); @@ -1563,9 +1580,14 @@ bool MathCursor::interpret(char c) return true; } + // try auto-correction + if (autocorrect_ && hasPrevAtom() && math_autocorrect(prevAtom(), c)) + return true; + // no special circumstances, so insert the character without any fuss insert(c, lastcode_ == LM_TC_MIN ? MathCharInset::nativeCode(c) : lastcode_); lastcode_ = LM_TC_MIN; + autocorrect_ = true; return true; } diff --git a/src/mathed/math_cursor.h b/src/mathed/math_cursor.h index 3f03b6fa4e..350de76ad9 100644 --- a/src/mathed/math_cursor.h +++ b/src/mathed/math_cursor.h @@ -287,7 +287,8 @@ private: InsetFormulaBase * formula_; /// text code of last char entered MathTextCodes lastcode_; - // Selection stuff + /// do we allow autocorrection + bool autocorrect_; /// do we currently select bool selection_; }; diff --git a/src/mathed/math_inset.C b/src/mathed/math_inset.C index 41b40a4474..3210b3558f 100644 --- a/src/mathed/math_inset.C +++ b/src/mathed/math_inset.C @@ -38,6 +38,16 @@ int MathInset::height() const } +ostream & operator<<(ostream & os, MathAtom const & at) +{ + if (at.nucleus()) + os << *(at.nucleus()); + else + os << "(nil)"; + return os; +} + + ostream & operator<<(ostream & os, MathInset const & inset) { WriteStream wi(os, false, false); @@ -45,7 +55,6 @@ ostream & operator<<(ostream & os, MathInset const & inset) return os; } - MathInset::size_type MathInset::nargs() const { return 0; diff --git a/src/mathed/math_inset.h b/src/mathed/math_inset.h index 3bdff2dbbf..eafdc3e2bb 100644 --- a/src/mathed/math_inset.h +++ b/src/mathed/math_inset.h @@ -255,5 +255,6 @@ public: }; std::ostream & operator<<(std::ostream &, MathInset const &); +std::ostream & operator<<(std::ostream &, MathAtom const &); #endif diff --git a/src/mathed/math_parser.C b/src/mathed/math_parser.C index 35a555650e..a7bb6be11d 100644 --- a/src/mathed/math_parser.C +++ b/src/mathed/math_parser.C @@ -420,8 +420,10 @@ bool Parser::good() const char Parser::getChar() { - if (!good()) + if (!good()) { lyxerr << "The input stream is not well..." << endl; + dump(); + } return tokens_[pos_++].character(); } @@ -486,7 +488,7 @@ void Parser::tokenize(string const & buffer) char c; while (is.get(c)) { - //lyxerr << "reading c: " << c << "\n"; + lyxerr << "reading c: " << c << "\n"; switch (catcode(c)) { case catNewline: { @@ -1030,8 +1032,8 @@ void Parser::parse_into1(MathArray & array, unsigned flags, MathTextCodes code) else if (t.cat() == catEnd) { if (flags & FLAG_BRACE_LAST) return; - dump(); lyxerr << "found '}' unexpectedly, array: '" << array << "'\n"; + dump(); //lyxerr << "found '}' unexpectedly\n"; //lyx::Assert(0); //add(array, '}', LM_TC_TEX); @@ -1039,6 +1041,7 @@ void Parser::parse_into1(MathArray & array, unsigned flags, MathTextCodes code) else if (t.cat() == catAlign) { lyxerr << "found tab unexpectedly, array: '" << array << "'\n"; + dump(); //lyxerr << "found tab unexpectedly\n"; add(array, '&', LM_TC_TEX); }