Diff
Not logged in

Differences From:

File src/creoleparser.c part of check-in [cacb8db398] - Minor fixes to creole by robert on 2009-09-26 14:33:22. [view]

To:

File src/creoleparser.c part of check-in [b99aa66d1f] - add wiki-contents macro to creole parser, plus minor bug fix by robert on 2009-10-05 20:05:22. [view]

@@ -59,12 +59,19 @@
 #define KIND_MONOSPACED      0x0004000
 #define KIND_BREAK           0x0008000
 
 #define KIND_TABLE_ROW       0x0010000
+#define KIND_MACRO           0X0020000
+//}}}
+//{{{ MACRO
+#define MACRO_NONE           0X0000000
+#define MACRO_FOSSIL         0x0000001
+#define MACRO_WIKI_CONTENTS  0X0000002
 //}}}
 //{{{ FLAG
-// keep first four bits free
-#define FLAG_CENTER   0x0000100
+// keep first four bits free (why?:)
+#define FLAG_CENTER      0x0000100
+#define FLAG_MACRO_BLOCK 0X0000200
 //}}}
 struct Node {//{{{
 
   char *start;
@@ -111,11 +118,8 @@
   int inTable;
   int iesc;
 
   Blob *iblob;
-
-
-
 
 };
 //}}}
 
@@ -200,9 +204,9 @@
         }
         z[0] = '\n';
         return z + 1;
 
-      case'\n':
+      case '\n':
         return z + 1;
 
       case '\t':
         z[0] = ' ';
@@ -223,8 +227,9 @@
   }
 }
 //}}}
 //}}}
+
 
 //{{{ INLINE PARSER
 
 static int cr_isEsc(Parser *p){//{{{
@@ -360,9 +365,9 @@
     return 0;
 
   char *s = p->icursor + 3;
 
-  int count = p->iend - p->icursor - 6;
+  int count = p->iend - p->icursor - 3;
   while (count--){
     if (s[0]=='}' && s[1]=='}' && s[2]=='}' && s[3]!='}'){
       blob_appendf(p->iblob, "<tt class='creole-inline-nowiki'>%s</tt>", htmlize(p->icursor + 3, s - p->icursor-3));
       p->icursor = s + 3;
@@ -702,8 +707,21 @@
 
 }
 //}}}
 
+static void cr_renderMacro(Parser *p, Node *n){//{{{
+
+  switch (n->level){
+
+    case MACRO_WIKI_CONTENTS:
+      do_macro_wiki_contents(p, n);
+      break;
+
+  }
+
+}
+//}}}
+
 static void cr_render(Parser *p, Node *node){//{{{
 
   if (node->kind & KIND_PARAGRAPH){
     blob_append(p->iblob,   "\n<p>", -1);
@@ -718,8 +736,13 @@
         (node->flags & FLAG_CENTER) ? " style='text-align:center;'" : ""
     );
     cr_parseInline(p, node->start, node->end);
     blob_appendf(p->iblob, "</h%d>\n", node->level  );
+    return;
+  }
+
+  if (node->kind & KIND_MACRO){
+    cr_renderMacro(p, node);
     return;
   }
 
   if (node->kind & KIND_HORIZONTAL_RULE){
@@ -814,9 +837,9 @@
   p->this->kind = KIND_END_WIKI_MARKER;
   p->cursor += 10;
   return 1;
 }
-///}}}
+//}}}
 static int isNoWikiBlock(Parser *p){//{{{
 
   char *s = p->cursor;
 
@@ -846,8 +869,37 @@
   if (!p->lineWasBlank) return 0;
 
   p->cursor = s;
   p->this->kind = KIND_PARA_BREAK;
+  return 1;
+}
+//}}}
+static int isMacro(Parser *p){//{{{
+
+  char *s = p->cursor;
+  int macroId;
+  int matchLength;
+
+  if (s[0]!='<') return 0; s++;
+  if (s[0]!='<') return 0; s++;
+  if (s[0]=='<') return 0;
+
+  matchLength = cr_has_macro(s, &macroId);
+  if (!matchLength) return 0;
+
+  s += matchLength;
+  p->this->start = s;
+
+  if (s[-1]!='>'){
+    while (s[0] && s[1] && s[0]!='\n' && !(s[0]=='>' && s[1]=='>')) s++;
+    if (!(s[0] == '>' && s[1] == '>')) return 0;
+    s +=2;
+  }
+  p->cursor = s;
+  p->this->kind = KIND_MACRO;
+  p->this->level = macroId;
+  p->this->flags &= FLAG_MACRO_BLOCK;
+  p->this->end = s-2;
   return 1;
 }
 //}}}
 static int isHeading(Parser *p){//{{{
@@ -978,8 +1030,9 @@
   return 1;
 
 }
 //}}}
+
 static void cr_parse(Parser *p, char* z){//{{{
 
   p->previous = pool_new(p);
   p->previous->kind = KIND_PARA_BREAK;
@@ -1002,8 +1055,9 @@
       if (isNoWikiBlock(p)) break;
       if (isParaBreak(p))   break;
 
       // order not important
+      if (isMacro(p)) break;
       if (isHeading(p)) break;
       if (isHorizontalRule(p)) break;
       if (isListItem(p)) break;
       if (isTable(p)) break;
@@ -1038,8 +1092,48 @@
   }
 }
 //}}}
 
+//}}}
+
+//{{{ MACROS
+LOCAL void do_macro_wiki_contents(Parser *p, Node *n){//{{{
+
+  Stmt q;
+
+  blob_append(p->iblob, "<ul>", 4);
+
+  db_prepare(&q,
+    "SELECT substr(tagname, 6, 1000) FROM tag WHERE tagname GLOB 'wiki-*'"
+    " ORDER BY lower(tagname)"
+  );
+  while( db_step(&q)==SQLITE_ROW ){
+    const char *zName = db_column_text(&q, 0);
+    blob_appendf(p->iblob, "<li><a href=\"%s/wiki?name=%T\">%h</a></li>", g.zBaseURL, zName, zName);
+  }
+  db_finalize(&q);
+  blob_append(p->iblob, "</ul>", 5);
+}//}}}
+
+
+static int cr_match(char *z1, char *z2, int *len){
+  *len = strlen(z2);
+  return !memcmp(z1, z2 ,*len);
+}
+
+int cr_has_macro(char *z, int *tokenType){
+
+  int len;
+
+  if (cr_match(z, "wiki-contents>>", &len)) {
+    *tokenType = MACRO_WIKI_CONTENTS;
+    return len;
+  }
+
+  tokenType = MACRO_NONE;
+  return 0;
+
+}
 //}}}
 
 char *wiki_render_creole(Renderer *r, char *z){