I hacked together this little patch to contrib/nvi to make it support
simple modelines. The original author of nvi (Keith Bostic) says in
the sources that modelines are not to be implemented because of
security concerns, but I believe that implementing them after vim's
style (i.e., only allowing arguments to the 'set' option in modelines)
doesn't pose any security threat. Besides, I find them quite useful
when editing some specific files, for which I want specific settings.
Acceptable modelines are in the form: (ex/vi regex)
.*[[:blank:]]\+\(vi\)\|\(ex\):options
where 'options' are space- or colon-separated arguments to 'set'.

Well, please tell me what you think about it, and whether I should
file a PR to get this included. Without further ado, here is the
patch:

diff -Nru a/common/exf.c b/common/exf.c
--- a/common/exf.c      Wed Jul 14 22:22:19 2004
+++ b/common/exf.c      Wed Jul 14 23:33:17 2004
@@ -42,6 +42,83 @@
 
 #include "common.h"
 
+char * parse_modeline(sp, line, size)
+       SCR *sp;
+       char *line;
+       int size;
+{
+       char *cmd, *ex;
+       int i;
+
+       cmd = malloc(sizeof (*cmd) * size);
+
+       if ( !(ex = strstr(line, "vi:")) && !(ex = strstr(line, "ex:")) )
+               return NULL; /* no modelines here */
+       if ( (ex != line) && !isblank(*(ex - 1)))
+               return NULL; /* no modelines here either */
+
+       /* What we have to do is initialize *cmd with 'set ',
+        * change colons to spaces and append the resulting mess
+        * to cmd.
+        */
+       strcpy(cmd, "set ");
+       i = strlen(cmd);
+       ex += 3;
+       while(*ex != '\n' && *ex != '\r' && i < size) /* run till end of line */
+       {
+               if(*ex == ':')
+                       cmd[i] = ' ';
+               else
+                       cmd[i] = *ex;
+               i++;
+               ex++;
+       }
+       cmd[i] = '\0';
+
+       return cmd;
+}
+
+/* 
+ * We look for a modeline, and return a cooked string ready to be
+ * run by ex_run_str.
+ * the first one is found; if there is no modeline, return NULL.
+ */
+char * get_modeline(sp)
+       SCR * sp;
+{
+       char *cmd, *line;
+       int i, lnop, linesz, lineempty;
+
+       line = malloc(sizeof(*line) * 255); /* shall we have a modeline
longer than that? */
+
+       if (db_last(sp, &lnop))
+               return NULL;
+       if (lnop == 0)
+               return NULL;
+
+       for (i = 1; i <= lnop && i <= 5; i++)
+       {
+               db_eget(sp, i, &line, &linesz, &lineempty);
+               if(lineempty)
+                       continue;
+               if ( (cmd = parse_modeline(sp, line, linesz)) != NULL)
+                       return cmd;
+       }
+
+       /* just like before, but counting lines from bottom up */
+       for (i = lnop; i > 0 && i >= (lnop - 5); i--)
+       {
+               db_eget(sp, i, &line, &linesz, &lineempty);
+               if(lineempty)
+                       continue;
+               if ( (cmd = parse_modeline(sp, line, linesz)) != NULL)
+                       return cmd;
+       }
+
+       /* If we reached this point, there is nothing to return. Therefore, */
+       return NULL;
+}
+
 static int     file_backup __P((SCR *, char *, char *));
 static void    file_cinit __P((SCR *));
 static void    file_comment __P((SCR *));
@@ -520,6 +597,7 @@
        MARK m;
        size_t len;
        int nb;
+       char *cmd;
 
        /* Set some basic defaults. */
        sp->lno = 1;
@@ -612,6 +690,14 @@
         */
        m.lno = sp->lno;
        m.cno = sp->cno;
+
+       if (O_ISSET(sp, O_MODELINE)) { 
+               cmd = get_modeline(sp); 
+               if (cmd != NULL)
+                       if (ex_run_str(sp, "modeline", cmd, strlen(cmd), 0, 0)) 
+                               return;
+       }
+
        (void)mark_set(sp, ABSMARK1, &m, 0);
 }
 
diff -Nru a/common/options.c b/common/options.c
--- a/common/options.c  Wed Jul 14 22:22:19 2004
+++ b/common/options.c  Wed Jul 14 22:32:54 2004
@@ -124,7 +124,7 @@
  *     example of what your intro CS professor referred to as the perils of
  *     mixing code and data.  Don't add it, or I will kill you.
  */
-       {"modeline",    NULL,           OPT_0BOOL,      OPT_NOSET},
+       {"modeline",    NULL,           OPT_0BOOL,      0},
 /* O_MSGCAT      4.4BSD */
        {"msgcat",      f_msgcat,       OPT_STR,        0},
 /* O_NOPRINT     4.4BSD */
_______________________________________________
[EMAIL PROTECTED] mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-hackers
To unsubscribe, send any mail to "[EMAIL PROTECTED]"

Reply via email to