Check-in [b99aa66d1f]
Not logged in
Overview

SHA1 Hash:b99aa66d1f91abf5b01c793e5bbc7df2df98b0a0
Date: 2009-10-05 20:05:22
User: robert
Comment:add wiki-contents macro to creole parser, plus minor bug fix
Timelines: ancestors | descendants | both | creole
Other Links: files | ZIP archive | manifest

Tags And Properties
Changes
[hide diffs]

Modified src/creoleparser.c from [e5d7a584f0] to [54d077bd42].

@@ -58,14 +58,21 @@
 #define KIND_SUBSCRIPT       0x0002000
 #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;
   char *end;
@@ -110,13 +117,10 @@
   int inLink;
   int inTable;
   int iesc;
 
   Blob *iblob;
-
-
-
 
 };
 //}}}
 
 #endif
@@ -199,11 +203,11 @@
           return z + 2;
         }
         z[0] = '\n';
         return z + 1;
 
-      case'\n':
+      case '\n':
         return z + 1;
 
       case '\t':
         z[0] = ' ';
         z++;
@@ -222,10 +226,11 @@
     }
   }
 }
 //}}}
 //}}}
+
 
 //{{{ INLINE PARSER
 
 static int cr_isEsc(Parser *p){//{{{
   if (p->iesc){
@@ -359,11 +364,11 @@
   if (p->icursor[1]!='{' || p->icursor[2]!='{')
     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;
       return 1;
@@ -701,10 +706,23 @@
   p->inTable = 0;
 
 }
 //}}}
 
+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);
     cr_parseInline(p, node->start, node->end );
@@ -717,10 +735,15 @@
         node->level,
         (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){
     blob_append(p->iblob, "<hr />", -1);
@@ -813,11 +836,11 @@
   p->this->start = s;
   p->this->kind = KIND_END_WIKI_MARKER;
   p->cursor += 10;
   return 1;
 }
-///}}}
+//}}}
 static int isNoWikiBlock(Parser *p){//{{{
 
   char *s = p->cursor;
 
   if (s[0] != '{') return 0; s++;
@@ -845,10 +868,39 @@
   char *s = cr_nextLine(p, p->cursor);
   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){//{{{
 
@@ -977,10 +1029,11 @@
   p->this->kind = KIND_PARAGRAPH;
   return 1;
 
 }
 //}}}
+
 static void cr_parse(Parser *p, char* z){//{{{
 
   p->previous = pool_new(p);
   p->previous->kind = KIND_PARA_BREAK;
 
@@ -1001,10 +1054,11 @@
       // must be first
       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;
 
@@ -1037,10 +1091,50 @@
 
   }
 }
 //}}}
 
+//}}}
+
+//{{{ 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){
 
   Parser parser;