Hi,
I got bored yesterday evening, so I wrote a minimal org-mode support.
For now it supports:
- bullet lists highlight
- TODO/DONE/ highlight and cycling
- bullet line and subtree promotion/demotion
However I couldn't get the correct bindings for those yet so I took
arbitrary keys for now.

I don't intend to make a full org-mode clone, as it's way too complex,
and it's much less useful without folding support, but for note taking
and TODO list it might be useful enough.

cf.
http://orgmode.org/

François.
Index: Makefile
===================================================================
RCS file: /sources/qemacs/qemacs/Makefile,v
retrieving revision 1.57
diff -u -r1.57 Makefile
--- Makefile	2 Jan 2014 10:10:24 -0000	1.57
+++ Makefile	6 Jan 2014 11:56:10 -0000
@@ -111,7 +111,7 @@
 
 ifdef CONFIG_ALL_MODES
   OBJS+= unihex.o clang.o xml.o bufed.o \
-         lisp.o makemode.o perl.o htmlsrc.o script.o variables.o
+         lisp.o makemode.o org-mode.o perl.o htmlsrc.o script.o variables.o
   ifndef CONFIG_WIN32
     OBJS+= shell.o dired.o latex-mode.o
   endif
--- /dev/null	2013-11-11 13:26:50.667131979 +0100
+++ org-mode.c	2014-01-06 12:54:48.000000000 +0100
@@ -0,0 +1,362 @@
+/*
+ * Org mode for QEmacs.
+ *
+ * Copyright (c) 2001, 2002 Fabrice Bellard.
+ * Copyright (c) 2002-2013 Charlie Gordon.
+ * Copyright (c) 2014 Francois Revol.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "qe.h"
+
+ModeDef org_mode;
+
+#define IN_BULLET       0x01
+#define IN_ACTION       0x02
+#define IN_TAG          0x04
+
+#define MAX_BUF_SIZE    512
+
+
+/* TODO: define specific styles */
+static struct OrgTodoKeywords {
+    const char *keyword;
+    int style;
+} OrgTodoKeywords [] = {
+  {"TODO", QE_STYLE_STRING},
+  {"DONE", QE_STYLE_TYPE}
+};
+
+/* TODO: define specific styles */
+#define BULLET_STYLES 5
+static int OrgBulletStyles[BULLET_STYLES] = {
+    QE_STYLE_FUNCTION,
+    QE_STYLE_VARIABLE,
+    QE_STYLE_PREPROCESS,
+    QE_STYLE_STRING,
+    QE_STYLE_TYPE
+};
+
+static int org_bullet_depth(int *str, int n)
+{
+    int i;
+
+    for (i = 0; i < n && (str[i] & CHAR_MASK) == '*'; i++) {
+        if ((str[i + 1] & CHAR_MASK) == ' ') {
+	    return i;
+	}
+    }
+    return -1;
+}
+
+static int org_todo_keyword(int *str, int n)
+{
+    int i;
+    char c;
+    int klen;
+    char kbuf[32];
+
+    klen = 0;
+    for (i = 0; i < n && qe_isalpha(c = (str[i] & CHAR_MASK)); i++) {
+        if (klen < countof(kbuf) - 1)
+	    kbuf[klen++] = c;
+	else
+	    break;
+    }
+    kbuf[klen] = '\0';
+    if (klen > 0 && c == ' ') {
+      int k;
+      for (k = 0; k < countof(OrgTodoKeywords); k++) {
+	if (!strcmp(kbuf, OrgTodoKeywords[k].keyword)) {
+	  set_color(str, str + i, OrgTodoKeywords[k].style);
+	  return k;
+	}
+      }
+    }
+    return -1;
+}
+
+static void org_colorize_line(unsigned int *str, int n, int *statep,
+                              __unused__ int state_only)
+{
+    int colstate = *statep;
+    int bullets = 0;
+    int base_style = 0;
+    int i = 0, j = 0;
+    int klen;
+    char kbuf[32];
+    char c;
+    int k;
+
+    bullets = org_bullet_depth(str, n);
+    if (bullets > -1) {
+	    colstate = IN_BULLET;
+	    base_style = OrgBulletStyles[bullets % BULLET_STYLES];
+	    set_color(str, str + bullets + 1, base_style);
+	    i = bullets + 2;
+    }
+
+    if (colstate & IN_BULLET) {
+        int kw = org_todo_keyword(str + i, n - i);
+        if (kw > -1) {
+	    int kwlen = strlen(OrgTodoKeywords[kw].keyword);
+            set_color(str + i, str + i + kwlen, OrgTodoKeywords[kw].style);
+	    i += kwlen;
+	}
+    }
+
+    while (i < n) {
+        c = str[i] & CHAR_MASK;
+        switch (c) {
+        default:
+            break;
+        }
+	set_color1(str + i, base_style);
+        i++;
+        continue;
+    }
+
+    colstate = 0;
+    *statep = colstate;
+}
+
+static void do_org_todo(EditState *s)
+{
+  int offset, offsetl, line_num, col_num, bullets, len;
+  unsigned int buf[MAX_BUF_SIZE], *p;
+  int kw;
+
+    /* find start of line */
+    eb_get_pos(s->b, &line_num, &col_num, s->offset);
+    offset = eb_goto_bol(s->b, s->offset);
+    do {
+      offsetl = offset;
+      len = eb_get_line(s->b, buf, countof(buf), &offsetl);
+      bullets = org_bullet_depth(buf, len);
+      if (bullets > -1) {
+	  break;
+      }
+      offsetl = offset;
+      offset = eb_prev_line(s->b, offset);
+    } while (offsetl > 0);
+
+    if (bullets < 0)
+      return;
+
+    offset = eb_goto_bol(s->b, offset);
+    kw = org_todo_keyword(buf + bullets + 2, len - bullets);
+
+    if (kw > -1) {
+      int kwlen = strlen(OrgTodoKeywords[kw].keyword);
+      eb_delete(s->b, offset + bullets + 2, kwlen + 1);
+    }
+
+    kw++;
+
+    if (kw < countof(OrgTodoKeywords)) {
+      int kwlen = strlen(OrgTodoKeywords[kw].keyword);
+      eb_insert(s->b, offset + bullets + 2, " ", 1);
+      eb_insert(s->b, offset + bullets + 2, OrgTodoKeywords[kw].keyword, kwlen);
+    }
+}
+
+static void do_org_meta_return(EditState *s)
+{
+    int offset, offsetl, line_num, col_num, bullets, len;
+    unsigned int buf[MAX_BUF_SIZE], *p;
+    int kw;
+
+    /* find start of line */
+    eb_get_pos(s->b, &line_num, &col_num, s->offset);
+    offset = eb_goto_bol(s->b, s->offset);
+    offsetl = offset;
+    len = eb_get_line(s->b, buf, countof(buf), &offsetl);
+    bullets = org_bullet_depth(buf, len);
+    if (bullets < 0)
+      return;
+
+    if (col_num > 0)
+      offset = offsetl;
+
+    eb_insert(s->b, offset, " \n", 2);
+    do {
+        eb_insert(s->b, offset, "*", 1);
+    } while (bullets--);
+    eb_goto_eol(s->b, offset);
+    if (col_num > 0)
+      text_move_up_down(s, 1);
+    text_move_eol(s);
+}
+
+static void do_org_insert_todo_heading(EditState *s)
+{
+    printf("M-S-RET\n");
+    /* TODO */
+}
+
+static void do_org_promote(EditState *s, int dir)
+{
+    int offset, offsetl, line_num, col_num, len;
+    int bullets;
+    unsigned int buf[MAX_BUF_SIZE], *p;
+    int kw;
+
+    /* find start of line */
+    eb_get_pos(s->b, &line_num, &col_num, s->offset);
+    offset = eb_goto_bol(s->b, s->offset);
+    offsetl = offset;
+    len = eb_get_line(s->b, buf, countof(buf), &offsetl);
+    bullets = org_bullet_depth(buf, len);
+    if (bullets < 0)
+      return;
+
+    if (dir > 0)
+        eb_insert(s->b, offset, "*", 1);
+    if (dir < 0 && bullets > 0)
+        eb_delete(s->b, offset, 1);
+}
+
+static void do_org_promote_subtree(EditState *s, int dir)
+{
+    int offset, offsetl, offseti, line_num, col_num, len;
+    int bullets, bullets1;
+    unsigned int buf[MAX_BUF_SIZE], *p;
+    int kw;
+
+    /* find start of line */
+    eb_get_pos(s->b, &line_num, &col_num, s->offset);
+    offset = eb_goto_bol(s->b, s->offset);
+    offsetl = offset;
+    len = eb_get_line(s->b, buf, countof(buf), &offsetl);
+    bullets = org_bullet_depth(buf, len);
+    if (bullets < 0)
+      return;
+
+    if (dir > 0)
+        eb_insert(s->b, offset, "*", 1);
+    else if (dir < 0 && bullets > 0)
+        eb_delete(s->b, offset, 1);
+    else
+        return;
+
+    bullets1 = bullets;
+    for (;;) {
+        offsetl = eb_next_line(s->b, offset);
+	if (offsetl == offset)
+	    break;
+	offset = offseti = offsetl;
+	eb_get_pos(s->b, &line_num, &col_num, offseti);
+	len = eb_get_line(s->b, buf, countof(buf), &offseti);
+	bullets = org_bullet_depth(buf, len);
+	if (bullets < 0)
+	    continue;
+	if (bullets <= bullets1)
+	    break;
+	
+	if (dir > 0)
+	    eb_insert(s->b, offset, "*", 1);
+	if (dir < 0 && bullets > 0)
+	    eb_delete(s->b, offset, 1);
+   }
+}
+
+static void do_org_metaleft(EditState *s)
+{
+  do_org_promote(s, -1);
+}
+
+static void do_org_metaright(EditState *s)
+{
+  do_org_promote(s, 1);
+}
+
+static void do_org_shiftmetaleft(EditState *s)
+{
+  do_org_promote_subtree(s, -1);
+}
+
+static void do_org_shiftmetaright(EditState *s)
+{
+  do_org_promote_subtree(s, 1);
+}
+
+static int org_mode_probe(ModeDef *mode, ModeProbeData *p)
+{
+    /* just check file extension */
+    if (match_extension(p->filename, mode->extensions))
+        return 80;
+
+    return 0;
+}
+
+static int org_mode_init(EditState *s, __unused__ ModeSavedData *saved_data)
+{
+    int ret;
+
+    ret = text_mode_init(s, saved_data);
+    if (ret)
+        return ret;
+
+    s->wrap = WRAP_TRUNCATE;
+    return 0;
+}
+
+static void org_mode_close(__unused__ EditState *s)
+{
+}
+
+/* Org mode specific commands */
+static CmdDef org_commands[] = {
+    /* actually C-c C-t */
+    CMD2( KEY_CTRL('t'), KEY_NONE,
+         "org-todo", do_org_todo, ES, "*")
+    CMD2( KEY_META(KEY_RET), KEY_NONE,
+         "org-meta-return", do_org_meta_return, ES, "*")
+    /*
+    CMD2( KEY_META_S('\n'), KEY_NONE,
+         "org-insert-todo-heading", do_org_insert_todo_heading, ES, "*")
+    */
+    /* actually M-left */
+    CMD2( KEY_CTRL_LEFT, KEY_NONE,
+         "org-metaleft", do_org_metaleft, ES, "*")
+    /* actually M-right */
+    CMD2( KEY_CTRL_RIGHT, KEY_NONE,
+         "org-metaright", do_org_metaright, ES, "*")
+    /* actually M-S-left */
+    CMD2( KEY_CTRLX('<'), KEY_NONE,
+         "org-shiftmetaleft", do_org_shiftmetaleft, ES, "*")
+    /* actually M-S-right */
+    CMD2( KEY_CTRLX('>'), KEY_NONE,
+         "org-shiftmetaright", do_org_shiftmetaright, ES, "*")
+    CMD_DEF_END,
+};
+
+static int org_init(void)
+{
+    memcpy(&org_mode, &text_mode, sizeof(ModeDef));
+    org_mode.name = "org";
+    org_mode.extensions = "org";
+    org_mode.mode_probe = org_mode_probe;
+    org_mode.colorize_func = org_colorize_line;
+    org_mode.mode_init = org_mode_init;
+
+    qe_register_mode(&org_mode);
+    qe_register_cmd_table(org_commands, &org_mode);
+
+    return 0;
+}
+
+qe_module_init(org_init);
_______________________________________________
Qemacs-devel mailing list
Qemacs-devel@nongnu.org
https://lists.nongnu.org/mailman/listinfo/qemacs-devel

Reply via email to