From 902a1c99cb166f9f90b2051b3c60cac8465451c2 Mon Sep 17 00:00:00 2001 From: visor Date: Tue, 16 Nov 2010 00:38:50 +0900 Subject: [PATCH] fix defun-wiki-command output. --- modules/ml-motor.cc | 3 +- wiki/wikicmd.cc | 210 +++++++++++++++++++++++++++++++++++++++++----------- wiki/wikicmd.h | 1 + wiki/wikienv.cc | 23 ++++++ wiki/wikienv.h | 11 +++ wiki/wikiformat.cc | 21 ++++++ wiki/wikiformat.h | 38 +++++++++- wiki/wikimotor.h | 2 +- 8 files changed, 261 insertions(+), 48 deletions(-) diff --git a/modules/ml-motor.cc b/modules/ml-motor.cc index 60db047..a1b918a 100644 --- a/modules/ml-motor.cc +++ b/modules/ml-motor.cc @@ -160,7 +160,7 @@ MNode* ml_motor_item (MNode* cell, MlEnv* mlenv) { /*DOC: ===motor-output=== (motor-output TEXT...) -> NIL -Text output via HTMLMotor. +Text output via HTMLMotor as HTML template. */ //#AFUNC motor-output ml_motor_output @@ -216,6 +216,7 @@ MNode* ml_motor_output_html (MNode* cell, MlEnv* mlenv) { /*DOC: ===motor-output-raw=== (motor-output-raw TEXT...) -> NIL +Text output asis. */ //#AFUNC motor-output-raw ml_motor_output_raw diff --git a/wiki/wikicmd.cc b/wiki/wikicmd.cc index c0b3311..c89da51 100644 --- a/wiki/wikicmd.cc +++ b/wiki/wikicmd.cc @@ -15,6 +15,9 @@ #include #include +/* +WIKICOMPAT: 1をセットすると,defun-wiki-commandで定義した関数の中で,motor-output, motor-output-rawで出力したテキストをWikiテキストとして解釈する。 +*/ /*DOC: ==行コマンド== @@ -35,6 +38,7 @@ static void do_linevec (WikiLine::linevec* block, WikiFormat* wiki) { +... +$endrepeat } +変数''VAR''に,数値''FROM''から''TO''までの値を1づつ加算しながら代入し,$endrepeatまでの間のブロックを繰り返し実行する。 */ //#WIKICMD $repeat $endrepeat wc_repeat @@ -94,11 +98,16 @@ void wc_repeat (WikiLine* wl, WikiFormat* wiki) { /*DOC: ===$doarray=== {div:pre -+$doarray:''VAR'',''VAR'',...:''INDEX_VAR'' ++$doarray:''VAR1'',''VAR2'',...[:''INDEX_VAR''] +... +$enddoarray } +配列''VAR1'', ''VAR2'', ...の各要素をそれぞれ変数''VAR1'', ''VAR2'', ...に代入しながら,$enddoarrayまでのブロックを繰り返し実行する。 +ブロックの中で変数''VAR1'', ...に代入した値は,配列に書き戻される。 +配列の長さが異なる場合は,配列''VAR1''の長さに揃えられる。 +''INDEX_VAR''を指定すると,配列のインデックス番号を変数''INDEX_VAR''に代入して,ブロックを実行する。 + */ //#WIKICMD $doarray $enddoarray wc_doarray void wc_doarray (WikiLine* wl, WikiFormat* wiki) { @@ -168,6 +177,9 @@ void wc_doarray (WikiLine* wl, WikiFormat* wiki) { +$endblock } +LISPセル''EXPR''が真のとき,$elseblockまたは$endblockまでのブロックを実行する。 +$elseblockに条件を書かないとき,それ以前のすべての条件が真でないときに次のブロックを実行する。 + */ //#WIKICMD $block $elseblock $endblock wc_block void wc_block (WikiLine* wl, WikiFormat* wiki) { @@ -285,6 +297,8 @@ void wc_setvar (WikiLine* wl, WikiFormat* wiki) { +$eval:''EXPR'' } +LISPセル''EXPR''を実行する。 + */ //#WIKICMD $eval wc_eval void wc_eval (WikiLine* wl, WikiFormat* wiki) { @@ -330,6 +344,10 @@ void wc_eval (WikiLine* wl, WikiFormat* wiki) { +$insert:VARIABLE:superuser:== } +変数''VARIABLE''に格納されたWikiテキストを挿入する。 +オプションの「=」を追加すると,「=」の数だけ挿入されるWikiテキストのタイトルの深さが下げられる。 +superuserオプションをつけると, + */ //#WIKICMD $insert wc_insert void wc_insert (WikiLine* wl, WikiFormat* wiki) { @@ -368,10 +386,12 @@ void wc_insert (WikiLine* wl, WikiFormat* wiki) { } } if (args.size () >= 1) { + AutoInclCount autoIncl (wiki->mlenv); ustring text = wiki->getVar (args[0]); WikiLine::linevec bl; wiki->headbase += hn; wiki->pass1 (text, &bl, super); + autoIncl.inc (); do_linevec (&bl, wiki); wiki->headbase -= hn; } @@ -495,6 +515,143 @@ void wc_local (WikiLine* wl, WikiFormat* wiki) { } /* ============================================================ */ +/*DOC: +===$macro=== +{div:pre ++$macro:''NAME'':''VARIABLE'',... ++... ++$endmacro ++ +$NAME:PARAM,... +} +マクロは組み込みコマンドをオーバーライドできない。 + +*/ +//#WIKICMD $macro $endmacro wc_macro +void wc_macro (WikiLine* wl, WikiFormat* wiki) { + WikiMotor motor (wl->begin, wl->end, wiki); + WikiMotorObjVec objv; + WikiMotorObjVecVec args; + ustring name; +// std::vector vars; + MNodeList vars; + int i, n; + + assert (0); // メモリ管理問題 + + if (wiki->protectMode && ! wl->fsuper) { +#ifdef DEBUG + std::cerr << "(wiki):(protected)\n"; +#endif /* DEBUG */ + return; + } + +#ifdef DEBUG + std::cerr << "(wiki):" << ustring (wl->begin0, wl->end) << "\n"; +#endif /* DEBUG */ + + motor.compile (objv); + objv.splitCharA (':', args); + if (args.size () >= 1) { + name = clipWhite (args[0]->textOut (wiki)); + } else { + wiki->errorMsg.append (CharConst ("$macro: wrong number of parameters.\n")); + return; + } + if (args.size () == 2) { + WikiMotorObjVecVec v; + args[1]->splitCharA (',', v); + for (i = 0; i < v.size (); i ++) { +// vars.push_back (clipWhite (v[i]->textOut (wiki))); + vars.append (newMNode_str (new ustring (clipWhite (v[i]->textOut (wiki))))); + } + } else if (args.size () > 2) { + wiki->errorMsg.append (CharConst ("$macro: wrong number of parameters.\n")); + } + + if (wl->block) { + wiki->env->wikienv->wikiMacro.setVar (name, vars.release (), wl->block); + wl->block = NULL; + } + +#ifdef DEBUG +// std::cerr << "(wiki):$endmacro\n"; +#endif /* DEBUG */ +} + +/* ============================================================ */ +static void call_defun_wikicmd (ustring& name, MNode* wf, WikiMotorObjVec& objv2, WikiLine* wl, WikiFormat* wiki) { + WikiMotorObjVecVec argsv; + MNodePtr vargs; + + objv2.splitCharA (':', argsv); + vargs = wiki->buildArgs (argsv.begin (), argsv.end ()); + { + MotorOutputString out; + MotorOutput* back = wiki->env->output; + WikiMotorOutputString* wikiback = wiki->env->wikioutput; + WikiMotorOutputString wikiout (wiki); + MNodePtr node; + MNodePtr bcell; + + wiki->env->wikioutput = &wikiout; + wiki->env->output = &out; + bcell = wiki->env->mlenv->currentCell; + wiki->env->mlenv->currentCell = NULL; + try { + node = execDefun (wiki->env->mlenv, wf, vargs (), name); + } catch (ustring& msg) { + wiki->logLispFunctionError (msg, ustring (wl->begin, wl->end)); + } + wiki->env->mlenv->currentCell = bcell; + if (wikiout.ans.length () > 0) { + WikiLine::linevec bl; + wiki->pass1 (wikiout.ans, &bl, wl->fsuper); + do_linevec (&bl, wiki); + } + wiki->env->wikioutput = wikiback; + if (out.ans.length () > 0) { +#ifdef WIKICOMPAT + WikiLine::linevec bl; + wiki->pass1 (out.ans, &bl, wl->fsuper); + do_linevec (&bl, wiki); +#else + wiki->pushBlockRaw (out.ans.begin (), out.ans.end ()); +#endif + } + wiki->env->output = back; + } +} + +static void call_defun_macro (ustring& name, WikiMacro* mf, WikiMotorObjVec& objv2, WikiLine* wl, WikiFormat* wiki) { + WikiMotorObjVecVec argsv; +// MNodePtr vargs; + + objv2.splitCharA (':', argsv); +// vargs = wiki->buildArgs (argsv.begin (), argsv.end ()); +// mf->mars; + { + AutoLocalVariable autoLocal (wiki->mlenv); + MNode* p = mf->vars (); + MNode* t; + MNode* v; + int i, n; + n = argsv.size (); + i = 0; + while (p && (t = p->car ())) { + if (i < n) { + v = newMNode_str (new ustring (argsv[i]->textOut (wiki))); + i ++; + } else { + v = NULL; + } + wiki->mlenv->setLocalVar (to_string (t), v); + p = p->cdr (); + } + do_linevec (mf->wl, wiki); + } +} + void wc_call_defun (WikiLine* wl, WikiFormat* wiki) { WikiMotor motor (wl->begin + 1, wl->end, wiki); WikiMotorObjVec objv; @@ -502,6 +659,7 @@ void wc_call_defun (WikiLine* wl, WikiFormat* wiki) { ustring name; MNode* wf; bool fx = true; + WikiMacro* mf; #ifdef DEBUG std::cerr << "(wiki):" << ustring (wl->begin0, wl->end) << "\n"; @@ -511,50 +669,12 @@ void wc_call_defun (WikiLine* wl, WikiFormat* wiki) { if (wiki->protectMode && ! wl->fsuper && ! wiki->env->wikienv->wikiGuestFunc.get (name)) fx = false; - if (fx && (wf = wiki->env->wikienv->wikiCmd.getVar (name))) { - WikiMotorObjVecVec argsv; - MNodePtr vargs; - - objv2.splitCharA (':', argsv); - vargs = wiki->buildArgs (argsv.begin (), argsv.end ()); - { -#ifdef WIKICOMPAT - MotorOutputString out; - MotorOutput* back = wiki->env->output; -#endif - WikiMotorOutputString* wikiback = wiki->env->wikioutput; - WikiMotorOutputString wikiout (wiki); - MNodePtr node; - MNodePtr bcell; - - wiki->env->wikioutput = &wikiout; -#ifdef WIKICOMPAT - wiki->env->output = &out; -#endif - bcell = wiki->env->mlenv->currentCell; - wiki->env->mlenv->currentCell = NULL; - try { - node = execDefun (wiki->env->mlenv, wf, vargs (), name); - } catch (ustring& msg) { - wiki->logLispFunctionError (msg, ustring (wl->begin, wl->end)); - } - wiki->env->mlenv->currentCell = bcell; - if (wikiout.ans.length () > 0) { - WikiLine::linevec bl; - wiki->pass1 (wikiout.ans, &bl, wl->fsuper); - do_linevec (&bl, wiki); - } - wiki->env->wikioutput = wikiback; -#ifdef WIKICOMPAT - if (out.ans.length () > 0) { - WikiLine::linevec bl; - wiki->pass1 (out.ans, &bl, wl->fsuper); - do_linevec (&bl, wiki); - } - wiki->env->output = back; -#endif - } - } else { + if (fx && (wf = wiki->env->wikienv->wikiCmd.getVar (name))) { // Wiki Command + call_defun_wikicmd (name, wf, objv2, wl, wiki); + } else if (mf = wiki->env->wikienv->wikiMacro.getVar (name)) { // Wiki Macro. macroは誰でも実行できる。 +// std::cerr << "macro:" << name << "\n"; + call_defun_macro (name, mf, objv2, wl, wiki); + } else { // 処理なし WikiLine::linevec bl; WikiLine* wl2; ustring u (CharConst ("^")); diff --git a/wiki/wikicmd.h b/wiki/wikicmd.h index ddeae60..c5c3648 100644 --- a/wiki/wikicmd.h +++ b/wiki/wikicmd.h @@ -15,6 +15,7 @@ void wc_eval (WikiLine* wl, WikiFormat* wiki); void wc_insert (WikiLine* wl, WikiFormat* wiki); void wc_data (WikiLine* wl, WikiFormat* wiki); void wc_local (WikiLine* wl, WikiFormat* wiki); +void wc_macro (WikiLine* wl, WikiFormat* wiki); void wc_call_defun (WikiLine* wl, WikiFormat* wiki); void wikiOutput (const ustring& text, bool fsuper, WikiFormat* wiki); diff --git a/wiki/wikienv.cc b/wiki/wikienv.cc index b6c72cc..74756db 100644 --- a/wiki/wikienv.cc +++ b/wiki/wikienv.cc @@ -4,3 +4,26 @@ #include "ustring.h" uregex re_wikicmdsep ("(:)|([ \t]+$)"); + +void MacroVar::setVar (const ustring& name, MNode* var, WikiLine::linevec* wl) { + std::pair x; + erase (name); + x = insert (value_type (name, WikiMacro ())); + x.first->second.vars = var; + x.first->second.wl = wl; +} + +WikiMacro* MacroVar::getVar (const ustring& name) { + iterator it = find (name); + if (it == end ()) { + return NULL; + } else { + return &it->second; + } +} + +bool MacroVar::defined (const ustring& name) { + iterator it = find (name); + return (it != end ()); +} + diff --git a/wiki/wikienv.h b/wiki/wikienv.h index be2e60c..0dbbbac 100644 --- a/wiki/wikienv.h +++ b/wiki/wikienv.h @@ -2,14 +2,25 @@ #define WIKIENV_H #include "motorvar.h" +#include "wikiformat.h" #include "ustring.h" +class MacroVar: public boost::unordered_map { + public: + MacroVar () {}; + virtual ~MacroVar () {}; + virtual void setVar (const ustring& name, MNode* var, WikiLine::linevec* wl); + virtual WikiMacro* getVar (const ustring& name); + virtual bool defined (const ustring& name); +}; + class WikiEnv { public: MotorVar wikiFunc2; MotorVar wikiFunc; MotorVar wikiLink; MotorVar wikiCmd; + MacroVar wikiMacro; MotorSet wikiGuestFunc; WikiEnv () {}; diff --git a/wiki/wikiformat.cc b/wiki/wikiformat.cc index 29357b4..6628c01 100644 --- a/wiki/wikiformat.cc +++ b/wiki/wikiformat.cc @@ -1846,6 +1846,19 @@ void WikiBlockHR::output (MotorOutput* out) { } /* ============================================================ */ +bool WikiBlockRaw::nextLine (uiterator b, uiterator e) { + return false; +} + +void WikiBlockRaw::addLine (uiterator b, uiterator e) { + text.assign (b, e); +} + +void WikiBlockRaw::output (MotorOutput* out) { + out->out_toText (text); +} + +/* ============================================================ */ void WikiFormat::pass1 (const ustring& text, WikiLine::linevec* block, bool fsuper) { Splitter sp (text, re_nl); @@ -2208,6 +2221,14 @@ void WikiFormat::compileLines (WikiLineScanner& scanner, bool (*fn)(WikiLine& s } } +void WikiFormat::pushBlockRaw (uiterator b, uiterator e) { + WikiBlockRaw* obj; + + obj = new WikiBlockRaw (this); + blockp->push_back (obj); + obj->addLine (b, e); +} + int WikiFormat::countWikiH (uiterator& b, uiterator e) { int ans = 0; diff --git a/wiki/wikiformat.h b/wiki/wikiformat.h index 4b909c5..e48405d 100644 --- a/wiki/wikiformat.h +++ b/wiki/wikiformat.h @@ -1,7 +1,7 @@ #ifndef WIKIFORMAT_H #define WIKIFORMAT_H -#include "wikienv.h" +//#include "wikienv.h" #include "wikimotor.h" #include "wikitable.h" #include "motoroutput.h" @@ -81,6 +81,28 @@ class WikiLine { }; +class WikiMacro { + public: + MNodePtr vars; + WikiLine::linevec* wl; + +#if 0 + WikiMacro (MNode* _vars, WikiLine::linevec* _wl) { + vars = _vars; + wl = _wl; + }; +#endif + WikiMacro () { + wl = NULL; + }; + virtual ~WikiMacro () { +// delete vars; +// vars = NULL; + delete wl; + wl = NULL; + }; +}; + class WikiLineScanner { public: WikiLine::linevec* wlv; @@ -292,6 +314,7 @@ class WikiBlock { BlockDiv, BlockForm, BlockHR, + BlockRaw, } blockType; typedef enum { CloseNA, @@ -586,6 +609,18 @@ class WikiBlockHR: public WikiBlock { virtual void output (MotorOutput* out); }; +class WikiBlockRaw: public WikiBlock { + public: + ustring text; + + WikiBlockRaw(WikiFormat* w): WikiBlock (BlockRaw, w) {}; + virtual ~WikiBlockRaw () {}; + + virtual bool nextLine (uiterator b, uiterator e); + virtual void addLine (uiterator b, uiterator e); + virtual void output (MotorOutput* out); +}; + class WikiFormat { public: typedef enum { @@ -644,6 +679,7 @@ class WikiFormat { virtual bool checkClose (uiterator b, uiterator e); virtual void compileLine (WikiLineScanner& scanner); virtual void compileLines (WikiLineScanner& scanner, bool (*fn)(WikiLine& spp, WikiLineScanner& scanner, WikiFormat* wiki, void* par) = false, void* par = false); + virtual void pushBlockRaw (uiterator b, uiterator e); virtual void push_block (boost::ptr_vector* b) { bstack.push_back (cur); cur = NULL; diff --git a/wiki/wikimotor.h b/wiki/wikimotor.h index a4ec4a4..7f7d46f 100644 --- a/wiki/wikimotor.h +++ b/wiki/wikimotor.h @@ -2,7 +2,7 @@ #define WIKIMOTOR_H #include "wikitable.h" -#include "wikienv.h" +//#include "wikienv.h" #include "motor.h" #include "ml.h" #include "util_splitter.h" -- 2.11.0