]> git.neil.brown.name Git - edlib.git/commitdiff
mark: separate mark:moving from mark:arrived
authorNeilBrown <neil@brown.name>
Sat, 27 May 2023 07:46:18 +0000 (17:46 +1000)
committerNeilBrown <neil@brown.name>
Sun, 28 May 2023 23:25:52 +0000 (09:25 +1000)
The mark:moving notification was originally for when a specific mark
moved at all.
For b64 I extended it to also notify when *any* mark moved to a specific
mark.
This can cause illegal nested notification if a mark:moving handler
tries to move a (non-specific) mark.  That is bad.

So separate the two: Add mark:arrived for when a mark is moved to a
flagged marks.

Also make sure all new marks aren't flagged.  I invert the sense of the
flag and call it "MARK_FLAG_WATCHED".  This will be clear by default,
and only set once the (renamed) mark_watch() is called.

Signed-off-by: NeilBrown <neil@brown.name>
DOC/Developer/03-documents.md
DOC/TODO.md
core-doc.c
core-mark.c
core.h
lang-python.c
lib-base64.c
lib-view.c
python/render-c-mode.py

index 034ad8f123771dbfdb5762329109a9655542ca8d..1d3cf81ebc69c883d3777fdd75a12cef6864f9c9 100644 (file)
@@ -72,13 +72,24 @@ group, then some searching may be required to find a specific nearby
 mark.  When you start with a pointer you can immediately find a nearby
 mark of any group.  Pointers cannot store extra arbitrary data.
 
-The first time a mark is moved to a different location in the document a
-"mark:moving" message is sent to the pane which owns the mark (usually a
-document).  Subsequent movement will not cause any notification until
-"mark_ack(mark)" is called.  This clears a flag on the mark so that the
-next movement will again cause a message to be sent.  This is useful for
-various tasks including ensuring that any drawing of the cursor is
-updated properly.
+Calling "mark_watch(mark)" on a mark causes it to have a flag set so
+that certain movements of marks cause a notification to be sent to the
+pane which owns the mark - usually a document.  When a notification is
+sent, the "watched" flag is cleared on the mark that was moved (if it
+was already set), so the notification handler will need to call
+mark_watch(mark) again if it needs to see the next movement.
+
+Whenever a watch mark is moved, whether by a movement command
+("doc:char", "doc:set-ref" etc) or by moving it to the location of
+another mark with mark_to_mark(), a "mark:moving" notification is sent
+to the owner of the mark.  The primary mark in the notification is the
+mark that was moved.  The focus is the mark owner.
+
+Whenever a mark is moved with mark_to_mark() to a mark which is watched,
+a "mark:arrived" notification is sent to the mark owner.  In this case
+the destination mark is passed to the notification as the secondary mark
+(mark2).  If mark_to_mark() is called with both marks being watch, both
+notifications are sent.
 
 ### working with marks
 
@@ -88,7 +99,7 @@ The following ..
 - mark_dup(mark)
 - mark_dup_view(mark)
 - mark_free(mark)
-- mark_ack(mark)
+- mark_watch(mark)
 - mark_next(mark)
 - mark_prev(mark)
 - mark_reset(pane, mark, int)
index 6e14ff90ddac5f068bb27846e9357fdf7e08c970..8a912fbc18203a5b6206e2a5ee100619d5afb1e5 100644 (file)
@@ -46,6 +46,8 @@ Current priorities
 - [ ] commands to resolve a conflict
 - [ ] command to apply a patch hunk
 - [ ] whitespace: don't show errors unless doc has been changed.???
+- [ ] mailto: links should be sent to nm (if active)
+- [ ] press K:Enter on a link should do something
 
 - [ ] split notmuch into two databases, last 6 months and the rest.
 - [ ] script to move messages every week - but not deleted messages
@@ -56,9 +58,14 @@ Current priorities
 Bugs to be fixed
 ----------------
 
-- [ ] I cannot dup a mark in a mark:moving handler.  That is too
+- [ ] multipart must handle Notify:Close better.  It should NULL out the
+      pointer to the pane, and always check it isn't NULL.
+- [X] I cannot dup a mark in a mark:moving handler.  That is too
       restrictive.  I need a different way to decide that incoming marks
       get notified.
+      Maybe generate "mark:arrived" when a mark is moved to an
+      interesting mark, and flag new marks as "moved" so they don't
+      initially send a mark:moved notification.
 - [X] doc:text passes an unterminated string to "content" for
       doc:content.  num2 is the length.  python doesn't know this
       and so tries to convert it all to utf8.  This is wasteful as
@@ -73,8 +80,11 @@ Bugs to be fixed
       double them
 - [X] when w3m text is copied we get the markup.  I find this useful,
       but is it *right*??
-- [ ] notmuch: don't mark up links in text created by w3m - they are
-      already marked if needed.
+- [X] notmuch: don't mark up links in text created by w3m - they are
+      already marked if needed.  This was fixed by making conversion
+      async so:
+- [ ] async email part converts need to do their own URL marking.
+      PDF particularly, and html2md.  Maybe others.
 - [X] notmuch: "reply" should clear unread/new flags.
 - [X] transparent images appear in email with horiz lines
 - [X] Replying to w3m/html mail results in unsightly markup in reply
@@ -84,7 +94,7 @@ Bugs to be fixed
       isn't an md-mode yet!
 - [X] config.py should load from $HOME/.config/edlib/config.py
         exec(read())
-- [ ] lang-python should put each mode in a separate module
+- [ ] lang-python should put each module in a separate module
       Maybe PyImport_ExecCodeModuleEx() after reading and compile()ing
       the source file.  Or set up path to find edlib modules.
 - [X] redefining doc:char but not doc:content in mail-compose causes
@@ -108,6 +118,7 @@ Bugs to be fixed
 - [ ] email: urls should not be followed unless they are visible.
       Maybe display in the message window, which might be made larger
       just for this purpose.
+      Maybe "Message-button"
 - [ ] renderline *knows* about scaling and when it places the cursor
       in an image, it gets it wrong for ncurses.  It should ask about
       scaling.
index 5100b02df284f45af36f637e77d8ad5b73e1eb8c..0066ff438743d77deacf2246933e5bebc6fcecfb 100644 (file)
@@ -978,7 +978,7 @@ DEF_CMD(doc_refresh_view)
                dd->old_point = mark_dup(dd->point);
        else
                mark_to_mark(dd->old_point, dd->point);
-       mark_ack(dd->point);
+       mark_watch(dd->point);
        return 1;
 }
 
@@ -1333,7 +1333,7 @@ static void do_doc_assign(struct pane *p safe, struct pane *doc safe)
        pane_add_notify(p, doc, "doc:notify-viewers");
        pane_add_notify(p, doc, "mark:moving");
        call("doc:notify:doc:revisit", doc, 0);
-       mark_ack(m);
+       mark_watch(m);
 }
 
 static struct pane *doc_attach(struct pane *parent)
index 867db3ace5fd520fea86035df2840242543b4828..86a2a0585853eabda99bdb00941b621969bad0fa 100644 (file)
@@ -210,19 +210,19 @@ void mark_free(struct mark *m)
 
 static void notify_mark_moving(struct mark *m safe, struct mark *m2)
 {
-       if (m2 && !(m2->flags & MARK_FLAG_MOVED))
-               /* Any mark moved here is notified */;
-       else if (m->flags & MARK_FLAG_MOVED)
-               return;
-       m->flags |= MARK_FLAG_MOVED;
+       if (m->flags & MARK_FLAG_WATCHED) {
+               m->flags &= ~MARK_FLAG_WATCHED;
+               pane_notify("mark:moving", m->owner, 0, m);
+       }
 
-       pane_notify("mark:moving", m->owner, 0, m, NULL, 0, m2);
+       if (m2 && (m2->flags & MARK_FLAG_WATCHED))
+               pane_notify("mark:arrived", m->owner, 0, m, NULL, 0, m2);
 }
 
-void mark_ack(struct mark *m)
+void mark_watch(struct mark *m)
 {
        if (m)
-               m->flags &= ~MARK_FLAG_MOVED;
+               m->flags |= MARK_FLAG_WATCHED;
 }
 
 static void mark_ref_copy(struct mark *to safe, struct mark *from safe)
@@ -492,7 +492,6 @@ struct mark *doc_new_mark(struct pane *p safe, int view, struct pane *owner)
        INIT_TLIST_HEAD(&ret->view, GRP_MARK);
        ret->viewnum = view;
        hlist_add_head(&ret->all, &d->marks);
