Merge pull request #38 from FreeBirdLjj/issue#16
authorMichael Göhler <somebody.here@gmx.de>
Sat, 27 Sep 2014 10:24:02 +0000 (12:24 +0200)
committerMichael Göhler <somebody.here@gmx.de>
Sat, 27 Sep 2014 10:24:02 +0000 (12:24 +0200)
Issue#16

README.md
include/common.h [new file with mode: 0644]
include/markdown.h
include/parser.h
sample.md
src/parser.c
src/viewer.c

index 027b59b..cbf3326 100644 (file)
--- a/README.md
+++ b/README.md
@@ -34,10 +34,12 @@ _Supports basic markdown formating:_
     - headlines
     - code
     - quotes
+    - unordered list
 
 - in-line formating
     - bold text
     - underlined text
+    - code
 
 _Supports headers prefixed by @ symbol._
 
diff --git a/include/common.h b/include/common.h
new file mode 100644 (file)
index 0000000..23b656c
--- /dev/null
@@ -0,0 +1,7 @@
+#if !defined( COMMON_H )
+#define COMMON_H
+
+#define MAX(a, b) ({ typeof(a) _a = a; typeof(b) _b = b; _a > _b? _a : _b; })
+#define MIN(a, b) ({ typeof(a) _a = a; typeof(b) _b = b; _a < _b? _a : _b; })
+
+#endif // !defined( COMMON_H )
index 7c786ef..a1dd759 100644 (file)
@@ -44,6 +44,9 @@ enum line_bitmask {
     IS_QUOTE,
     IS_CODE,
     IS_HR,
+    IS_UNORDERED_LIST_1,
+    IS_UNORDERED_LIST_2,
+    IS_UNORDERED_LIST_3,
     IS_EMPTY
 };
 
index 2690b20..1a113e0 100644 (file)
  *
  */
 
+#include "common.h"
 #include "markdown.h"
 
 #define EXPAND_TABS 4
 #define CODE_INDENT 4
+#define UNORDERED_LIST_MAX_LEVEL 3
 
 deck_t *markdown_load(FILE *input);
 int markdown_analyse(cstring_t *text);
index f7a4d54..b8588db 100644 (file)
--- a/sample.md
+++ b/sample.md
@@ -108,8 +108,8 @@ becomes
 
 Inline highlighting is supported as followed:
 
-- *\** colors text as red
-- *\_* underlines text
+\- *\** colors text as red
+\- *\_* underlines text
 
 \_some\_ \*highlighted\* \_\*text\*\_
 
@@ -133,6 +133,36 @@ becomes
 
 -------------------------------------------------
 
+# Supported markdown formatting's
+
+The leading stars or minuses make list.
+
+TODO list:
+\* TODO major 1
+\    \- TODO minor 1.1
+\        \- Detail 1.1.1
+\        \- Detail 1.1.2
+\    \- TODO minor 1.2
+\* TODO major 2
+\* TODO major 3
+\    \* TODO minor 3.1
+\    \* TODO minor 3.2
+
+becomes
+
+TODO list:
+* TODO major 1
+    - TODO minor 1.1
+        - Detail 1.1.1
+        - Detail 1.1.2
+    - TODO minor 1.2
+* TODO major 2
+* TODO major 3
+    * TODO minor 3.1
+    * TODO minor 3.2
+
+-------------------------------------------------
+
 ## More information about markdown
 
 can be found on
@@ -170,8 +200,8 @@ want to convert it to PDF.
 
 This can be achieved by two additional tools:
 
-- *markdown* to convert to HTML
-- *wkhtmltopdf* to convert from HTML to PDF
+\- *markdown* to convert to HTML
+\- *wkhtmltopdf* to convert from HTML to PDF
 
 After installing them, you can simply type:
 
index 0852e80..a573106 100644 (file)
@@ -189,7 +189,6 @@ deck_t *markdown_load(FILE *input) {
         deck->slide->lines -= hc;
     }
 
