commit 8b0cb7b261b5b5443413aac65dcfc7a934838f90 (HEAD, refs/remotes/origin/master) Author: Michael Albinus Date: Fri May 3 10:05:15 2019 +0200 ; Fix declaration in tramp-compat.el diff --git a/lisp/net/tramp-compat.el b/lisp/net/tramp-compat.el index a05c841978..b8a2b45136 100644 --- a/lisp/net/tramp-compat.el +++ b/lisp/net/tramp-compat.el @@ -45,8 +45,8 @@ (require 'timer) (require 'ucs-normalize) -(declare-function tramp-compat-file-local-name 'tramp-compat) -(declare-function tramp-compat-file-name-quoted-p 'tramp-compat) +(declare-function tramp-compat-file-local-name "tramp-compat") +(declare-function tramp-compat-file-name-quoted-p "tramp-compat") ;; For not existing functions, obsolete functions, or functions with a ;; changed argument list, there are compiler warnings. We want to commit 9ae94ebdfa80cf3983c254696b5ab998f7296aec Author: Alexander Gramiak Date: Sat Apr 27 15:00:13 2019 -0600 Refactor update_window_begin and update_window_end hooks Bug#35464. * src/dispnew.c (gui_update_window_begin, gui_update_window_end): New procedures implementing common functionality. * src/nsterm.m: (ns_update_window_begin, ns_update_window_end): * src/xterm.c: (x_update_window_begin, x_update_window_end): Remove in favor of only using the new generic versions. * src/w32term.c: (w32_update_window_begin, w32_update_window_end): Remove duplicated and unused code. diff --git a/src/dispextern.h b/src/dispextern.h index 4d6d0371d3..bb981f83fc 100644 --- a/src/dispextern.h +++ b/src/dispextern.h @@ -3521,6 +3521,10 @@ void clear_glyph_matrix_rows (struct glyph_matrix *, int, int); void clear_glyph_row (struct glyph_row *); void prepare_desired_row (struct window *, struct glyph_row *, bool); void update_single_window (struct window *); +#ifdef HAVE_WINDOW_SYSTEM +extern void gui_update_window_begin (struct window *); +extern void gui_update_window_end (struct window *, bool, bool); +#endif void do_pending_window_change (bool); void change_frame_size (struct frame *, int, int, bool, bool, bool, bool); void init_display (void); diff --git a/src/dispnew.c b/src/dispnew.c index 25a2d1cd38..52a7b6d6ee 100644 --- a/src/dispnew.c +++ b/src/dispnew.c @@ -3390,7 +3390,9 @@ update_window (struct window *w, bool force_p) struct glyph_matrix *desired_matrix = w->desired_matrix; bool paused_p; int preempt_count = clip_to_bounds (1, baud_rate / 2400 + 1, INT_MAX); +#ifdef HAVE_WINDOW_SYSTEM struct redisplay_interface *rif = FRAME_RIF (XFRAME (WINDOW_FRAME (w))); +#endif #ifdef GLYPH_DEBUG /* Check that W's frame doesn't have glyph matrices. */ eassert (FRAME_WINDOW_P (XFRAME (WINDOW_FRAME (w)))); @@ -3411,7 +3413,9 @@ update_window (struct window *w, bool force_p) bool changed_p = 0, mouse_face_overwritten_p = 0; int n_updated = 0; - rif->update_window_begin_hook (w); +#ifdef HAVE_WINDOW_SYSTEM + gui_update_window_begin (w); +#endif yb = window_text_bottom_y (w); row = MATRIX_ROW (desired_matrix, 0); end = MATRIX_MODE_LINE_ROW (desired_matrix); @@ -3533,13 +3537,13 @@ update_window (struct window *w, bool force_p) #ifdef HAVE_WINDOW_SYSTEM update_window_fringes (w, 0); -#endif /* End the update of window W. Don't set the cursor if we paused updating the display because in this case, set_window_cursor_after_update hasn't been called, and W->output_cursor doesn't contain the cursor location. */ - rif->update_window_end_hook (w, !paused_p, mouse_face_overwritten_p); + gui_update_window_end (w, !paused_p, mouse_face_overwritten_p); +#endif } else paused_p = 1; @@ -3555,6 +3559,90 @@ update_window (struct window *w, bool force_p) return paused_p; } +#ifdef HAVE_WINDOW_SYSTEM + +/* Start update of window W. */ + +void +gui_update_window_begin (struct window *w) +{ + struct frame *f = XFRAME (WINDOW_FRAME (w)); + Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f); + + block_input (); + + if (FRAME_RIF (f)->update_window_begin_hook) + FRAME_RIF (f)->update_window_begin_hook (w); + + w->output_cursor = w->cursor; + + if (f == hlinfo->mouse_face_mouse_frame) + { + /* Don't do highlighting for mouse motion during the update. */ + hlinfo->mouse_face_defer = true; + + /* If the frame needs to be redrawn, simply forget about any + prior mouse highlighting. */ + if (FRAME_GARBAGED_P (f)) + hlinfo->mouse_face_window = Qnil; + } + + unblock_input (); +} + +/* End update of window W. + + Draw vertical borders between horizontally adjacent windows, and + display W's cursor if CURSOR_ON_P is non-zero. + + MOUSE_FACE_OVERWRITTEN_P non-zero means that some row containing + glyphs in mouse-face were overwritten. In that case we have to + make sure that the mouse-highlight is properly redrawn. */ +void +gui_update_window_end (struct window *w, bool cursor_on_p, + bool mouse_face_overwritten_p) +{ + struct frame *f = XFRAME (WINDOW_FRAME (w)); + + block_input (); + + /* Pseudo windows don't have cursors, so don't display them here. */ + if (!w->pseudo_window_p) + { + + if (cursor_on_p) + display_and_set_cursor (w, true, + w->output_cursor.hpos, w->output_cursor.vpos, + w->output_cursor.x, w->output_cursor.y); + + if (draw_window_fringes (w, true)) + { + if (WINDOW_RIGHT_DIVIDER_WIDTH (w)) + gui_draw_right_divider (w); + else + gui_draw_vertical_border (w); + } + } + + /* If a row with mouse-face was overwritten, arrange for + frame_up_to_date_hook to redisplay the mouse highlight. */ + if (mouse_face_overwritten_p) + { + Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f); + + hlinfo->mouse_face_beg_row = hlinfo->mouse_face_beg_col = -1; + hlinfo->mouse_face_end_row = hlinfo->mouse_face_end_col = -1; + hlinfo->mouse_face_window = Qnil; + } + + if (FRAME_RIF (f)->update_window_end_hook) + FRAME_RIF (f)->update_window_end_hook (w, + cursor_on_p, + mouse_face_overwritten_p); + unblock_input (); +} + +#endif /* HAVE_WINDOW_SYSTEM */ /* Update the display of area AREA in window W, row number VPOS. AREA can be either LEFT_MARGIN_AREA or RIGHT_MARGIN_AREA. */ diff --git a/src/nsterm.m b/src/nsterm.m index cdf1916e71..ffb7b7692b 100644 --- a/src/nsterm.m +++ b/src/nsterm.m @@ -1106,7 +1106,7 @@ static NSRect constrain_frame_rect(NSRect frameRect, bool isFullscreen) ns_update_begin (struct frame *f) /* -------------------------------------------------------------------------- Prepare for a grouped sequence of drawing calls - external (RIF) call; whole frame, called before update_window_begin + external (RIF) call; whole frame, called before gui_update_window_begin -------------------------------------------------------------------------- */ { #ifdef NS_IMPL_COCOA @@ -1128,81 +1128,11 @@ static NSRect constrain_frame_rect(NSRect frameRect, bool isFullscreen) } -static void -ns_update_window_begin (struct window *w) -/* -------------------------------------------------------------------------- - Prepare for a grouped sequence of drawing calls - external (RIF) call; for one window, called after update_begin - -------------------------------------------------------------------------- */ -{ - struct frame *f = XFRAME (WINDOW_FRAME (w)); - Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f); - - NSTRACE_WHEN (NSTRACE_GROUP_UPDATES, "ns_update_window_begin"); - w->output_cursor = w->cursor; - - block_input (); - - if (f == hlinfo->mouse_face_mouse_frame) - { - /* Don't do highlighting for mouse motion during the update. */ - hlinfo->mouse_face_defer = 1; - - /* If the frame needs to be redrawn, - simply forget about any prior mouse highlighting. */ - if (FRAME_GARBAGED_P (f)) - hlinfo->mouse_face_window = Qnil; - - /* (further code for mouse faces ifdef'd out in other terms elided) */ - } - - unblock_input (); -} - - -static void -ns_update_window_end (struct window *w, bool cursor_on_p, - bool mouse_face_overwritten_p) -/* -------------------------------------------------------------------------- - Finished a grouped sequence of drawing calls - external (RIF) call; for one window called before update_end - -------------------------------------------------------------------------- */ -{ - NSTRACE_WHEN (NSTRACE_GROUP_UPDATES, "ns_update_window_end"); - - /* note: this fn is nearly identical in all terms */ - if (!w->pseudo_window_p) - { - block_input (); - - if (cursor_on_p) - display_and_set_cursor (w, 1, - w->output_cursor.hpos, w->output_cursor.vpos, - w->output_cursor.x, w->output_cursor.y); - - if (draw_window_fringes (w, 1)) - { - if (WINDOW_RIGHT_DIVIDER_WIDTH (w)) - gui_draw_right_divider (w); - else - gui_draw_vertical_border (w); - } - - unblock_input (); - } - - /* If a row with mouse-face was overwritten, arrange for - frame_up_to_date to redisplay the mouse highlight. */ - if (mouse_face_overwritten_p) - reset_mouse_highlight (MOUSE_HL_INFO (XFRAME (w->frame))); -} - - static void ns_update_end (struct frame *f) /* -------------------------------------------------------------------------- Finished a grouped sequence of drawing calls - external (RIF) call; for whole frame, called after update_window_end + external (RIF) call; for whole frame, called after gui_update_window_end -------------------------------------------------------------------------- */ { NSTRACE_WHEN (NSTRACE_GROUP_UPDATES, "ns_update_end"); @@ -5166,8 +5096,8 @@ static Lisp_Object ns_string_to_lispmod (const char *s) gui_clear_end_of_line, ns_scroll_run, ns_after_update_window_line, - ns_update_window_begin, - ns_update_window_end, + NULL, /* update_window_begin */ + NULL, /* update_window_end */ 0, /* flush_display */ gui_clear_window_mouse_face, gui_get_glyph_overhangs, diff --git a/src/w32term.c b/src/w32term.c index 451dd54dd8..0abec3d92a 100644 --- a/src/w32term.c +++ b/src/w32term.c @@ -529,7 +529,7 @@ w32_display_pixel_width (struct w32_display_info *dpyinfo) /* Start an update of frame F. This function is installed as a hook for update_begin, i.e. it is called when update_begin is called. - This function is called prior to calls to w32_update_window_begin + This function is called prior to calls to gui_update_window_begin for each window being updated. */ static void @@ -555,58 +555,12 @@ w32_update_begin (struct frame *f) static void w32_update_window_begin (struct window *w) { - struct frame *f = XFRAME (WINDOW_FRAME (w)); - Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f); - /* Hide the system caret during an update. */ if (w32_use_visible_system_caret && w32_system_caret_hwnd) { SendMessageTimeout (w32_system_caret_hwnd, WM_EMACS_HIDE_CARET, 0, 0, 0, 6000, NULL); } - - w->output_cursor = w->cursor; - - block_input (); - - if (f == hlinfo->mouse_face_mouse_frame) - { - /* Don't do highlighting for mouse motion during the update. */ - hlinfo->mouse_face_defer = true; - - /* If F needs to be redrawn, simply forget about any prior mouse - highlighting. */ - if (FRAME_GARBAGED_P (f)) - hlinfo->mouse_face_window = Qnil; - -#if 0 /* Rows in a current matrix containing glyphs in mouse-face have - their mouse_face_p flag set, which means that they are always - unequal to rows in a desired matrix which never have that - flag set. So, rows containing mouse-face glyphs are never - scrolled, and we don't have to switch the mouse highlight off - here to prevent it from being scrolled. */ - - /* Can we tell that this update does not affect the window - where the mouse highlight is? If so, no need to turn off. - Likewise, don't do anything if the frame is garbaged; - in that case, the frame's current matrix that we would use - is all wrong, and we will redisplay that line anyway. */ - if (!NILP (hlinfo->mouse_face_window) - && w == XWINDOW (hlinfo->mouse_face_window)) - { - int i; - - for (i = 0; i < w->desired_matrix->nrows; ++i) - if (MATRIX_ROW_ENABLED_P (w->desired_matrix, i)) - break; - - if (i < w->desired_matrix->nrows) - clear_mouse_face (hlinfo); - } -#endif /* 0 */ - } - - unblock_input (); } /* Draw a vertical window border from (x,y0) to (x,y1) */ @@ -694,39 +648,8 @@ w32_draw_window_divider (struct window *w, int x0, int x1, int y0, int y1) static void w32_update_window_end (struct window *w, bool cursor_on_p, - bool mouse_face_overwritten_p) + bool mouse_face_overwritten_p) { - if (!w->pseudo_window_p) - { - block_input (); - - if (cursor_on_p) - display_and_set_cursor (w, true, - w->output_cursor.hpos, w->output_cursor.vpos, - w->output_cursor.x, w->output_cursor.y); - - if (draw_window_fringes (w, true)) - { - if (WINDOW_RIGHT_DIVIDER_WIDTH (w)) - gui_draw_right_divider (w); - else - gui_draw_vertical_border (w); - } - - unblock_input (); - } - - /* If a row with mouse-face was overwritten, arrange for - XTframe_up_to_date to redisplay the mouse highlight. */ - if (mouse_face_overwritten_p) - { - Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (XFRAME (w->frame)); - - hlinfo->mouse_face_beg_row = hlinfo->mouse_face_beg_col = -1; - hlinfo->mouse_face_end_row = hlinfo->mouse_face_end_col = -1; - hlinfo->mouse_face_window = Qnil; - } - /* Unhide the caret. This won't actually show the cursor, unless it was visible before the corresponding call to HideCaret in w32_update_window_begin. */ @@ -2859,7 +2782,7 @@ w32_scroll_run (struct window *w, struct run *run) block_input (); - /* Cursor off. Will be switched on again in w32_update_window_end. */ + /* Cursor off. Will be switched on again in gui_update_window_end. */ gui_clear_cursor (w); { diff --git a/src/xdisp.c b/src/xdisp.c index 95ff8513e3..3bdb8ea1b0 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -18030,12 +18030,14 @@ try_window_reusing_current_matrix (struct window *w) if (run.height > 0 && run.current_y != run.desired_y) { +#ifdef HAVE_WINDOW_SYSTEM update_begin (f); - FRAME_RIF (f)->update_window_begin_hook (w); + gui_update_window_begin (w); FRAME_RIF (f)->clear_window_mouse_face (w); FRAME_RIF (f)->scroll_run_hook (w, &run); - FRAME_RIF (f)->update_window_end_hook (w, false, false); + gui_update_window_end (w, false, false); update_end (f); +#endif } /* Shift current matrix down by nrows_scrolled lines. */ @@ -18194,12 +18196,14 @@ try_window_reusing_current_matrix (struct window *w) if (run.height) { +#ifdef HAVE_WINDOW_SYSTEM update_begin (f); - FRAME_RIF (f)->update_window_begin_hook (w); + gui_update_window_begin (w); FRAME_RIF (f)->clear_window_mouse_face (w); FRAME_RIF (f)->scroll_run_hook (w, &run); - FRAME_RIF (f)->update_window_end_hook (w, false, false); + gui_update_window_end (w, false, false); update_end (f); +#endif } /* Adjust Y positions of reused rows. */ @@ -19147,10 +19151,12 @@ try_window_id (struct window *w) if (FRAME_WINDOW_P (f)) { - FRAME_RIF (f)->update_window_begin_hook (w); +#ifdef HAVE_WINDOW_SYSTEM + gui_update_window_begin (w); FRAME_RIF (f)->clear_window_mouse_face (w); FRAME_RIF (f)->scroll_run_hook (w, &run); - FRAME_RIF (f)->update_window_end_hook (w, false, false); + gui_update_window_end (w, false, false); +#endif } else { diff --git a/src/xterm.c b/src/xterm.c index dd19b8bde1..26f74cde91 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -989,7 +989,7 @@ x_set_frame_alpha (struct frame *f) /* Start an update of frame F. This function is installed as a hook for update_begin, i.e. it is called when update_begin is called. - This function is called prior to calls to x_update_window_begin for + This function is called prior to calls to gui_update_window_begin for each window being updated. Currently, there is nothing to do here because all interesting stuff is done on a window basis. */ @@ -1033,33 +1033,6 @@ x_update_begin (struct frame *f) #endif /* USE_CAIRO */ } -/* Start update of window W. */ - -static void -x_update_window_begin (struct window *w) -{ - struct frame *f = XFRAME (WINDOW_FRAME (w)); - Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f); - - w->output_cursor = w->cursor; - - block_input (); - - if (f == hlinfo->mouse_face_mouse_frame) - { - /* Don't do highlighting for mouse motion during the update. */ - hlinfo->mouse_face_defer = true; - - /* If F needs to be redrawn, simply forget about any prior mouse - highlighting. */ - if (FRAME_GARBAGED_P (f)) - hlinfo->mouse_face_window = Qnil; - } - - unblock_input (); -} - - /* Draw a vertical window border from (x,y0) to (x,y1) */ static void @@ -1139,55 +1112,6 @@ x_draw_window_divider (struct window *w, int x0, int x1, int y0, int y1) } } -/* End update of window W. - - Draw vertical borders between horizontally adjacent windows, and - display W's cursor if CURSOR_ON_P is non-zero. - - MOUSE_FACE_OVERWRITTEN_P non-zero means that some row containing - glyphs in mouse-face were overwritten. In that case we have to - make sure that the mouse-highlight is properly redrawn. - - W may be a menu bar pseudo-window in case we don't have X toolkit - support. Such windows don't have a cursor, so don't display it - here. */ - -static void -x_update_window_end (struct window *w, bool cursor_on_p, - bool mouse_face_overwritten_p) -{ - if (!w->pseudo_window_p) - { - block_input (); - - if (cursor_on_p) - display_and_set_cursor (w, true, - w->output_cursor.hpos, w->output_cursor.vpos, - w->output_cursor.x, w->output_cursor.y); - - if (draw_window_fringes (w, true)) - { - if (WINDOW_RIGHT_DIVIDER_WIDTH (w)) - gui_draw_right_divider (w); - else - gui_draw_vertical_border (w); - } - - unblock_input (); - } - - /* If a row with mouse-face was overwritten, arrange for - XTframe_up_to_date to redisplay the mouse highlight. */ - if (mouse_face_overwritten_p) - { - Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (XFRAME (w->frame)); - - hlinfo->mouse_face_beg_row = hlinfo->mouse_face_beg_col = -1; - hlinfo->mouse_face_end_row = hlinfo->mouse_face_end_col = -1; - hlinfo->mouse_face_window = Qnil; - } -} - /* Show the frame back buffer. If frame is double-buffered, atomically publish to the user's screen graphics updates made since the last call to show_back_buffer. */ @@ -4306,7 +4230,7 @@ x_scroll_run (struct window *w, struct run *run) block_input (); - /* Cursor off. Will be switched on again in x_update_window_end. */ + /* Cursor off. Will be switched on again in gui_update_window_end. */ gui_clear_cursor (w); #ifdef USE_CAIRO @@ -13145,8 +13069,8 @@ static struct redisplay_interface x_redisplay_interface = gui_clear_end_of_line, x_scroll_run, x_after_update_window_line, - x_update_window_begin, - x_update_window_end, + NULL, /* update_window_begin */ + NULL, /* update_window_end */ x_flip_and_flush, gui_clear_window_mouse_face, gui_get_glyph_overhangs, commit d17ae7f5afb851a26a957bd7d1765aae6d08fe1d Author: Dmitry Gutov Date: Fri May 3 02:48:44 2019 +0300 xref--find-ignores-arguments: Return "" if IGNORES is nil diff --git a/lisp/progmodes/xref.el b/lisp/progmodes/xref.el index c7f015b94f..bf999aeb0d 100644 --- a/lisp/progmodes/xref.el +++ b/lisp/progmodes/xref.el @@ -1064,7 +1064,8 @@ IGNORES is a list of glob patterns." IGNORES is a list of glob patterns. DIR is an absolute directory, used as the root of the ignore globs." (cl-assert (not (string-match-p "\\`~" dir))) - (when ignores + (if (not ignores) + "" (concat (shell-quote-argument "(") " -path " commit 1cd4a5e5e5db5dc26e279002f3a718e190bcec0c Author: Dmitry Gutov Date: Fri May 3 01:52:05 2019 +0300 Allow project-find-regexp'ing inside an ignored dir * lisp/progmodes/project.el (project-find-regexp): Don't pass project's ignores to project--files-in-directory. The FILES glob should be enough, and we don't want to prohibit searching inside ignored directories this way (it can be counter-intuitive). diff --git a/lisp/progmodes/project.el b/lisp/progmodes/project.el index 11a2ef4009..7c8ca15868 100644 --- a/lisp/progmodes/project.el +++ b/lisp/progmodes/project.el @@ -355,7 +355,7 @@ requires quoting, e.g. `\\[quoted-insert]'." (let ((dir (read-directory-name "Base directory: " nil default-directory t))) (project--files-in-directory dir - (project--dir-ignores pr dir) + nil (grep-read-files regexp)))))) (project--find-regexp-in-files regexp files))) commit f2b395c4c57c0274de38df7a4fe42dbc63a5000c Author: Dmitry Gutov Date: Fri May 3 01:47:15 2019 +0300 (xref--mouse-2): Fix not to jump to the next line * lisp/progmodes/xref.el (xref--mouse-2): Fix not to jump to the next line. diff --git a/lisp/progmodes/xref.el b/lisp/progmodes/xref.el index 18e97bd0f6..c7f015b94f 100644 --- a/lisp/progmodes/xref.el +++ b/lisp/progmodes/xref.el @@ -731,7 +731,8 @@ references displayed in the current *xref* buffer." (interactive "e") (mouse-set-point event) (forward-line 0) - (xref--search-property 'xref-item) + (or (get-text-property (point) 'xref-item) + (xref--search-property 'xref-item)) (xref-show-location-at-point)) (defun xref--insert-xrefs (xref-alist) commit 5ff4bfaeec8f9c18c7dd0c8479b399b83c1e6fc2 Author: Dmitry Gutov Date: Fri May 3 01:29:59 2019 +0300 Fix an "empty identifier" problem * lisp/progmodes/xref.el (xref--read-identifier): Abort on empty input if there is no default (https://lists.gnu.org/archive/html/help-gnu-emacs/2019-05/msg00012.html). diff --git a/lisp/progmodes/xref.el b/lisp/progmodes/xref.el index e5e59721eb..18e97bd0f6 100644 --- a/lisp/progmodes/xref.el +++ b/lisp/progmodes/xref.el @@ -828,20 +828,25 @@ Return an alist of the form ((FILENAME . (XREF ...)) ...)." (defun xref--read-identifier (prompt) "Return the identifier at point or read it from the minibuffer." (let* ((backend (xref-find-backend)) - (id (xref-backend-identifier-at-point backend))) + (def (xref-backend-identifier-at-point backend))) (cond ((or current-prefix-arg - (not id) + (not def) (xref--prompt-p this-command)) - (completing-read (if id - (format "%s (default %s): " - (substring prompt 0 (string-match - "[ :]+\\'" prompt)) - id) - prompt) - (xref-backend-identifier-completion-table backend) - nil nil nil - 'xref--read-identifier-history id)) - (t id)))) + (let ((id + (completing-read + (if def + (format "%s (default %s): " + (substring prompt 0 (string-match + "[ :]+\\'" prompt)) + def) + prompt) + (xref-backend-identifier-completion-table backend) + nil nil nil + 'xref--read-identifier-history def))) + (if (equal id "") + (or def (user-error "There is no defailt identifier")) + id))) + (t def)))) ;;; Commands commit d9f62fceaf2915c67f6917c668af6ff4aacc26a7 Author: Alan Mackenzie Date: Thu May 2 20:53:47 2019 +0000 Fix fontification of first item in CC Mode macro without parentheses * lisp/progmodes/cc-engine.el (c-find-decl-prefix-search): Handle the new matching possibility (of a #define construct) in the new c-decl-prefix-or-start-re. (c-find-decl-spots): Allow the initial search for an in-macro starting point settle on the # of #define, to facilitate the regexp matching in c-find-decl-prefix-search. * lisp/progmodes/cc-langs.el (c-anchored-hash-define-no-parens): New lang const. (c-literal-start-regexp): Correct what was always supposed to be a "generic string" regexp element. (c-decl-prefix-or-start-re): Enhance also to match "#define ". (c-dposr-cpp-macro-depth): New lang variable and lang constant. diff --git a/lisp/progmodes/cc-engine.el b/lisp/progmodes/cc-engine.el index f9e570e9f3..7e6a46ea6e 100644 --- a/lisp/progmodes/cc-engine.el +++ b/lisp/progmodes/cc-engine.el @@ -5692,7 +5692,10 @@ comment at the start of cc-engine.el for more info." (setq cfd-re-match cfd-limit) nil) ((c-got-face-at - (if (setq cfd-re-match (match-end 1)) + (if (setq cfd-re-match + (or (match-end 1) + (and c-dposr-cpp-macro-depth + (match-end (1+ c-dposr-cpp-macro-depth))))) ;; Matched the end of a token preceding a decl spot. (progn (goto-char cfd-re-match) @@ -5703,15 +5706,19 @@ comment at the start of cc-engine.el for more info." c-literal-faces) ;; Pseudo match inside a comment or string literal. Skip out ;; of comments and string literals. - (while (progn - (unless - (and (match-end 1) - (c-got-face-at (1- (point)) c-literal-faces) - (not (c-got-face-at (point) c-literal-faces))) - (goto-char (c-next-single-property-change - (point) 'face nil cfd-limit))) - (and (< (point) cfd-limit) - (c-got-face-at (point) c-literal-faces)))) + (while + (progn + (unless + (and + (or (match-end 1) + (and c-dposr-cpp-macro-depth + (match-end (1+ c-dposr-cpp-macro-depth)))) + (c-got-face-at (1- (point)) c-literal-faces) + (not (c-got-face-at (point) c-literal-faces))) + (goto-char (c-next-single-property-change + (point) 'face nil cfd-limit))) + (and (< (point) cfd-limit) + (c-got-face-at (point) c-literal-faces)))) t) ; Continue the loop over pseudo matches. ((and c-opt-identifier-concat-key (match-string 1) @@ -5863,7 +5870,7 @@ comment at the start of cc-engine.el for more info." ;; before the point, and do the first `c-decl-prefix-or-start-re' ;; search unless we're at bob. - (let (start-in-literal start-in-macro syntactic-pos) + (let (start-in-literal start-in-macro syntactic-pos hash-define-pos) ;; Must back up a bit since we look for the end of the previous ;; statement or declaration, which is earlier than the first ;; returned match. @@ -6018,7 +6025,21 @@ comment at the start of cc-engine.el for more info." ;; The only syntactic ws in macros are comments. (c-backward-comments) (or (bobp) (backward-char)) - (c-beginning-of-current-token)) + (c-beginning-of-current-token) + ;; If we're in a macro without argument parentheses, we could have + ;; now ended up at the macro's identifier. We need to be at #define + ;; for `c-find-decl-prefix-search' to find the first token of the + ;; macro's expansion. + (when (and (c-on-identifier) + (setq hash-define-pos + (save-excursion + (and + (zerop (c-backward-token-2 2)) ; over define, # + (save-excursion + (beginning-of-line) + (looking-at c-opt-cpp-macro-define-id)) + (point))))) + (goto-char hash-define-pos))) (start-in-literal ;; If we're in a comment it can only be the closest diff --git a/lisp/progmodes/cc-langs.el b/lisp/progmodes/cc-langs.el index 00c581a06a..8b7e4ef7c0 100644 --- a/lisp/progmodes/cc-langs.el +++ b/lisp/progmodes/cc-langs.el @@ -979,6 +979,14 @@ definition, or nil if the language doesn't have any." (c-lang-defvar c-opt-cpp-macro-define-id (c-lang-const c-opt-cpp-macro-define-id)) +(c-lang-defconst c-anchored-hash-define-no-parens + ;; Regexp matching everything up to the end of a cpp define which has no + ;; argument parentheses. Or nil in languages which don't have them. + t (if (c-lang-const c-opt-cpp-macro-define) + (concat (c-lang-const c-anchored-cpp-prefix) + (c-lang-const c-opt-cpp-macro-define) + "[ \t]+\\(\\sw\\|_\\)+\\([^(a-zA-Z0-9_]\\|$\\)"))) + (c-lang-defconst c-cpp-expr-directives "List of cpp directives (without the prefix) that are followed by an expression." @@ -1614,7 +1622,7 @@ starter." t (concat (c-lang-const c-comment-start-regexp) "\\|" (if (memq 'gen-string-delim c-emacs-features) - "\"|" + "\"\\|\\s|" "\""))) (c-lang-defvar c-literal-start-regexp (c-lang-const c-literal-start-regexp)) @@ -3183,24 +3191,40 @@ constructs." ;; token that might precede such a construct, e.g. ';', '}' or '{'. ;; It's built from `c-decl-prefix-re'. ;; - ;; If the first submatch did not match, the match of the whole - ;; regexp is taken to be at the first token in the declaration. - ;; `c-decl-start-re' is not checked in this case. + ;; If the first submatch did not match, we have either a #define construct + ;; without parentheses or the match of the whole regexp is taken to be at + ;; the first token in the declaration. `c-decl-start-re' is not checked in + ;; these cases. ;; ;; Design note: The reason the same regexp is used to match both ;; tokens that precede declarations and start them is to avoid an ;; extra regexp search from the previous declaration spot in ;; `c-find-decl-spots'. Users of `c-find-decl-spots' also count on - ;; that it finds all declaration/cast/label starts in approximately + ;; it finding all declaration/cast/label starts in approximately ;; linear order, so we can't do the searches in two separate passes. - t (if (c-lang-const c-decl-start-kwds) - (concat (c-lang-const c-decl-prefix-re) - "\\|" - (c-make-keywords-re t (c-lang-const c-decl-start-kwds))) - (c-lang-const c-decl-prefix-re))) + t (cond + ((and (c-lang-const c-decl-start-kwds) + (c-lang-const c-anchored-hash-define-no-parens)) + (concat (c-lang-const c-decl-prefix-re) + "\\|" (c-lang-const c-anchored-hash-define-no-parens) + "\\|" (c-make-keywords-re t (c-lang-const c-decl-start-kwds)))) + ((c-lang-const c-decl-start-kwds) + (concat (c-lang-const c-decl-prefix-re) + "\\|" (c-make-keywords-re t (c-lang-const c-decl-start-kwds)))) + ((c-lang-const c-anchored-hash-define-no-parens) + (concat (c-lang-const c-decl-prefix-re) + "\\|" (c-lang-const c-anchored-hash-define-no-parens))) + (t (c-lang-const c-decl-prefix-re)))) (c-lang-defvar c-decl-prefix-or-start-re (c-lang-const c-decl-prefix-or-start-re)) +(c-lang-defconst c-dposr-cpp-macro-depth + ;; The match number of `c-anchored-hash-define-no-parens''s first match + ;; within `c-decl-prefix-or-start-re', or nil if there is no such component. + t (if (c-lang-const c-anchored-hash-define-no-parens) + (1+ (regexp-opt-depth (c-lang-const c-decl-prefix-re))))) +(c-lang-defvar c-dposr-cpp-macro-depth (c-lang-const c-dposr-cpp-macro-depth)) + (c-lang-defconst c-cast-parens ;; List containing the paren characters that can open a cast, or nil in ;; languages without casts. commit 17a722982cca4e8e643c7a9102903e820e784cc6 Author: Stefan Monnier Date: Thu May 2 11:00:20 2019 -0400 * lisp/mail/footnote.el: Add TEXT and POINTERS together Rather than adding POINTERS and TEXT separately to footnote--markers-alist, add them together, so we don't need footnote--first-text-marker because the TEXT part is never nil. (footnote--insert-numbered-footnote): Return marker. (footnote--insert-text-marker, footnote--insert-pointer-marker): Delete functions. (footnote--insert-markers): New function to replace them. (footnote--insert-footnote): Adjust accordingly. Simplify pointless `unless`. (footnote--first-text-marker): Remove. Replace all calls by (cadr (car footnote--markers-alist)) or just footnote--markers-alist. diff --git a/lisp/mail/footnote.el b/lisp/mail/footnote.el index d985444a8e..327eda11dc 100644 --- a/lisp/mail/footnote.el +++ b/lisp/mail/footnote.el @@ -457,7 +457,7 @@ footnote styles." (let ((fn-regexp (footnote--current-regexp index-regexp))) (save-excursion (pcase-dolist (`(,fn ,text . ,pointers) footnote--markers-alist) - ;; Take care of the pointers first + ;; Take care of the pointers first. (dolist (locn pointers) (goto-char locn) ;; Try to handle the case where `footnote-start-tag' and @@ -505,15 +505,18 @@ footnote styles." ;; Internal functions (defun footnote--insert-numbered-footnote (arg &optional mousable) - "Insert numbered footnote at point." + "Insert numbered footnote at point. +Return a marker pointing to the beginning of the [...]." (let ((string (concat footnote-start-tag (footnote--index-to-string arg) - footnote-end-tag))) + footnote-end-tag)) + (pos (point))) (insert (if mousable (propertize string 'footnote-number arg footnote-mouse-highlight t) - (propertize string 'footnote-number arg))))) + (propertize string 'footnote-number arg))) + (copy-marker pos t))) (defun footnote--renumber (to alist-elem) "Renumber a single footnote." @@ -550,33 +553,13 @@ footnote styles." (or (re-search-backward footnote-signature-separator nil t) (point))) -(defun footnote--insert-text-marker (arg locn) - "Insert a marker pointing to footnote ARG, at buffer location LOCN." - (let ((entry (assq arg footnote--markers-alist))) - (unless (cadr entry) - (let ((marker (copy-marker locn t))) - (if entry - (setf (cadr entry) marker) - (push `(,arg ,marker) footnote--markers-alist) - (setq footnote--markers-alist - (footnote--sort footnote--markers-alist))))))) - -(defun footnote--insert-pointer-marker (arg locn) - "Insert a marker pointing to footnote ARG, at buffer location LOCN." - (let ((entry (assq arg footnote--markers-alist)) - (marker (copy-marker locn t))) - (if entry - (push marker (cddr entry)) - (push `(,arg nil ,marker) footnote--markers-alist) - (setq footnote--markers-alist - (footnote--sort footnote--markers-alist))))) - -(defun footnote--first-text-marker () - (let ((tmp footnote--markers-alist)) - (while (and tmp (null (cadr (car footnote--markers-alist)))) - ;; Skip entries which don't (yet) have a TEXT marker. - (set tmp (cdr tmp))) - (cadr (car tmp)))) +(defun footnote--insert-markers (arg text ptr) + "Insert the markers of new footnote ARG." + (cl-assert (and (numberp arg) (markerp text) (markerp ptr))) + (cl-assert (not (assq arg footnote--markers-alist))) + (push `(,arg ,text ,ptr) footnote--markers-alist) + (setq footnote--markers-alist + (footnote--sort footnote--markers-alist))) (defun footnote--goto-first () "Go to beginning of footnote area and return non-nil if successful. @@ -586,42 +569,37 @@ Presumes we're within the footnote area already." (re-search-backward (concat "^" footnote-section-tag-regexp) nil t)) (footnote--markers-alist - (let ((pos (footnote--first-text-marker))) - (when pos - (goto-char pos)))))) + (goto-char (cadr (car footnote--markers-alist)))))) (defun footnote--insert-footnote (arg) "Insert a footnote numbered ARG, at (point)." (push-mark) - (let ((old-point (point))) - (footnote--insert-numbered-footnote arg t) - (footnote--insert-pointer-marker arg old-point)) - (footnote--goto-char-point-max) - (if (footnote--goto-first) - (save-restriction - (when footnote-narrow-to-footnotes-when-editing - (footnote--narrow-to-footnotes)) - (footnote-goto-footnote (1- arg)) ; evil, FIXME (less evil now) - ;; (message "Inserting footnote %d" arg) - (unless - (or (eq arg 1) - (when (re-search-forward - (if footnote-spaced-footnotes - "\n\n" - (concat "\n" (footnote--current-regexp))) - nil t) - (unless (beginning-of-line) t)) - (footnote--goto-char-point-max) - (footnote--goto-first)))) - (unless (looking-at "^$") - (insert "\n")) - (when (eobp) - (insert "\n")) - (unless (string-equal footnote-section-tag "") - (insert footnote-section-tag "\n"))) - (let ((old-point (point))) - (footnote--insert-numbered-footnote arg nil) - (footnote--insert-text-marker arg old-point))) + (let ((ptr (footnote--insert-numbered-footnote arg t))) + (footnote--goto-char-point-max) + (if (footnote--goto-first) + (save-restriction + (when footnote-narrow-to-footnotes-when-editing + (footnote--narrow-to-footnotes)) + (footnote-goto-footnote (1- arg)) ; evil, FIXME (less evil now) + ;; (message "Inserting footnote %d" arg) + (or (eq arg 1) + (when (re-search-forward + (if footnote-spaced-footnotes + "\n\n" + (concat "\n" (footnote--current-regexp))) + nil t) + (beginning-of-line) + t) + (footnote--goto-char-point-max) + (footnote--goto-first))) + (unless (looking-at "^$") + (insert "\n")) + (when (eobp) + (insert "\n")) + (unless (string-equal footnote-section-tag "") + (insert footnote-section-tag "\n"))) + (let ((text (footnote--insert-numbered-footnote arg nil))) + (footnote--insert-markers arg text ptr)))) (defun footnote--sort (list) (sort list #'car-less-than-car)) @@ -671,14 +649,14 @@ With optional arg BEFORE-TAG, return position of the `footnote-section-tag' instead, if applicable." (cond ;; FIXME: Shouldn't we use `footnote--get-area-point-max' instead? - ((not (footnote--first-text-marker)) (point-max)) - ((not before-tag) (footnote--first-text-marker)) - ((string-equal footnote-section-tag "") (footnote--first-text-marker)) + ((not footnote--markers-alist) (point-max)) + ((not before-tag) (cadr (car footnote--markers-alist))) + ((string-equal footnote-section-tag "") (cadr (car footnote--markers-alist))) (t (save-excursion - (goto-char (footnote--first-text-marker)) + (goto-char (cadr (car footnote--markers-alist))) (if (re-search-backward (concat "^" footnote-section-tag-regexp) nil t) - (match-beginning 0) + (point) (message "Footnote section tag not found!") ;; This `else' should never happen, and indicates an error, ;; ie. footnotes already exist and a footnote-section-tag is defined, @@ -696,7 +674,7 @@ instead, if applicable." ;; function, and repeat. ;; ;; TODO: integrate sanity checks at reasonable operational points. - (footnote--first-text-marker)))))) + (point)))))) (defun footnote--get-area-point-max () "Return the end of footnote area. @@ -832,8 +810,8 @@ specified, jump to the text of that footnote." ((not (string-equal footnote-section-tag "")) (re-search-backward (concat "^" footnote-section-tag-regexp)) (forward-line 1)) - ((footnote--first-text-marker) - (goto-char (footnote--first-text-marker))))) + (footnote--markers-alist + (goto-char (cadr (car footnote--markers-alist)))))) (t (error "I don't see a footnote here"))))) commit 39acaff574140b67ef5311c5764a6b3b29491991 Author: Alan Mackenzie Date: Thu May 2 14:30:29 2019 +0000 CC Mode: Fix multiline block comments in macros. In particulr, handle multiline block comments whose newlines are not escaped. There is an example of this in #define EXTRA_CONTEXT_FIELDS in editfns.c. * lisp/progmodes/cc-engine.el (c-beginning-of-macro, c-end-of-macro): Enclose the loops scanning escaped newlines with outer loops which check heuristically for, respectively, a block comment ender and a block comment starter on the lines we end up on. (A rigorous syntactic check would be too slow, here.) * lisp/progmodes/cc-langs.el (c-last-c-comment-end-on-line-re) (c-last-open-c-comment-start-on-line-re): New language constants/variables. diff --git a/lisp/progmodes/cc-engine.el b/lisp/progmodes/cc-engine.el index a0459b9f2a..f9e570e9f3 100644 --- a/lisp/progmodes/cc-engine.el +++ b/lisp/progmodes/cc-engine.el @@ -287,7 +287,8 @@ otherwise return nil and leave point unchanged. Note that this function might do hidden buffer changes. See the comment at the start of cc-engine.el for more info." - (let ((here (point))) + (let ((here (point)) + (pause (c-point 'eol))) (when c-opt-cpp-prefix (if (and (car c-macro-cache) (>= (point) (car c-macro-cache)) @@ -307,8 +308,23 @@ comment at the start of cc-engine.el for more info." (save-restriction (if lim (narrow-to-region lim (point-max))) (beginning-of-line) - (while (eq (char-before (1- (point))) ?\\) - (forward-line -1)) + (when (or (null lim) + (>= here lim)) + (while + (progn + (while (eq (char-before (1- (point))) ?\\) + (forward-line -1)) + (when (and c-last-c-comment-end-on-line-re + (re-search-forward + c-last-c-comment-end-on-line-re pause t)) + (goto-char (match-end 1)) + (if (c-backward-single-comment) + (progn + (beginning-of-line) + (setq pause (point))) + (goto-char pause) + nil))))) + (back-to-indentation) (if (and (<= (point) here) (save-match-data (looking-at c-opt-cpp-start)) @@ -345,12 +361,23 @@ comment at the start of cc-engine.el for more info." c-macro-cache-start-pos nil c-macro-cache-syntactic nil c-macro-cache-no-comment nil)) - (while (progn - (end-of-line) - (when (and (eq (char-before) ?\\) - (not (eobp))) - (forward-char) - t))) + (while + (progn + (while (progn + (end-of-line) + (when (and (eq (char-before) ?\\) + (not (eobp))) + (forward-char) + t))) + (if (and c-last-open-c-comment-start-on-line-re + (re-search-backward + c-last-open-c-comment-start-on-line-re + (c-point 'bol) t)) + (progn + (goto-char (match-beginning 1)) + (c-forward-single-comment)) + nil))) + (when (and (car c-macro-cache) (bolp) (not (eq (char-before (1- (point))) ?\\))) @@ -2007,6 +2034,10 @@ comment at the start of cc-engine.el for more info." ;; Take elaborate precautions to detect an open block comment at ;; the end of a macro. If we find one, we set `safe-start' to nil ;; and break off any further scanning of comments. + ;; + ;; (2019-05-02): `c-end-of-macro' now moves completely over block + ;; comments, even multiline ones lacking \s at their EOLs. So a + ;; lot of the following is probably redundant now. (let ((com-begin (point)) com-end in-macro) (when (and (c-forward-single-comment) (setq com-end (point)) diff --git a/lisp/progmodes/cc-langs.el b/lisp/progmodes/cc-langs.el index 50f8b8473b..00c581a06a 100644 --- a/lisp/progmodes/cc-langs.el +++ b/lisp/progmodes/cc-langs.el @@ -1589,6 +1589,26 @@ properly." (c-lang-defvar c-line-comment-start-regexp (c-lang-const c-line-comment-start-regexp)) +(c-lang-defconst c-last-c-comment-end-on-line-re + "Regexp which matches the last block comment ender on the +current line, if any, or nil in those languages without block +comments. When a match is found, submatch 1 contains the comment +ender." + t "\\(\\*/\\)\\([^*]\\|\\*[^/]\\)*$" + awk nil) +(c-lang-defvar c-last-c-comment-end-on-line-re + (c-lang-const c-last-c-comment-end-on-line-re)) + +(c-lang-defconst c-last-open-c-comment-start-on-line-re + "Regexp which matches the last block comment start on the +current ine, if any, or nil in those languages without block +comments. When a match is found, submatch 1 contains the comment +starter." + t "\\(/\\*\\)\\([^*]\\|\\*[^/]\\)*$" + awk nil) +(c-lang-defvar c-last-open-c-comment-start-on-line-re + (c-lang-const c-last-open-c-comment-start-on-line-re)) + (c-lang-defconst c-literal-start-regexp ;; Regexp to match the start of comments and string literals. t (concat (c-lang-const c-comment-start-regexp) commit 3fa9c9f774277530f4dac6c4f5de157cb4cdc536 Author: Stefan Monnier Date: Thu May 2 10:27:42 2019 -0400 * lisp/mail/footnote.el: Tweak markers convention Instead of using markers that are sometimes before and sometimes after the [...] and using `insert-before-markers` to make sure those that are are before stay before, always place them before, and make them "move after"so they stay with their [...] without the need for insert-before-markers. (footnote--current-regexp): Add arg to match previous style. Include the start/end "tags" in the regexp. Adjust all callers. (footnote--markers-alist): Change position of POINTERS. (footnote--refresh-footnotes, footnote--renumber) (footnote--make-hole, footnote-delete-footnote) (footnote-back-to-message): Adjust accordingly, mostly by using `looking-at` instead of `looking-back`. (footnote--make-hole): Always return footnote nb to use. (footnote-add-footnote): Simplify call accordingly. * test/lisp/mail/footnote-tests.el: New file. diff --git a/lisp/mail/footnote.el b/lisp/mail/footnote.el index 9a918376e6..d985444a8e 100644 --- a/lisp/mail/footnote.el +++ b/lisp/mail/footnote.el @@ -165,8 +165,7 @@ left with the first character of footnote text." Where FN is the footnote number, TEXT is a marker pointing to the footnote's text, and POINTERS is a list of markers pointing to the places from which the footnote is referenced. -TEXT points right *before* the [...] and POINTERS point right -*after* the [...].") +Both TEXT and POINTERS points right *before* the [...]") (defvar footnote-mouse-highlight 'highlight ;; FIXME: This `highlight' property is not currently used. @@ -436,30 +435,26 @@ Conversion is done based upon the current selected style." (nth 0 footnote-style-alist)))) (funcall (nth 1 alist) index))) -(defun footnote--current-regexp () +(defun footnote--current-regexp (&optional index-regexp) "Return the regexp of the index of the current style." - (let ((regexp (nth 2 (or (assq footnote-style footnote-style-alist) - (nth 0 footnote-style-alist))))) + (let ((regexp (or index-regexp + (nth 2 (or (assq footnote-style footnote-style-alist) + (nth 0 footnote-style-alist)))))) (concat + (regexp-quote footnote-start-tag) "\\(" ;; Hack to avoid repetition of repetition. ;; FIXME: I'm not sure the added * makes sense at all; there is ;; always a single number within the footnote-{start,end}-tag pairs. - ;; Worse, the code goes on and adds yet another + later on, in - ;; footnote-refresh-footnotes, just in case. That makes even less sense. - ;; Likely, both the * and the extra + should go away. (if (string-match "[^\\]\\\\\\{2\\}*[*+?]\\'" regexp) (substring regexp 0 -1) regexp) - "*"))) + "*\\)" (regexp-quote footnote-end-tag)))) (defun footnote--refresh-footnotes (&optional index-regexp) "Redraw all footnotes. You must call this or arrange to have this called after changing footnote styles." - (let ((fn-regexp (concat - (regexp-quote footnote-start-tag) - "\\(" (or index-regexp (footnote--current-regexp)) "+\\)" - (regexp-quote footnote-end-tag)))) + (let ((fn-regexp (footnote--current-regexp index-regexp))) (save-excursion (pcase-dolist (`(,fn ,text . ,pointers) footnote--markers-alist) ;; Take care of the pointers first @@ -467,8 +462,7 @@ footnote styles." (goto-char locn) ;; Try to handle the case where `footnote-start-tag' and ;; `footnote-end-tag' are the same string. - (when (looking-back fn-regexp - (line-beginning-position)) + (when (looking-at fn-regexp) (replace-match (propertize (concat @@ -515,7 +509,7 @@ footnote styles." (let ((string (concat footnote-start-tag (footnote--index-to-string arg) footnote-end-tag))) - (insert-before-markers + (insert (if mousable (propertize string 'footnote-number arg footnote-mouse-highlight t) @@ -524,13 +518,11 @@ footnote styles." (defun footnote--renumber (to alist-elem) "Renumber a single footnote." (unless (equal to (car alist-elem)) ;Nothing to do. - (let* ((fn-regexp (concat (regexp-quote footnote-start-tag) - (footnote--current-regexp) - (regexp-quote footnote-end-tag)))) + (let* ((fn-regexp (footnote--current-regexp))) (setcar alist-elem to) (dolist (posn (cddr alist-elem)) (goto-char posn) - (when (looking-back fn-regexp (line-beginning-position)) + (when (looking-at fn-regexp) (replace-match (propertize (concat footnote-start-tag @@ -562,7 +554,7 @@ footnote styles." "Insert a marker pointing to footnote ARG, at buffer location LOCN." (let ((entry (assq arg footnote--markers-alist))) (unless (cadr entry) - (let ((marker (copy-marker locn))) + (let ((marker (copy-marker locn t))) (if entry (setf (cadr entry) marker) (push `(,arg ,marker) footnote--markers-alist) @@ -572,7 +564,7 @@ footnote styles." (defun footnote--insert-pointer-marker (arg locn) "Insert a marker pointing to footnote ARG, at buffer location LOCN." (let ((entry (assq arg footnote--markers-alist)) - (marker (copy-marker locn))) + (marker (copy-marker locn t))) (if entry (push marker (cddr entry)) (push `(,arg nil ,marker) footnote--markers-alist) @@ -601,8 +593,9 @@ Presumes we're within the footnote area already." (defun footnote--insert-footnote (arg) "Insert a footnote numbered ARG, at (point)." (push-mark) - (footnote--insert-pointer-marker arg (point)) - (footnote--insert-numbered-footnote arg t) + (let ((old-point (point))) + (footnote--insert-numbered-footnote arg t) + (footnote--insert-pointer-marker arg old-point)) (footnote--goto-char-point-max) (if (footnote--goto-first) (save-restriction @@ -615,10 +608,7 @@ Presumes we're within the footnote area already." (when (re-search-forward (if footnote-spaced-footnotes "\n\n" - (concat "\n" - (regexp-quote footnote-start-tag) - (footnote--current-regexp) - (regexp-quote footnote-end-tag))) + (concat "\n" (footnote--current-regexp))) nil t) (unless (beginning-of-line) t)) (footnote--goto-char-point-max) @@ -730,10 +720,12 @@ footnote area, returns `point-max'." ;;; User functions (defun footnote--make-hole () + "Make room in the alist for a new footnote at point. +Return the footnote number to use." (save-excursion (let (rc) (dolist (alist-elem footnote--markers-alist) - (when (< (point) (- (cl-caddr alist-elem) 3)) + (when (<= (point) (cl-caddr alist-elem)) (unless rc (setq rc (car alist-elem))) (save-excursion @@ -743,7 +735,8 @@ footnote area, returns `point-max'." (1+ (car alist-elem)))) (footnote--renumber (1+ (car alist-elem)) alist-elem)))) - rc))) + (or rc + (1+ (or (caar (last footnote--markers-alist)) 0)))))) (defun footnote-add-footnote () "Add a numbered footnote. @@ -753,27 +746,17 @@ If the variable `footnote-narrow-to-footnotes-when-editing' is set, the buffer is narrowed to the footnote body. The restriction is removed by using `footnote-back-to-message'." (interactive "*") - (let ((num - (if footnote--markers-alist - (let ((last (car (last footnote--markers-alist)))) - (if (< (point) (cl-caddr last)) - (footnote--make-hole) - (1+ (car last)))) - 1))) + (let ((num (footnote--make-hole))) (message "Adding footnote %d" num) (footnote--insert-footnote num) - (insert-before-markers (make-string footnote-body-tag-spacing ? )) - (let ((opoint (point))) - (save-excursion - (insert-before-markers - (if footnote-spaced-footnotes - "\n\n" - "\n")) - (when footnote-narrow-to-footnotes-when-editing - (footnote--narrow-to-footnotes))) - ;; Emacs/XEmacs bug? save-excursion doesn't restore point when using - ;; insert-before-markers. - (goto-char opoint)))) + (insert (make-string footnote-body-tag-spacing ? )) + (save-excursion + (insert + (if footnote-spaced-footnotes + "\n\n" + "\n")) + (when footnote-narrow-to-footnotes-when-editing + (footnote--narrow-to-footnotes))))) (defun footnote-delete-footnote (&optional arg) "Delete a numbered footnote. @@ -787,14 +770,11 @@ delete the footnote with that number." (y-or-n-p (format "Really delete footnote %d?" arg)))) (let ((alist-elem (or (assq arg footnote--markers-alist) (error "Can't delete footnote %d" arg))) - (fn-regexp (concat (regexp-quote footnote-start-tag) - (footnote--current-regexp) - (regexp-quote footnote-end-tag)))) + (fn-regexp (footnote--current-regexp))) (dolist (locn (cddr alist-elem)) (save-excursion (goto-char locn) - (when (looking-back fn-regexp - (line-beginning-position)) + (when (looking-at fn-regexp) (delete-region (match-beginning 0) (match-end 0))))) (save-excursion (goto-char (cadr alist-elem)) @@ -867,7 +847,9 @@ being set it is automatically widened." (when note (when footnote-narrow-to-footnotes-when-editing (widen)) - (goto-char (cl-caddr (assq note footnote--markers-alist)))))) + (goto-char (cl-caddr (assq note footnote--markers-alist))) + (when (looking-at (footnote--current-regexp)) + (goto-char (match-end 0)))))) (defvar footnote-mode-map (let ((map (make-sparse-keymap))) diff --git a/test/lisp/mail/footnote-tests.el b/test/lisp/mail/footnote-tests.el new file mode 100644 index 0000000000..464443f403 --- /dev/null +++ b/test/lisp/mail/footnote-tests.el @@ -0,0 +1,47 @@ +;;; footnote-tests.el --- Tests for footnote-mode -*- lexical-binding: t; -*- + +;; Copyright (C) 2019 Free Software Foundation, Inc. + +;; Author: Stefan Monnier +;; Keywords: + +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see . + +;;; Commentary: + +;; + +;;; Code: + +(ert-deftest footnote-tests-same-place () + (with-temp-buffer + (footnote-mode 1) + (insert "hello world") + (beginning-of-line) (forward-word) + (footnote-add-footnote) + (insert "footnote") + (footnote-back-to-message) + (should (equal (buffer-substring (point-min) (point)) + "hello[1]")) + (beginning-of-line) (forward-word) + (footnote-add-footnote) + (insert "other footnote") + (footnote-back-to-message) + (should (equal (buffer-substring (point-min) (point)) + "hello[1]")) + (should (equal (buffer-substring (point-min) (line-end-position)) + "hello[1][2] world")))) + +(provide 'footnote-tests) +;;; footnote-tests.el ends here commit e10e314e2b7583d892e86cee92ec57d3a1030ce4 Author: Sam Steingold Date: Thu May 2 10:17:56 2019 -0400 use view-mode on score file for ease of scrolling and quitting diff --git a/lisp/play/gamegrid.el b/lisp/play/gamegrid.el index 4a9dac7f74..54eeafd2b5 100644 --- a/lisp/play/gamegrid.el +++ b/lisp/play/gamegrid.el @@ -663,6 +663,7 @@ FILE is created there." (revert-buffer nil t nil) (display-buffer buf)) (find-file-read-only target)) + (view-mode) (goto-char (point-min)) (search-forward (concat (int-to-string score) " " (user-login-name) " " @@ -691,7 +692,8 @@ FILE is created there." (forward-line gamegrid-score-file-length) (delete-region (point) (point-max)) (setq buffer-read-only t) - (save-buffer))) + (save-buffer) + (view-mode))) ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; commit c555d10d0feee51dfe45305d3aae60490f425447 Author: Sam Steingold Date: Thu May 2 10:17:04 2019 -0400 tetris-null-map: bind "q" to `quit-window` diff --git a/lisp/play/tetris.el b/lisp/play/tetris.el index 1e0681d7ff..a797a26d59 100644 --- a/lisp/play/tetris.el +++ b/lisp/play/tetris.el @@ -277,6 +277,7 @@ each one of its four blocks.") (defvar tetris-null-map (let ((map (make-sparse-keymap 'tetris-null-map))) (define-key map "n" 'tetris-start-game) + (define-key map "q" 'quit-window) map)) ;; ;;;;;;;;;;;;;;;; game functions ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; commit e13b8c0e405f1b5b78a1eeb3c33422b2fc93f002 Author: Mattias EngdegÄrd Date: Mon Apr 29 16:42:04 2019 +0200 Small code clean-up of file-notify-add-watch * lisp/filenotify.el (file-notify-add-watch): Clearly separate backend-specific code from the rest, and simplify. (file-notify--add-watch-inotify, file-notify--add-watch-kqueue) (file-notify--add-watch-w32notify, file-notify--add-watch-gfilenotify): New functions. diff --git a/lisp/filenotify.el b/lisp/filenotify.el index 62dd1cd911..4d22061138 100644 --- a/lisp/filenotify.el +++ b/lisp/filenotify.el @@ -262,9 +262,49 @@ EVENT is the cadr of the event in `file-notify-handle-event' file (file-notify--event-watched-file event)))) (file-notify-rm-watch desc))))))) -;; `kqueue', `gfilenotify' and `w32notify' return a unique descriptor -;; for every `file-notify-add-watch', while `inotify' returns a unique -;; descriptor per inode only. +(declare-function inotify-add-watch "inotify.c" (file flags callback)) +(declare-function kqueue-add-watch "kqueue.c" (file flags callback)) +(declare-function w32notify-add-watch "w32notify.c" (file flags callback)) +(declare-function gfile-add-watch "gfilenotify.c" (file flags callback)) + +(defun file-notify--add-watch-inotify (_file dir flags) + "Add a watch for FILE in DIR with FLAGS, using inotify." + (inotify-add-watch dir + (append + (and (memq 'change flags) + '(create delete delete-self modify move-self move)) + (and (memq 'attribute-change flags) + '(attrib))) + #'file-notify-callback)) + +(defun file-notify--add-watch-kqueue (file _dir flags) + "Add a watch for FILE in DIR with FLAGS, using kqueue." + ;; kqueue does not report changes to file contents when watching + ;; directories, so we watch each file directly. + (kqueue-add-watch file + (append + (and (memq 'change flags) + '(create delete write extend rename)) + (and (memq 'attribute-change flags) + '(attrib))) + #'file-notify-callback)) + +(defun file-notify--add-watch-w32notify (_file dir flags) + "Add a watch for FILE in DIR with FLAGS, using w32notify." + (w32notify-add-watch dir + (append + (and (memq 'change flags) + '(file-name directory-name size last-write-time)) + (and (memq 'attribute-change flags) + '(attributes))) + #'file-notify-callback)) + +(defun file-notify--add-watch-gfilenotify (_file dir flags) + "Add a watch for FILE in DIR with FLAGS, using gfilenotify." + (gfile-add-watch dir + (append '(watch-mounts send-moved) flags) + #'file-notify-callback)) + (defun file-notify-add-watch (file flags callback) "Add a watch for filesystem events pertaining to FILE. This arranges for filesystem events pertaining to FILE to be reported @@ -315,70 +355,34 @@ FILE is the name of the file whose event is being reported." (dir (directory-file-name (if (file-directory-p file) file - (file-name-directory file)))) - desc func l-flags) + (file-name-directory file))))) (unless (file-directory-p dir) (signal 'file-notify-error `("Directory does not exist" ,dir))) - (if handler - ;; A file name handler could exist even if there is no local - ;; file notification support. - (setq desc (funcall handler 'file-notify-add-watch dir flags callback)) - - ;; Check, whether Emacs has been compiled with file notification - ;; support. - (unless file-notify--library - (signal 'file-notify-error - '("No file notification package available"))) - - ;; Determine low-level function to be called. - (setq func - (cond - ((eq file-notify--library 'inotify) 'inotify-add-watch) - ((eq file-notify--library 'kqueue) 'kqueue-add-watch) - ((eq file-notify--library 'gfilenotify) 'gfile-add-watch) - ((eq file-notify--library 'w32notify) 'w32notify-add-watch))) - - ;; Determine respective flags. - (if (eq file-notify--library 'gfilenotify) - (setq l-flags (append '(watch-mounts send-moved) flags)) - (when (memq 'change flags) - (setq - l-flags - (cond - ((eq file-notify--library 'inotify) - '(create delete delete-self modify move-self move)) - ((eq file-notify--library 'kqueue) - '(create delete write extend rename)) - ((eq file-notify--library 'w32notify) - '(file-name directory-name size last-write-time))))) - (when (memq 'attribute-change flags) - (push (cond - ((eq file-notify--library 'inotify) 'attrib) - ((eq file-notify--library 'kqueue) 'attrib) - ((eq file-notify--library 'w32notify) 'attributes)) - l-flags))) - - ;; Call low-level function. - (setq desc (funcall - ;; kqueue does not report file changes in directory - ;; monitor. So we must watch the file itself. - func (if (eq file-notify--library 'kqueue) file dir) - l-flags 'file-notify-callback))) - - ;; We do not want to enter quoted file names into the hash. - (setq file (file-name-unquote file) - dir (file-name-unquote dir)) - - ;; Modify `file-notify-descriptors'. - (let ((watch (file-notify--watch-make - dir - (unless (file-directory-p file) (file-name-nondirectory file)) - callback))) - (puthash desc watch file-notify-descriptors)) - ;; Return descriptor. - desc)) + (let ((desc + (if handler + (funcall handler 'file-notify-add-watch dir flags callback) + (funcall + (pcase file-notify--library + ('inotify #'file-notify--add-watch-inotify) + ('kqueue #'file-notify--add-watch-kqueue) + ('w32notify #'file-notify--add-watch-w32notify) + ('gfilenotify #'file-notify--add-watch-gfilenotify) + (_ (signal 'file-notify-error + '("No file notification package available")))) + file dir flags)))) + + ;; Modify `file-notify-descriptors'. + (let ((watch (file-notify--watch-make + ;; We do not want to enter quoted file names into the hash. + (file-name-unquote dir) + (unless (file-directory-p file) + (file-name-nondirectory file)) + callback))) + (puthash desc watch file-notify-descriptors)) + ;; Return descriptor. + desc))) (defun file-notify-rm-watch (descriptor) "Remove an existing watch specified by its DESCRIPTOR. commit 0efaae78f2b66de7ebeff7d1c16771ddafdf2d06 Author: Stefan Monnier Date: Thu May 2 09:00:53 2019 -0400 * lisp/mail/footnote.el: Use dolist and hoist regexps out of loops (footnote--refresh-footnotes): Use pcase-dolist; compute regexp once outside of the loops. Use less confusing `literal` arg to `replace-match` and specify `fixedcase` since footnote--index-to-string already chose the proper case for us. (footnote--renumber): Use dolist; compute regexp once outside of the loops; shortcircuit when number is unchanged. (footnote--text-under-cursor): Rewrite. (footnote--make-hole): Use dolist. (footnote-add-footnote): CSE. (footnote-delete-footnote): Use dolist; compute regexp once outside of the loop. (footnote-delete-footnote): Don't renumber if there's no footnote left. (footnote-renumber-footnotes): Use dolist. diff --git a/lisp/mail/footnote.el b/lisp/mail/footnote.el index ef359b62b4..9a918376e6 100644 --- a/lisp/mail/footnote.el +++ b/lisp/mail/footnote.el @@ -164,7 +164,9 @@ left with the first character of footnote text." "List of (FN TEXT . POINTERS). Where FN is the footnote number, TEXT is a marker pointing to the footnote's text, and POINTERS is a list of markers pointing -to the places from which the footnote is referenced.") +to the places from which the footnote is referenced. +TEXT points right *before* the [...] and POINTERS point right +*after* the [...].") (defvar footnote-mouse-highlight 'highlight ;; FIXME: This `highlight' property is not currently used. @@ -452,52 +454,41 @@ Conversion is done based upon the current selected style." (defun footnote--refresh-footnotes (&optional index-regexp) "Redraw all footnotes. -You must call this or arrange to have this called after changing footnote -styles." - (unless index-regexp - (setq index-regexp (footnote--current-regexp))) - (save-excursion - ;; Take care of the pointers first - (let ((i 0) locn alist) - (while (setq alist (nth i footnote--markers-alist)) - (setq locn (cddr alist)) - (while locn - (goto-char (car locn)) +You must call this or arrange to have this called after changing +footnote styles." + (let ((fn-regexp (concat + (regexp-quote footnote-start-tag) + "\\(" (or index-regexp (footnote--current-regexp)) "+\\)" + (regexp-quote footnote-end-tag)))) + (save-excursion + (pcase-dolist (`(,fn ,text . ,pointers) footnote--markers-alist) + ;; Take care of the pointers first + (dolist (locn pointers) + (goto-char locn) ;; Try to handle the case where `footnote-start-tag' and ;; `footnote-end-tag' are the same string. - (when (looking-back (concat - (regexp-quote footnote-start-tag) - "\\(" index-regexp "+\\)" - (regexp-quote footnote-end-tag)) + (when (looking-back fn-regexp (line-beginning-position)) (replace-match (propertize (concat footnote-start-tag - (footnote--index-to-string (1+ i)) + (footnote--index-to-string fn) footnote-end-tag) - 'footnote-number (1+ i) footnote-mouse-highlight t) - nil "\\1")) - (setq locn (cdr locn))) - (setq i (1+ i)))) - - ;; Now take care of the text section - (let ((i 0) alist) - (while (setq alist (nth i footnote--markers-alist)) - (goto-char (cadr alist)) - (when (looking-at (concat - (regexp-quote footnote-start-tag) - "\\(" index-regexp "+\\)" - (regexp-quote footnote-end-tag))) + 'footnote-number fn footnote-mouse-highlight t) + t t))) + + ;; Now take care of the text section + (goto-char text) + (when (looking-at fn-regexp) (replace-match (propertize (concat footnote-start-tag - (footnote--index-to-string (1+ i)) + (footnote--index-to-string fn) footnote-end-tag) - 'footnote-number (1+ i)) - nil "\\1")) - (setq i (1+ i)))))) + 'footnote-number fn) + t t)))))) (defun footnote-cycle-style () "Select next defined footnote style." @@ -532,31 +523,28 @@ styles." (defun footnote--renumber (to alist-elem) "Renumber a single footnote." - (let* ((posn-list (cddr alist-elem))) - (setcar alist-elem to) - (while posn-list - (goto-char (car posn-list)) - (when (looking-back (concat (regexp-quote footnote-start-tag) - (footnote--current-regexp) - (regexp-quote footnote-end-tag)) - (line-beginning-position)) - (replace-match - (propertize + (unless (equal to (car alist-elem)) ;Nothing to do. + (let* ((fn-regexp (concat (regexp-quote footnote-start-tag) + (footnote--current-regexp) + (regexp-quote footnote-end-tag)))) + (setcar alist-elem to) + (dolist (posn (cddr alist-elem)) + (goto-char posn) + (when (looking-back fn-regexp (line-beginning-position)) + (replace-match + (propertize + (concat footnote-start-tag + (footnote--index-to-string to) + footnote-end-tag) + 'footnote-number to footnote-mouse-highlight t)))) + (goto-char (cadr alist-elem)) + (when (looking-at fn-regexp) + (replace-match + (propertize (concat footnote-start-tag (footnote--index-to-string to) footnote-end-tag) - 'footnote-number to footnote-mouse-highlight t))) - (setq posn-list (cdr posn-list))) - (goto-char (cadr alist-elem)) - (when (looking-at (concat (regexp-quote footnote-start-tag) - (footnote--current-regexp) - (regexp-quote footnote-end-tag))) - (replace-match - (propertize - (concat footnote-start-tag - (footnote--index-to-string to) - footnote-end-tag) - 'footnote-number to))))) + 'footnote-number to)))))) (defun footnote--narrow-to-footnotes () "Restrict text in buffer to show only text of footnotes." @@ -652,18 +640,11 @@ Presumes we're within the footnote area already." "Return the number of the current footnote if in footnote text. Return nil if the cursor is not positioned over the text of a footnote." - (when (and footnote--markers-alist - (<= (footnote--get-area-point-min) - (point) - (footnote--get-area-point-max))) - (let ((i 1) alist-txt result) - (while (and (setq alist-txt (nth i footnote--markers-alist)) - (null result)) - (when (< (point) (cadr alist-txt)) - (setq result (car (nth (1- i) footnote--markers-alist)))) - (setq i (1+ i))) - (when (and (null result) (null alist-txt)) - (setq result (car (nth (1- i) footnote--markers-alist)))) + (when (<= (point) (footnote--get-area-point-max)) + (let ((result nil)) + (pcase-dolist (`(,fn ,text . ,_) footnote--markers-alist) + (if (<= text (point)) + (setq result fn))) result))) (defun footnote--under-cursor () @@ -750,11 +731,8 @@ footnote area, returns `point-max'." (defun footnote--make-hole () (save-excursion - (let ((i 0) - (notes (length footnote--markers-alist)) - alist-elem rc) - (while (< i notes) - (setq alist-elem (nth i footnote--markers-alist)) + (let (rc) + (dolist (alist-elem footnote--markers-alist) (when (< (point) (- (cl-caddr alist-elem) 3)) (unless rc (setq rc (car alist-elem))) @@ -764,8 +742,7 @@ footnote area, returns `point-max'." (footnote--index-to-string (1+ (car alist-elem)))) (footnote--renumber (1+ (car alist-elem)) - alist-elem))) - (setq i (1+ i))) + alist-elem)))) rc))) (defun footnote-add-footnote () @@ -778,9 +755,10 @@ by using `footnote-back-to-message'." (interactive "*") (let ((num (if footnote--markers-alist - (if (< (point) (cl-caddar (last footnote--markers-alist))) - (footnote--make-hole) - (1+ (caar (last footnote--markers-alist)))) + (let ((last (car (last footnote--markers-alist)))) + (if (< (point) (cl-caddr last)) + (footnote--make-hole) + (1+ (car last)))) 1))) (message "Adding footnote %d" num) (footnote--insert-footnote num) @@ -807,20 +785,17 @@ delete the footnote with that number." (when (and arg (or (not footnote-prompt-before-deletion) (y-or-n-p (format "Really delete footnote %d?" arg)))) - (let (alist-elem locn) - (setq alist-elem (assq arg footnote--markers-alist)) - (unless alist-elem - (error "Can't delete footnote %d" arg)) - (setq locn (cddr alist-elem)) - (while (car locn) + (let ((alist-elem (or (assq arg footnote--markers-alist) + (error "Can't delete footnote %d" arg))) + (fn-regexp (concat (regexp-quote footnote-start-tag) + (footnote--current-regexp) + (regexp-quote footnote-end-tag)))) + (dolist (locn (cddr alist-elem)) (save-excursion - (goto-char (car locn)) - (when (looking-back (concat (regexp-quote footnote-start-tag) - (footnote--current-regexp) - (regexp-quote footnote-end-tag)) + (goto-char locn) + (when (looking-back fn-regexp (line-beginning-position)) - (delete-region (match-beginning 0) (match-end 0)))) - (setq locn (cdr locn))) + (delete-region (match-beginning 0) (match-end 0))))) (save-excursion (goto-char (cadr alist-elem)) (delete-region @@ -833,8 +808,8 @@ delete the footnote with that number." (point) 'footnote-number nil (footnote--goto-char-point-max)))))) (setq footnote--markers-alist (delq alist-elem footnote--markers-alist)) - (footnote-renumber-footnotes) - (when (null footnote--markers-alist) + (if footnote--markers-alist + (footnote-renumber-footnotes) (save-excursion (if (not (string-equal footnote-section-tag "")) (let* ((end (footnote--goto-char-point-max)) @@ -855,13 +830,9 @@ delete the footnote with that number." "Renumber footnotes, starting from 1." (interactive "*") (save-excursion - (let ((i 0) - (notes (length footnote--markers-alist)) - alist-elem) - (while (< i notes) - (setq alist-elem (nth i footnote--markers-alist)) - (unless (= (1+ i) (car alist-elem)) - (footnote--renumber (1+ i) alist-elem)) + (let ((i 1)) + (dolist (alist-elem footnote--markers-alist) + (footnote--renumber i alist-elem) (setq i (1+ i)))))) (defun footnote-goto-footnote (&optional arg) @@ -900,13 +871,13 @@ being set it is automatically widened." (defvar footnote-mode-map (let ((map (make-sparse-keymap))) - (define-key map "a" 'footnote-add-footnote) - (define-key map "b" 'footnote-back-to-message) - (define-key map "c" 'footnote-cycle-style) - (define-key map "d" 'footnote-delete-footnote) - (define-key map "g" 'footnote-goto-footnote) - (define-key map "r" 'footnote-renumber-footnotes) - (define-key map "s" 'footnote-set-style) + (define-key map "a" #'footnote-add-footnote) + (define-key map "b" #'footnote-back-to-message) + (define-key map "c" #'footnote-cycle-style) + (define-key map "d" #'footnote-delete-footnote) + (define-key map "g" #'footnote-goto-footnote) + (define-key map "r" #'footnote-renumber-footnotes) + (define-key map "s" #'footnote-set-style) map)) (defvar footnote-minor-mode-map