[prev in list] [next in list] [prev in thread] [next in thread]
List: openbsd-tech
Subject: Hooks in mg
From: Sunil Nimmagadda <sunil () sunilnimmagadda ! com>
Date: 2012-02-22 19:17:00
Message-ID: 20120222190500.GA24269 () puffy
[Download RAW message or body]
Hello,
This diff generalize the hooks execution and allows to define new hook
execution points. For example if your .mg is now...
auto-execute *.c c-mode
then with this diff you can change it to...
add-hook find-file-hook c-mode
add-hook before-save-hook deltrailspace
find-file-hook type hooks get executed every time a file is read in
and before-save-hook type hooks get executed when a buffer is about to
be saved. deltrailspace is a hook that removes trailing whitespace before
saving a buffer whose filename matches *.[ch1-9]
comments?
Index: Makefile
===================================================================
RCS file: /home/sunil/cvs/src/usr.bin/mg/Makefile,v
retrieving revision 1.25
diff -u -p -r1.25 Makefile
--- Makefile 28 Nov 2011 04:41:39 -0000 1.25
+++ Makefile 22 Feb 2012 18:06:59 -0000
@@ -24,7 +24,7 @@ SRCS= autoexec.c basic.c buffer.c cinfo.
#
# More or less standalone extensions.
#
-SRCS+= cmode.c dired.c grep.c tags.c theo.c
+SRCS+= cmode.c dired.c hookexec.c hooks.c grep.c tags.c theo.c
afterinstall:
${INSTALL} -d ${DESTDIR}${DOCDIR}/mg
Index: def.h
===================================================================
RCS file: /home/sunil/cvs/src/usr.bin/mg/def.h,v
retrieving revision 1.118
diff -u -p -r1.118 def.h
--- def.h 10 Dec 2011 14:09:48 -0000 1.118
+++ def.h 22 Feb 2012 18:09:04 -0000
@@ -654,6 +654,19 @@ int next_error(int, int);
int globalwdtoggle(int, int);
int compile(int, int);
+/* hooks.c */
+void cmode_hook(void);
+void deltspace_hook(void);
+
+/* hookexec.c */
+enum hooktype {
+ HOOKTYPE_UNDEF,
+ HOOKTYPE_FIND_FILE,
+ HOOKTYPE_BEFORE_SAVE
+};
+int addhook(int, int);
+void exechooks(enum hooktype);
+
/*
* Externals.
*/
Index: file.c
===================================================================
RCS file: /home/sunil/cvs/src/usr.bin/mg/file.c,v
retrieving revision 1.76
diff -u -p -r1.76 file.c
--- file.c 31 Aug 2011 08:58:29 -0000 1.76
+++ file.c 22 Feb 2012 18:11:38 -0000
@@ -238,6 +238,8 @@ readin(char *fname)
free(ael);
}
+ exechooks(HOOKTYPE_FIND_FILE);
+
/* no change */
curbp->b_flag &= ~BFCHG;
@@ -572,6 +574,8 @@ buffsave(struct buffer *bp)
return (s);
}
+ exechooks(HOOKTYPE_BEFORE_SAVE);
+
if (makebackup && (bp->b_flag & BFBAK)) {
s = fbackupfile(bp->b_fname);
/* hard error */
Index: funmap.c
===================================================================
RCS file: /home/sunil/cvs/src/usr.bin/mg/funmap.c,v
retrieving revision 1.35
diff -u -p -r1.35 funmap.c
--- funmap.c 28 Nov 2011 04:41:39 -0000 1.35
+++ funmap.c 22 Feb 2012 18:13:32 -0000
@@ -21,6 +21,7 @@ static struct funmap *funs;
static struct funmap functnames[] = {
#ifndef NO_HELP
+ {addhook, "add-hook",},
{apropos_command, "apropos",},
#endif /* !NO_HELP */
{auto_execute, "auto-execute", },
Index: hookexec.c
===================================================================
RCS file: hookexec.c
diff -N hookexec.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ hookexec.c 22 Feb 2012 19:00:40 -0000
@@ -0,0 +1,157 @@
+/*
+ * Copyright (c) 2012 Sunil Nimmagadda <sunil@sunilnimmagadda.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/queue.h>
+#include <sys/tree.h>
+
+#include "def.h"
+
+struct hook;
+typedef void (*HF)(void);
+
+static int hcmp(struct hook *, struct hook *);
+static enum hooktype hlookup(char *);
+static int addhook_helper(enum hooktype, HF);
+static HF hfunction(const char *);
+
+struct hfname
+{
+ HF fp;
+ const char *name;
+};
+
+static struct hfname hfuncnames [] = {
+ {cmode_hook, "c-mode"},
+ {deltspace_hook, "deltrailspace"},
+ {NULL, NULL}
+};
+
+struct hookfunc {
+ SLIST_ENTRY(hookfunc) entry;
+ HF fp;
+};
+
+struct hook {
+ RB_ENTRY(hook) entry;
+ SLIST_HEAD(, hookfunc) hfuncs;
+ enum hooktype t;
+
+};
+
+/* key is enum hooktype and value is a list of HF. */
+static RB_HEAD(hookmap, hook) hmap = RB_INITIALIZER(&hmap);
+RB_GENERATE(hookmap, hook, entry, hcmp);
+
+int
+hcmp(struct hook *h1, struct hook *h2)
+{
+ return (h1->t != h2->t);
+}
+
+/*
+ * Determine hooktype, hookfunction and add it to the tree.
+ */
+/* ARGSUSED */
+int
+addhook(int f, int n)
+{
+ char buf[NXNAME], *hfuncname, *htname;
+ enum hooktype ht;
+ HF fp;
+
+ htname = eread("hook type: ", buf, NXNAME, EFNEW);
+ if (htname == NULL)
+ return (FALSE);
+ else if ((ht = hlookup(htname)) == HOOKTYPE_UNDEF)
+ return (FALSE);
+
+ hfuncname = eread("command: ", buf, NXNAME, EFNEW);
+ if (hfuncname == NULL)
+ return (FALSE);
+ else if ((fp = hfunction(hfuncname)) == NULL)
+ return (FALSE);
+
+ return addhook_helper(ht, fp);
+}
+
+/*
+ * Helper function to add an entry to tree. If hooktype not present
+ * in tree initialize list and add fp else just append fp to the list.
+ */
+int
+addhook_helper(enum hooktype t, HF fp)
+{
+ struct hook h, *hnew, *res;
+ struct hookfunc *hf;
+
+ if((hf = malloc(sizeof *hf)) == NULL)
+ return (FALSE);
+ hf->fp = fp;
+ h.t = t;
+ if ((res = RB_FIND(hookmap, &hmap, &h)) == NULL) {
+ if ((hnew = malloc(sizeof *hnew)) == NULL)
+ goto cleanup;
+ hnew->t = t;
+ SLIST_INIT(&hnew->hfuncs);
+ SLIST_INSERT_HEAD(&hnew->hfuncs, hf, entry);
+ RB_INSERT(hookmap, &hmap, hnew);
+ } else
+ SLIST_INSERT_HEAD(&res->hfuncs, hf, entry);
+ return (TRUE);
+cleanup:
+ free(hf);
+ return (FALSE);
+}
+
+/*
+ * For a given hooktype find the list of functions in tree and
+ * execute them sequentially.
+ */
+void
+exechooks(enum hooktype t)
+{
+ struct hook h, *res;
+ struct hookfunc *hf;
+
+ h.t = t;
+ if ((res = RB_FIND(hookmap, &hmap, &h)) == NULL)
+ return;
+ SLIST_FOREACH(hf, &res->hfuncs, entry)
+ (hf->fp)();
+}
+
+enum hooktype
+hlookup(char *s)
+{
+ if (strcmp(s, "before-save-hook") == 0)
+ return (HOOKTYPE_BEFORE_SAVE);
+ else if (strcmp(s, "find-file-hook") == 0)
+ return (HOOKTYPE_FIND_FILE);
+
+ return (HOOKTYPE_UNDEF);
+}
+
+HF
+hfunction(const char *name)
+{
+ struct hfname *p;
+
+ /* Linear lookup since we have very few hooks for now */
+ for (p = hfuncnames; p->name != NULL; p++)
+ if (strcmp(p->name, name) == 0)
+ return (p->fp);
+ return (NULL);
+}
Index: hooks.c
===================================================================
RCS file: hooks.c
diff -N hooks.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ hooks.c 22 Feb 2012 18:31:43 -0000
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2012 Sunil Nimmagadda <sunil@sunilnimmagadda.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <ctype.h>
+#include <fnmatch.h>
+
+#include "def.h"
+
+static void ttrim(struct line *);
+
+/*
+ * Enable c-mode for C files.
+ */
+void
+cmode_hook(void)
+{
+ if (fnmatch("*.c", curbp->b_fname, 0) == 0)
+ cmode(0, 1);
+}
+
+/*
+ * Delete trailing whitespace for C and manpage sources.
+ */
+void
+deltspace_hook(void)
+{
+ struct line *lp;
+
+ lp = curbp->b_headp;
+ if (fnmatch("*.[ch1-9]", curbp->b_fname, 0) != 0)
+ return;
+ for (lp = bfirstlp(curbp); lp != curbp->b_headp; lp = lforw(lp))
+ if (lp->l_text != NULL)
+ ttrim(lp);
+}
+
+/*
+ * Lines are not NUL terminated, reduce l_used to actually trim.
+ */
+void
+ttrim(struct line *lp)
+{
+ char *s;
+
+ s = lp->l_text + lp->l_used - 1;
+ while (isspace(*s) && s-- > lp->l_text)
+ lp->l_used--;
+}
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic