- [ ] If a pane wants to block mouse events from parents, as lib-view
does, it shouldn't need to catch all the combinations, or it
should be much easier
-- [ ] gather memory usage stats per-pane and allow a dump
+- [ ] gather memory usage stats per-pane, ensure 0 on close, and allow a dump
- [ ] show doc size in doc list - include undo size?
- [X] Ensure all panes that should use "Free" properly, and find some
way to encourage its use.
- [ ] design a way for a keystroke to interrupt a long-running function.
- [ ] extend Draw:measure protocol to allow constant-width-fonts to
cannot-scale displays can be detected and measurement optimised for.
-- [ ] improve timeout. Set timer once, then set a flag so that all commands fail
+- [X] improve timeout. Set timer once, then set a flag so that all commands fail
until some top-level clears the flag.
- [ ] reconsider all 'return comm_call()' calls. Do we every really
care if the callback succeeded?
the call which gave access to it, unless it registers for
notifications from the owner, and that probably only applies to
points.
+- [ ] do something useful on SIGINT - maybe expedite times_up().
### Longer term
- [ ] support $SUBST in file-open path names ??
- [ ] Need a debug mode where every mark usage is checked for validity.
also check the setref sets up all linkages.
-- [ ] remove all FIXMEs (there are 65) ... and any HACKs (2).
+- [ ] remove all FIXMEs (there are 77) ... and any HACKs (5).
- [ ] Replace asserts with warnings where possible.
- [ ] hide view-num inside pane so number cannot be misused.
i.e. each view is owned by a pane and can only be used by that pane.
### pygtk
-- [ ] can we capture the substates of character composition, and give feed-back?
+- [ ] can we capture the substates of character composition, and give
+ feed-back?
### display-x11-xcb
### lib-macro
-- [ ] don't allow starting macro inside a macro
+- [X] don't allow starting macro inside a macro
- [ ] detect errors including Abort and search failure etc. Abort capture or
replay on error
- [ ] Possibly wait for a shell-command etc to complete before continuing.
- [ ] things slow down after lots of edits. Maybe track
number of chunk, marks, undos etc and display them somewhere
- [ ] stop consistency checking a doc when it gets "big" ??
-- [ ] avoid infinite loops in consistency checks
+- [X] avoid infinite loops in consistency checks
- [ ] doc-text: opening file with e.g. 200,000 lines is very slow
Check this..
- [ ] moving in a big file is slow - check this
### lang-python
- [ ] review python doc:char implementations for simplification.
-- [ ] repeated alarm(10)/alarm(0) calls slow things down
+- [X] repeated alarm(10)/alarm(0) calls slow things down
- [ ] array index should allow two args, second being a mark for
doc:get-attr etc.
- [ ] should be able to test if a mark is NULL or Freed
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
+#include <signal.h>
#include <fcntl.h>
#include <stdarg.h>
#include <dlfcn.h>
return 1;
}
#endif
- if (key_lookup_prefix(map, ci) > 0)
+ /* Multiple modules can support module lookup, such as
+ * global-load-modules:python or global-load-module:lua.
+ * So do a prefix lookup.
+ */
+ if (key_lookup_prefix(map, ci, False) > 0)
return 1;
LOG("Failed to load module: %s", name);
return Efail;
*/
struct ed_info *ei = ci->home->data;
struct map *map = ei->map;
- int ret = key_lookup_prefix(map, ci);
+ int ret = key_lookup_prefix(map, ci, False);
if (ret)
return ret;
/* pointless to autoload for refresh */
return Efallthrough;
call("attach-libevent", ci->home);
- return key_lookup_prefix(map, ci);
+ return key_lookup_prefix(map, ci, False);
}
DEF_CMD(editor_activate_display)
const char *key = ci->key;
((struct cmd_info*)ci)->key = ksuffix(ci, "global-multicall-");
- ret = key_lookup_prefix(map, ci);
+ ret = key_lookup_prefix(map, ci, False);
((struct cmd_info*)ci)->key = key;
return ret;
}
return Efalse;
}
+static struct pane *editor;
+static void catch(int sig)
+{
+ struct cmd_info ci;
+ if (!editor)
+ return;
+ signal(sig, catch);
+ ci.home = editor;
+ ci.focus = editor;
+ ci.num = sig;
+ ci.num2 = 0;
+ ci.str = ci.str2 = NULL;
+ ci.mark = ci.mark2 = NULL;
+ ci.x = ci.y = 0;
+ switch (sig) {
+ case SIGALRM:
+ ci.key = "fast-alarm-";
+ key_lookup_prefix(editor->data->map, &ci, True);
+ break;
+ case SIGINT:
+ ci.key = "fast-interrupt-";
+ key_lookup_prefix(editor->data->map, &ci, True);
+ break;
+ }
+}
+
struct pane *editor_new(const char *comm_name)
{
struct pane *ed;
log_setup(ed);
window_setup(ed);
+ signal(SIGINT, catch);
+ signal(SIGALRM, catch);
+
+ editor = ed;
return ed;
}
}
}
-int key_lookup_prefix(struct map *m safe, const struct cmd_info *ci safe)
+int key_lookup_prefix(struct map *m safe, const struct cmd_info *ci safe,
+ bool simple)
{
+ /* A "Simple" lookup avoids the backtrace. It is used in
+ * signal handlers.
+ */
const char *k = ci->key;
int len = strlen(k);
int pos = key_find(m, k);
if (comm && comm != prev) {
((struct cmd_info*)ci)->comm = comm;
((struct cmd_info*)ci)->key = m->keys[pos+i];
- ret = do_comm_call(comm, ci);
+ if (simple)
+ ret = comm->func(ci);
+ else
+ ret = do_comm_call(comm, ci);
ASSERT(ret >= Efallthrough || ret < Eunused);
prev = comm;
/* something might have been added, recalc
+#include <unistd.h>
+
struct pane {
const char *name; /* For easy discovery in gdb */
struct pane *parent safe;
static inline void time_starts(struct pane *p safe)
{
pane_set_time(pane_root(p));
+ alarm(15);
}
static inline void time_ends(struct pane *p safe)
{
+ alarm(0);
pane_end_time(pane_root(p));
}
void key_free(struct map *m safe);
int key_handle(const struct cmd_info *ci safe);
int key_lookup(struct map *m safe, const struct cmd_info *ci safe);
-int key_lookup_prefix(struct map *m safe, const struct cmd_info *ci safe);
+int key_lookup_prefix(struct map *m safe, const struct cmd_info *ci safe,
+ bool simple);
struct command *key_lookup_cmd(struct map *m safe, const char *c safe);
void key_add(struct map *map safe, const char *k safe, struct command *comm);
void key_add_range(struct map *map safe,
return 1;
}
-static void python_interrupt(int sig)
+static bool python_running;
+DEF_CB(handle_alarm)
{
- /* Python code has been running for too long,
- * interrupt it.
- */
- kill(getpid(), 2);
+ if (python_running)
+ PyErr_SetInterrupt();
+ return 1;
}
REDEF_CB(python_call)
Py_BuildValue("ii", ci->x, ci->y));
if (rv && pc->callable) {
- signal(SIGALRM, python_interrupt);
- alarm(10);
+ python_running = True;
ret = PyObject_Call(pc->callable, args, kwds);
- alarm(0);
- signal(SIGALRM, SIG_DFL);
+ python_running = False;
}
Py_DECREF(args);
int rv;
PyObject *s1, *s2;
struct pyret pr;
- int remain;
- sighandler_t oldhan;
if (!pane_valid(self))
return NULL;
return NULL;
}
- remain = alarm(0);
- oldhan = signal(SIGALRM, SIG_DFL);
+ python_running = False;
rv = key_handle(&ci);
- if (oldhan != SIG_DFL) {
- signal(SIGALRM, oldhan);
- alarm(remain);
- }
+ python_running = True;
/* Just in case ... */
PyErr_Clear();
PyObject *m;
PyConfig config;
char *argv[2]= { "edlib", NULL };
+ sighandler_t sigint;
if (edlib_module_path)
module_dir = strdup(edlib_module_path);
else
module_dir = ".";
+ /* de-register SIGINT while we initialise python,
+ * so that Python thinks that it's registration is
+ * valid - so PyErr_SetInterrupt() don't think there
+ * is a race.
+ */
+ sigint = signal(SIGINT, SIG_DFL);
PyConfig_InitPythonConfig(&config);
config.isolated = 1;
PyConfig_SetBytesArgv(&config, 0, argv);
Py_InitializeFromConfig(&config);
PyConfig_Clear(&config);
+ signal(SIGINT, sigint);
PaneType.tp_new = PyType_GenericNew;
PaneIterType.tp_new = PyType_GenericNew;
EdlibModule = m;
ed_pane = ed;
+ call_comm("global-set-command", ed, &handle_alarm,
+ 0, NULL, "fast-alarm-python");
+
call_comm("global-set-command", ed, &python_load_module,
0, NULL, "global-load-modules:python");
}