-    // combine underlined H1/H2 in single line
     slide = deck->slide;
     while(slide) {
         line = slide->line;
@@ -199,6 +198,7 @@ deck_t *markdown_load(FILE *input) {
                CHECK_BIT(line->bits, IS_EMPTY) &&
                line->prev &&
                !CHECK_BIT(line->prev->bits, IS_EMPTY)) {
+                // combine underlined H1/H2 in single line
 
                 // remove line from linked list
                 line->prev->next = line->next;
@@ -222,7 +222,56 @@ deck_t *markdown_load(FILE *input) {
                 // delete line
                 (tmp->text->delete)(tmp->text);
                 free(tmp);
+            } else if(CHECK_BIT(line->bits, IS_UNORDERED_LIST_3)) {
+                tmp = line->next;
+                line_t *list_last_level_3 = line;
+
+                while(tmp &&
+                      CHECK_BIT(tmp->bits, IS_UNORDERED_LIST_3)) {
+                    if(CHECK_BIT(tmp->bits, IS_UNORDERED_LIST_3)) {
+                        list_last_level_3 = tmp;
+                    }
+                    tmp = tmp->next;
+                }
+
+                for(tmp = line; tmp != list_last_level_3; tmp = tmp->next) {
+                    SET_BIT(tmp->bits, IS_UNORDERED_LIST_3);
+                }
+            } else if(CHECK_BIT(line->bits, IS_UNORDERED_LIST_2)) {
+                tmp = line->next;
+                line_t *list_last_level_2 = line;
+
+                while(tmp &&
+                      (CHECK_BIT(tmp->bits, IS_UNORDERED_LIST_2) ||
+                       CHECK_BIT(tmp->bits, IS_UNORDERED_LIST_3))) {
+                    if(CHECK_BIT(tmp->bits, IS_UNORDERED_LIST_2)) {
+                        list_last_level_2 = tmp;
+                    }
+                    tmp = tmp->next;
+                }
+
+                for(tmp = line; tmp != list_last_level_2; tmp = tmp->next) {
+                    SET_BIT(tmp->bits, IS_UNORDERED_LIST_2);
+                }
+            } else if(CHECK_BIT(line->bits, IS_UNORDERED_LIST_1)) {
+                tmp = line->next;
+                line_t *list_last_level_1 = line;
+
+                while(tmp &&
+                      (CHECK_BIT(tmp->bits, IS_UNORDERED_LIST_1) ||
+                       CHECK_BIT(tmp->bits, IS_UNORDERED_LIST_2) ||
+                       CHECK_BIT(tmp->bits, IS_UNORDERED_LIST_3))) {
+                    if(CHECK_BIT(tmp->bits, IS_UNORDERED_LIST_1)) {
+                        list_last_level_1 = tmp;
+                    }
+                    tmp = tmp->next;
+                }
+                
+                for(tmp = line; tmp != list_last_level_1; tmp = tmp->next) {
+                    SET_BIT(tmp->bits, IS_UNORDERED_LIST_1);
+                }
             }
+
             line = line->next;
         }
         slide = slide->next;
@@ -233,6 +282,9 @@ deck_t *markdown_load(FILE *input) {
 
 int markdown_analyse(cstring_t *text) {
 
+    static int unordered_list_level = 0;
+    static int unordered_list_level_offset[] = {-1, -1, -1, -1};
+
     int i = 0;      // increment
     int bits = 0;   // markdown bits
     int offset = 0; // text offset
@@ -242,77 +294,126 @@ int markdown_analyse(cstring_t *text) {
         stars  = 0, minus  = 0,
         spaces = 0, other  = 0; // special character counts
 
+    const int unordered_list_offset = unordered_list_level_offset[unordered_list_level];
+
     // count leading spaces
     offset = next_nonblank(text, 0);
 
     // strip trailing spaces
     for(eol = text->size; eol > offset && isspace((unsigned char) text->text[eol - 1]); eol--);
 
-    // IS_CODE
-    if(offset >= CODE_INDENT) {
-        SET_BIT(bits, IS_CODE);
-    }
+    if(text->size >= offset + 2 &&
+       (text->text[offset] == '*' || text->text[offset] == '-') &&
+       text->text[offset + 1] == ' ') {
+
+        for(i = offset; i<eol; i++)
+            if(text->text[i] != '*' &&
+               text->text[i] != '-' &&
+               text->text[i] != ' ') {
+                if(offset > unordered_list_offset + CODE_INDENT) {
+                    SET_BIT(bits, IS_CODE);
+                } else if(offset != unordered_list_offset) {
+                    for(i = unordered_list_level; i >= 0; i--) {
+                        if(unordered_list_level_offset[i] == offset) {
+                            unordered_list_level = i;
+                            break;
+                        }
+                    }
+                    if(i != unordered_list_level) {
+                        unordered_list_level = MIN(unordered_list_level + 1, UNORDERED_LIST_MAX_LEVEL);
+                        unordered_list_level_offset[unordered_list_level] = offset;
+                    }
+                }
 
-    for(i = offset; i < eol; i++) {
+                if(unordered_list_level == 0) {
+                    unordered_list_level = 1;
+                    unordered_list_level_offset[1] = offset;
+                 }
 
-        if(text->text[i] == ' ') {
-            spaces++;
+                switch(unordered_list_level) {
+                    case 1: SET_BIT(bits, IS_UNORDERED_LIST_1); break;
+                    case 2: SET_BIT(bits, IS_UNORDERED_LIST_2); break;
+                    case 3: SET_BIT(bits, IS_UNORDERED_LIST_3); break;
+                    default: break;
+                }
+                
+                break;
+            }
+    }
+    
+    if(!CHECK_BIT(bits, IS_UNORDERED_LIST_1) &&
+       !CHECK_BIT(bits, IS_UNORDERED_LIST_2) &&
+       !CHECK_BIT(bits, IS_UNORDERED_LIST_3)) {
 
-        } else if(CHECK_BIT(bits, IS_CODE)) {
-            other++;
+        unordered_list_level = 0;
 
+        if(offset >= CODE_INDENT) {
+            // IS_CODE
+            SET_BIT(bits, IS_CODE);
         } else {
-            switch(text->text[i]) {
-                case '=': equals++;  break;
-                case '#': hashes++;  break;
-                case '*': stars++;   break;
-                case '-': minus++;   break;
-                case '\\': other++; i++; break;
-                default:  other++;   break;
+
+            for(i = offset; i < eol; i++) {
+
+                if(text->text[i] == ' ') {
+                    spaces++;
+
+                } else if(CHECK_BIT(bits, IS_CODE)) {
+                    other++;
+
+                } else {
+                    switch(text->text[i]) {
+                        case '=': equals++;  break;
+                        case '#': hashes++;  break;
+                        case '*': stars++;   break;
+                        case '-': minus++;   break;
+                        case '\\': other++; i++; break;
+                        default:  other++;   break;
+                    }
+                }
             }
-        }
-    }
 
-    // IS_H1
-    if((equals > 0 &&
-        hashes + stars + minus + spaces + other == 0) ||
-       (text &&
-        text->text &&
-        text->text[offset] == '#' &&
-        text->text[offset+1] != '#')) {
+            // IS_H1
+            if((equals > 0 &&
+                hashes + stars + minus + spaces + other == 0) ||
+               (text &&
+                text->text &&
+                text->text[offset] == '#' &&
+                text->text[offset+1] != '#')) {
 
-        SET_BIT(bits, IS_H1);
-    }
+                SET_BIT(bits, IS_H1);
+            }
 
-    // IS_H2
-    if((minus > 0 &&
-        equals + hashes + stars + spaces + other == 0) ||
-       (text &&
-        text->text &&
-        text->text[offset] == '#' &&
-        text->text[offset+1] == '#')) {
+            // IS_H2
+            if((minus > 0 &&
+                equals + hashes + stars + spaces + other == 0) ||
+               (text &&
+                text->text &&
+                text->text[offset] == '#' &&
+                text->text[offset+1] == '#')) {
 
-        SET_BIT(bits, IS_H2);
-    }
+                SET_BIT(bits, IS_H2);
+            }
 
-    // IS_QUOTE
-    if(text &&
-       text->text &&
-       text->text[offset] == '>') {
+            // IS_QUOTE
+            if(text &&
+               text->text &&
+               text->text[offset] == '>') {
 
-        SET_BIT(bits, IS_QUOTE);
-    }
+                SET_BIT(bits, IS_QUOTE);
+            }
 
-    // IS_HR
-    if((minus >= 3 && equals + hashes + stars + other == 0) ||
-       (stars >= 3 && equals + hashes + minus + other == 0)) {
+            // IS_HR
+            if((minus >= 3 && equals + hashes + stars + other == 0) ||
+               (stars >= 3 && equals + hashes + minus + other == 0)) {
 
-        SET_BIT(bits, IS_HR);
-    }
+                SET_BIT(bits, IS_HR);
+            }
 
-    // IS_EMPTY
-    if(other == 0) {
-        SET_BIT(bits, IS_EMPTY);
+            // IS_EMPTY
+            if(other == 0) {
+                SET_BIT(bits, IS_EMPTY);
+            }
+        }
     }
 
     return bits;
@@ -382,7 +483,7 @@ int length_utf8(char ch) {
 
     int i = 0; // increment
 
-    while(ch & 0x80) {
+    while(is_utf8(ch)) {
         i++;
         ch <<= 1;
     }
@@ -392,14 +493,14 @@ int length_utf8(char ch) {
 
 int next_nonblank(cstring_t *text, int i) {
     while ((i < text->size) && isspace((unsigned char) (text->text)[i]))
-        ++i;
+        i++;
 
     return i;
 }
 
 int next_blank(cstring_t *text, int i) {
     while ((i < text->size) && !isspace((unsigned char) (text->text)[i]))
-        ++i;
+        i++;
 
     return i;
 }
index 528f4d4..e3d2651 100644 (file)
@@ -368,10 +368,40 @@ void add_line(WINDOW *window, int y, int x, line_t *line, int max_cols, int colo
     char *c; // char pointer for iteration
     char *special = "\\*_`"; // list of interpreted chars
     cstack_t *stack = cstack_init();
-
+    
     if(line->text->text) {
         int offset = 0; // text offset
 
+        if(CHECK_BIT(line->bits, IS_UNORDERED_LIST_3)) {
+            offset = next_nonblank(line->text, 0);
+            char format_s[15];
+            strcpy(&format_s[0], CHECK_BIT(line->bits, IS_UNORDERED_LIST_1)? "|   " : "    ");
+            strcpy(&format_s[4], CHECK_BIT(line->bits, IS_UNORDERED_LIST_2)? "|   " : "    ");
+            strcpy(&format_s[8], line->next && CHECK_BIT(line->next->bits, IS_UNORDERED_LIST_3)? "+-- %s" : "`-- %s");
+            mvwprintw(window,
+                      y, x,
+                      format_s,
+                      &line->text->text[offset + 2]);
+        } else if(CHECK_BIT(line->bits, IS_UNORDERED_LIST_2)) {
+            offset = next_nonblank(line->text, 0);
+            char format_s[11];
+            strcpy(&format_s[0], CHECK_BIT(line->bits, IS_UNORDERED_LIST_1)? "|   " : "    ");
+            strcpy(&format_s[4], line->next && CHECK_BIT(line->next->bits, IS_UNORDERED_LIST_2)? "+-- %s" : "`-- %s");
+            mvwprintw(window,
+                      y, x,
+                      format_s,
+                      &line->text->text[offset + 2]);
+        } else if(CHECK_BIT(line->bits, IS_UNORDERED_LIST_1)) {
+            offset = next_nonblank(line->text, 0);
+            char format_s[7];
+            strcpy(&format_s[0], line->next && CHECK_BIT(line->next->bits, IS_UNORDERED_LIST_1)? "+-- %s" : "`-- %s");
+            mvwprintw(window,
+                      y, x,
+                      format_s,
+                      &line->text->text[offset + 2]);
+        } else
+
+
         // IS_CODE
         if(CHECK_BIT(line->bits, IS_CODE)) {