-       ret->flags = MARK_FLAG_MOVED;
 
        if (view == MARK_POINT) {
                struct point_links *lnk = alloc_buf(sizeof(*lnk) +
diff --git a/core.h b/core.h
index 7406eacc237e355eb4de40d3942e40a7efbcd74e..9734cafa2502f29dd0e88f877764634ccee520ba 100644 (file)
--- a/core.h
+++ b/core.h
@@ -224,7 +224,7 @@ struct mark {
                                              * understands .ref
                                              */
 };
-#define MARK_FLAG_MOVED                1
+#define MARK_FLAG_WATCHED      1
 
 static inline bool mark_valid(struct mark *m)
 {
@@ -245,7 +245,7 @@ struct point_links {
 struct mark *safe mark_dup(struct mark *m safe);
 struct mark *safe mark_dup_view(struct mark *m safe);
 void mark_free(struct mark *m);
-void mark_ack(struct mark *m);
+void mark_watch(struct mark *m);
 
 struct mark *mark_first(struct doc *d safe);
 struct mark *mark_next(struct mark *m safe);
index 070a3a8cbc75146f62156289bb4d586370c1cae2..fb2eb7bfbf639c0b9c00a2233738ac5a03e3cd6a 100644 (file)
@@ -2303,7 +2303,7 @@ static PyObject *Mark_release(Mark *self safe, PyObject *args)
        return Py_None;
 }
 
-static PyObject *Mark_ack(Mark *self safe, PyObject *args)
+static PyObject *Mark_watch(Mark *self safe, PyObject *args)
 {
        struct mark *m = self->mark;
 
@@ -2311,7 +2311,7 @@ static PyObject *Mark_ack(Mark *self safe, PyObject *args)
                PyErr_SetString(PyExc_TypeError, "Mark has been freed");
                return NULL;
        }
-       mark_ack(m);
+       mark_watch(m);
        Py_INCREF(Py_None);
        return Py_None;
 }
@@ -2335,7 +2335,7 @@ static PyMethodDef mark_methods[] = {
         "If this mark is in range, move to end"},
        {"release", (PyCFunction)Mark_release, METH_NOARGS,
         "release a vmark so it can disappear"},
-       {"ack", (PyCFunction)Mark_ack, METH_NOARGS,
+       {"watch", (PyCFunction)Mark_watch, METH_NOARGS,
         "acknowledge movement of a point - allow further notifications"},
        {"step", (PyCFunction)Mark_step, METH_VARARGS,
         "Move mark over any adjacent marks with same reference"},
index ceba1a2c1c8bc6e90fdc5ba6e2d778c78f69cac3..9594d82f5bea73e5bdc63e4679277387640fa4ae 100644 (file)
@@ -12,7 +12,7 @@
  * stacking b64 impossible - but who would want to?
  * This can have a value "0", "1", "2".  A mark is never on the
  * 4th char of a QUAD.
- * doc:set-ref initialises this as does a mark:moving notification
+ * doc:set-ref initialises this as does a mark:arrived notification
  * which references another mark.  doc:char and doc:byte will use
  * the pos to know how to interpret, and will update it after any
  * movement as will doc:content.
@@ -90,7 +90,7 @@ static void set_pos(struct mark *m safe, int pos)
                pos -= 4;
        ps[0] += pos;
        attr_set_str(&m->attrs, "b64-pos", ps);
-       mark_ack(m);
+       mark_watch(m);
 }
 
 static int get_pos(struct mark *m safe)
@@ -227,7 +227,7 @@ DEF_CMD(base64_setref)
        return Efallthrough;
 }
 
-DEF_CMD(base64_moving)
+DEF_CMD(base64_arrived)
 {
        struct mark *m = ci->mark;
        struct mark *ref = ci->mark2;
@@ -238,7 +238,7 @@ DEF_CMD(base64_moving)
 
        if (get_pos(m) >= 0)
                /* Interesting mark, keep tracking it */
-               mark_ack(m);
+               mark_watch(m);
        if (!ref)
                return 1;
        pos = get_pos(ref);
@@ -436,7 +436,7 @@ DEF_CMD(b64_attach)
        p = pane_register(ci->focus, 0, &b64_handle.c);
        if (!p)
                return Efail;
-       call("doc:request:mark:moving", p);
+       call("doc:request:mark:arrived", p);
 
        return comm_call(ci->comm2, "callback:attach", p);
 }
@@ -451,7 +451,7 @@ void edlib_init(struct pane *ed safe)
        key_add(b64_map, "doc:content", &base64_content);
        key_add(b64_map, "doc:content-bytes", &base64_content);
        key_add(b64_map, "doc:set-ref", &base64_setref);
-       key_add(b64_map, "mark:moving", &base64_moving);
+       key_add(b64_map, "mark:arrived", &base64_arrived);
        key_add(b64_map, "Free", &edlib_do_free);
 
        call_comm("global-set-command", ed, &b64_attach, 0, NULL, "attach-base64");
index 019b94fa96912c49247b8446033976de478e4a12..fb94af3b174619e65cbdca2abd685794a882c8da 100644 (file)
@@ -182,7 +182,7 @@ DEF_CMD(view_refresh)
                title = default_title;
        title = format_status(title, ci->focus, pm);
 
-       mark_ack(pm);
+       mark_watch(pm);
 
        if (vd->border & BORDER_LEFT) {
                /* Left border is (currently) always a scroll bar */
index d5cf15d1b97efe585a067cb963f87b2ca89e7dab..eefa5f0527a8311bf312afde927e2220fa9c052e 100644 (file)
@@ -913,7 +913,7 @@ class CModePane(edlib.Pane):
     def handle_refresh(self, key, focus, **a):
         "handle:Refresh:view"
         point = focus.call("doc:point", ret = 'mark')
-        point.ack()
+        point.watch()
         skip_pre = False
         skip_post = False
         if self.pre_paren: