O/lib-search.o O/lib-messageline.o O/lib-input.o O/lib-libevent.o \
O/lib-history.o O/lib-crop.o O/lib-markup.o O/lib-rfc822header.o \
O/lib-viewer.o O/lib-base64.o O/lib-qprint.o O/lib-utf8.o \
- O/lib-charset.o \
+ O/lib-charset.o O/lib-config.o \
O/lib-copybuf.o O/lib-whitespace.o O/lib-colourmap.o \
O/lib-renderline.o O/lib-x11selection-gtk.o O/lib-autosave.o \
O/lib-x11selection-xcb.o O/display-x11-xcb.o \
"open-doc-email");
call_comm("global-set-command", ed, &attach_email_view, 0, NULL,
"attach-email-view");
-
- call("global-load-module", ed, 0, NULL, "lib-html-to-text");
- call("global-load-module", ed, 0, NULL, "lib-html-w3m");
-
- call("global-load-module", ed, 0, NULL, "lib-pdf-to-text");
- call("global-load-module", ed, 0, NULL, "lib-doc-to-text");
- call("global-load-module", ed, 0, NULL, "lib-ical-to-text");
}
setlocale(LC_ALL, "");
setlocale(LC_CTYPE, "enUS.UTF-8");
+ call("global-load-module", ed, 0, NULL, "lib-config");
+ call("config-load", ed, 0, NULL, "edlib.ini", 0, NULL, argv[0]);
+
call("attach-doc-docs", ed);
- call("global-load-module", ed, 0, NULL, "lib-linecount");
- call("global-load-module", ed, 0, NULL, "lib-search");
- call("global-load-module", ed, 0, NULL, "lib-popup");
- call("global-load-module", ed, 0, NULL, "lang-python");
- call("global-load-module", ed, 0, NULL, "doc-text");
- call("global-load-module", ed, 0, NULL, "doc-dir");
- call("global-load-module", ed, 0, NULL, "render-hex");
- call("global-load-module", ed, 0, NULL, "render-present");
- call("global-load-module", ed, 0, NULL, "render-lines");
- call("global-load-module", ed, 0, NULL, "module-notmuch");
- call("global-load-module", ed, 0, NULL, "doc-email");
- call("global-load-module", ed, 0, NULL, "lib-viewer");
- call("global-load-module", ed, 0, NULL, "lib-qprint");
- call("global-load-module", ed, 0, NULL, "lib-copybuf");
- call("global-load-module", ed, 0, NULL, "lib-colourmap");
- call("global-load-module", ed, 0, NULL, "lib-textfill");
- call("global-load-module", ed, 0, NULL, "lib-autosave");
- call("global-load-module", ed, 0, NULL, "render-format");
-
- call("global-load-module", ed, 0, NULL, "render-c-mode");
- call("global-load-module", ed, 0, NULL, "lib-make");
- call("global-load-module", ed, 0, NULL, "lib-server");
- call("global-load-module", ed, 0, NULL, "lib-utf8");
- call("global-load-module", ed, 0, NULL, "lib-charset");
-
- call("global-load-module", ed, 0, NULL, "config");
while (optind < argc) {
char *file = argv[optind++];
--- /dev/null
+
+include = config.ini
+
+[module]
+
+lang-python = global-load-modules:python
+
+lib-popup = PopupTile
+lib-linecount =
+ Countlines
+ CountLinesAsync
+lib-search =
+ text-search
+ text-match
+ make-search
+ text-equals
+doc-text =
+ attach-doc-text
+ open-doc-text
+doc-dir =
+ attach-doc-dir
+ open-doc-dir
+doc-email =
+ open-doc-email
+ attach-email-view
+
+display-x11-xcb =
+ interactive-cmd-x11window
+ attach-display-x11
+display-pygtk =
+ interactice-cmd-gtkwindow
+ attach-display-gtk
+
+render-hex =
+ attach-render-hex
+ doc:appeared-hex
+render-present =
+ attach-markdown-present
+ attach-present
+ doc:appeared-present
+render-lines =
+ attach-render-lines
+ attach-render-text
+render-format = attach-render-format
+render-c-mode =
+ doc:appeared-c-mode
+ doc:appeared-py-mode
+ interactive-cmd-indent
+
+lib-viewer =
+ attach-viewer
+ doc:appeared-viewer
+lib-qprint =
+ attach-quoted_printable
+ attach-qprint
+lib-copybuf =
+ copy:save
+ copy:get
+lib-colourmap = colour:map
+lib-textfill =
+ attach-textfill
+ interactive-cmd-fill-mode
+lib-autosave =
+ startup-autosave
+ interactice-cmd-recover
+ doc:appeared-check-autosave
+lib-make =
+ interactive-cmd-make
+ interactive-cmd-grep
+ interactive-cmd-git-grep
+ interactive-cmd-next-match
+lib-server = ALWAYS
+lib-macro = macro:capture
+lib-aspell =
+ Spell:Check
+ Spell:Suggest
+ Spell:ThisWord
+ Spell:NextWord
+lib-calc =
+ CalcExpr
+ interactive-cmd-calc-replace
+render-calc =
+ interactive-cmd-calc
+ doc:appeared-calc
+lib-mergeview =
+ interactice-cmd-merge-mode
+ doc:appeared-mergeview
+lib-compose-email = attach-compose-email
+lib-autospell =
+ interactive-cmd-autospell
+ attach-autospell
+lib-whitespace =
+ attach-whitespace
+ interactice-cmd-whitespace-mode
+lib-x11selection-xcb = attach-x11selection
+lib-url =
+ url:mark-up
+ attach-render-url-view
+lib-diff =
+ attach-diff
+ interactive-cmd-diff-mode
+lib-wiggle = MakeWiggle
+
+module-notmuch =
+ interactive-cmd-nm
+ interactive-cmd-nmc
+ interactive-cmd-nms
+
+emacs-search =
+ attach-emacs-search
+ attach-emacs-search-highlight
+
+lib-html-to-text = html-to-text
+lib-html-w3m = html-to-text-w3m
+lib-pdf-to-text = pdf-to-text
+lib-doc-to-text = doc-to-text
+lib-ical-to-text = ical-to-text
+lib-utf8 =
+ attach-charset-utf-8
+ attach-utf8
+lib-charset = ALWAYS
+
+config = ALWAYS
--- /dev/null
+/*
+ * Copyright Neil Brown ©2023 <neil@brown.name>
+ * May be distributed under terms of GPLv2 - see file:COPYING
+ *
+ * Read an "ini" config file and set some attributes.
+ * Sections:
+ * global - set attr on editor
+ * module - set trigger to load module
+ * file:pattern - set attributes when matching file visited
+ * (not implemented fully yet)
+ *
+ * When not in a section, include= will load another file.
+ *
+ * Syntax for ini file
+ * - individual lines must not exceed 256 chars. Longer lines are
+ * silently truncated.
+ * - leading white space continues the previous line, this allowing large
+ * values. The newline and leading white space are stripped.
+ * - white space around "=", at EOL, and around section name in [section]
+ * is stripped
+ * - Double quotes at both ends of a value are stripped.
+ * - If first non-white is '#', line is ignored.
+ * - Everything after closing ']' of section is ignored
+ * - If value is no quoted, everything after first '#' is ignored
+ * - blank lines are ignored
+ */
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <ctype.h>
+#include "core.h"
+
+typedef void (*ini_handle)(void *data, char *section safe,
+ char *name safe, char *value safe,
+ const char *path safe,
+ int append);
+static void load_config(const char *path safe, struct pane *ed, const char *base);
+
+static void parse_ini(const char *path safe, ini_handle handle, void *data)
+{
+ FILE *f = fopen(path, "r");
+ char line[257];
+ char section[257] = "";
+ char name[257] = "";
+
+ if (!f)
+ return;
+ while (fgets(line, sizeof(line), f) != NULL) {
+ char *st, *eq;
+ char *eol = strchr(line, '\n');
+ int append, quote;
+
+ if (!eol) {
+ int ch;
+ while ((ch = fgetc(f)) != '\n' &&
+ ch != EOF)
+ ;
+ } else
+ *eol = 0;
+ if (line[0] == '[') {
+ eol = strchr(line, ']');
+ if (!eol)
+ continue;
+ while (eol > line && isblank(eol[-1]))
+ eol -= 1;
+ *eol = 0;
+ st = line+1;
+ while (isblank(*st))
+ st += 1;
+ strcpy(section, st);
+ name[0] = 0;
+ continue;
+ }
+ /* find/strip comment */
+ st = line; quote = 0;
+ while (*st && (quote || *st != '#')) {
+ if (*st == '"')
+ quote = !quote;
+ st += 1;
+ }
+ if (*st == '#')
+ *st = 0;
+ if (isblank(line[0])) {
+ if (!name[0])
+ /* Nothing to continue */
+ continue;
+ st = line;
+ while (isblank(*st))
+ st += 1;
+ if (!*st)
+ /* Blank line */
+ continue;
+ append = 1;
+ } else {
+ name[0] = 0;
+ /* There must be an '=' */
+ eq = strchr(line, '=');
+ if (!eq)
+ continue;
+ st = eq + 1;
+ while (eq > line && isblank(eq[-1]))
+ eq -= 1;
+ *eq = 0;
+ if (!line[0])
+ /* No name before '=' */
+ continue;
+ strcpy(name, line);
+ append = 0;
+ }
+ /* A value is at 'st', to be set or appended */
+ eol = st + strlen(st);
+ while (isblank(*st))
+ st += 1;
+ while (eol > st && isblank(eol[-1]))
+ eol -= 1;
+ if (*st == '"' && eol > st + 1 && eol[-1] == '"') {
+ st += 1;
+ eol -= 1;
+ }
+ *eol = 0;
+ handle(data, section, name, st, path, append);
+ }
+ fclose(f);
+}
+
+struct mod_cmd {
+ char *module;
+ int tried;
+ struct command c;
+};
+
+DEF_CB(autoload)
+{
+ struct mod_cmd *mc = container_of(ci->comm, struct mod_cmd, c);
+
+ if (mc->tried)
+ return Efallthrough;
+ mc->tried = 1;
+
+ /* NOTE: this might free mc, so don't touch it again */
+ call("global-load-module", ci->home, 0, NULL, mc->module);
+ return home_call(ci->home, ci->key, ci->focus,
+ ci->num, ci->mark, ci->str,
+ ci->num2, ci->mark2, ci->str2,
+ ci->x, ci->y, ci->comm2);
+}
+
+static void al_free(struct command *c safe)
+{
+ struct mod_cmd *mc = container_of(c, struct mod_cmd, c);
+
+ free(mc->module);
+ free(mc);
+}
+
+static void handle(void *data, char *section safe, char *name safe, char *value safe,
+ const char *path safe, int append)
+{
+ struct pane *p = data;
+
+ if (!p)
+ return;
+
+ if (strcmp(section, "") == 0) {
+ if (strcmp(name, "include") == 0) {
+ load_config(value, p, path);
+ return;
+ }
+ return;
+ }
+
+ if (strcmp(section, "global") == 0) {
+ call("global-set-attr", p, append, NULL, name,
+ 0, NULL, value);
+ return;
+ }
+
+ if (strcmp(section, "module") == 0 && value[0]) {
+ struct mod_cmd *mc;
+ if (strcmp(value, "ALWAYS") == 0) {
+ call("global-load-module", p, 0, NULL, name);
+ return;
+ }
+ mc = malloc(sizeof(*mc));
+ mc->module = strdup(name);
+ mc->tried = 0;
+ mc->c = autoload;
+ mc->c.free = al_free;
+ call_comm("global-set-command", p, &mc->c, 0, NULL,
+ value);
+ return;
+ }
+
+ if (strncmp(section, "file:", 5) == 0) {
+ char *k = strconcat(NULL, "global-file-attr:", section+5);
+ call(k, p, append, NULL, name, 0, NULL, value);
+ return;
+ }
+}
+
+static void load_config(const char *path safe, struct pane *ed, const char *base)
+{
+ char *sl, *p, *h;
+ if (*path == '/') {
+ parse_ini(path, handle, ed);
+ return;
+ }
+ /*
+ * Relative paths can be loaded from:
+ * dirname(base)
+ * /usr/share/edlib/
+ * $HOME/.config/edlib/
+ */
+ if (base && (sl = strrchr(base, '/')) != NULL) {
+ sl += 1;
+ p = malloc((sl - base) + strlen(path) + 1);
+ memcpy(p, base, sl - base);
+ strcpy(p + (sl - base), path);
+ if (access(p, F_OK) == 0) {
+ parse_ini(p, handle, ed);
+ free(p);
+ return;
+ }
+ free(p);
+ }
+ p = strconcat(NULL, "/usr/share/edlib/", path);
+ if (access(p, F_OK) == 0) {
+ parse_ini(p, handle, ed);
+ free(p);
+ return;
+ }
+ free(p);
+
+ h = getenv("HOME");
+ if (h == NULL || *h != '/')
+ return;
+ p = strconcat(NULL, h, "/.config/edlib/", path);
+ if (access(p, F_OK) == 0) {
+ parse_ini(p, handle, ed);
+ free(p);
+ return;
+ }
+ free(p);
+}
+
+DEF_CMD(config_load)
+{
+ if (ci->str)
+ load_config(ci->str, ci->home, ci->str2);
+ return 1;
+}
+
+void edlib_init(struct pane *ed safe)
+{
+ call_comm("global-set-command", ed, &config_load,
+ 0, NULL, "config-load");
+}
call_comm("global-set-command", ed, &attach_mode_emacs, 0, NULL, "attach-mode-emacs");
call_comm("global-set-command", ed, &attach_file_entry, 0, NULL, "attach-file-entry");
call_comm("global-set-command", ed, &emacs_shell, 0, NULL, "attach-shell-prompt");
-
- call("global-load-module", ed, 0, NULL, "emacs-search");
- call("global-load-module", ed, 0, NULL, "lib-macro");
- call("global-load-module", ed, 0, NULL, "lib-aspell");
- call("global-load-module", ed, 0, NULL, "lib-calc");
}
" *[0-9]*\\.)") # Numbered list
editor.call("global-set-command", "doc:appeared-config", config_appeared)
-
-# Some modules I want auto-loaded.
-editor.call("global-load-module", "lib-mergeview")
-editor.call("global-load-module", "render-calc")
-editor.call("global-load-module", "lib-compose-email")
-editor.call("global-load-module", "lib-autospell")
-editor.call("global-load-module", "lib-whitespace")
-editor.call("global-load-module", "display-pygtk")
-editor.call("global-load-module", "display-x11-xcb")
-editor.call("global-load-module", "lib-x11selection-xcb")
-editor.call("global-load-module", "lib-url")
-
-if 'HOME' in os.environ:
- path = os.environ['HOME'] + "/.config/edlib/config.py"
-try:
- with open(path, 'r') as fp:
- out = fp.read()
- exec(out)
-except:
- pass
edlib.editor.call("global-set-command", "attach-diff", diff_view_attach)
edlib.editor.call("global-set-command", "interactive-cmd-diff-mode", add_diff)
-edlib.editor.call("global-load-module", "lib-wiggle")
edlib.editor.call("global-set-command", "attach-merge", merge_view_attach)
edlib.editor.call("global-set-command", "interactive-cmd-merge-mode", add_merge)
-edlib.editor.call("global-load-module", "lib-wiggle")
edlib.editor.call("global-set-command", "doc:appeared-mergeview", merge_appeared)
return edlib.Efallthrough
edlib.editor.call("global-set-command", "attach-view-calc", calc_view_attach)
-edlib.editor.call("global-load-module", "lib-calc")
edlib.editor.call("global-set-command", "interactive-cmd-calc", add_calc)
edlib.editor.call("global-set-command", "doc:appeared-calc", calc_appeared)