Many improvements for Context Menus (bug#9054)

* lisp/menu-bar.el (menu-bar-showhide-menu): Add "Context Menus".

* lisp/mouse.el (context-menu-undo): Add "in Region" to the titles
when the region is active.
(context-menu-region): Use 'mouse-yank-from-menu' in menu items
created from 'yank-menu' for submenu "Paste from Kill Menu".
(context-menu-region): Add submenu "Select" with things to mark.
(mark-thing-at-mouse, mouse-yank-from-menu): New functions.

* lisp/thingatpt.el (bounds-of-thing-at-mouse): New function.

* lisp/progmodes/elisp-mode.el (elisp-context-menu):
* lisp/progmodes/prog-mode.el (prog-context-menu):
Use full symbol/identifier names in :help strings.

Suggested by Martin Rudalics <rudalics@gmx.at>
This commit is contained in:
Juri Linkov 2021-09-22 20:08:45 +03:00
parent 2386b08526
commit ac6afe9c33
5 changed files with 111 additions and 50 deletions

View file

@ -1315,6 +1315,11 @@ mail status in mode line"))
:visible (and (display-graphic-p) (fboundp 'x-show-tip))
:button (:toggle . tooltip-mode)))
(bindings--define-key menu [showhide-context-menu]
'(menu-item "Context Menus" context-menu-mode
:help "Turn mouse-3 context menus on/off"
:button (:toggle . context-menu-mode)))
(bindings--define-key menu [menu-bar-mode]
'(menu-item "Menu Bar" toggle-menu-bar-mode-from-frame
:help "Turn menu bar on/off"

View file

@ -418,16 +418,16 @@ Some context functions add menu items below the separator."
(listp pending-undo-list)
(consp buffer-undo-list)))
(define-key-after menu [undo]
'(menu-item "Undo" undo
`(menu-item ,(if (region-active-p) "Undo in Region" "Undo") undo
:help "Undo last edits")))
(when (and (not buffer-read-only)
(undo--last-change-was-undo-p buffer-undo-list))
(define-key-after menu [undo-redo]
'(menu-item "Redo" undo-redo
`(menu-item (if undo-in-region "Redo in Region" "Redo") undo-redo
:help "Redo last undone edits")))
menu)
(defun context-menu-region (menu _click)
(defun context-menu-region (menu click)
"Populate MENU with region commands."
(define-key-after menu [separator-region] menu-bar-separator)
(when (and mark-active (not buffer-read-only))
@ -455,21 +455,52 @@ Some context functions add menu items below the separator."
`(menu-item "Paste" mouse-yank-at-click
:help "Paste (yank) text most recently cut/copied")))
(when (and (cdr yank-menu) (not buffer-read-only))
(define-key-after menu (if (featurep 'ns) [select-paste]
[paste-from-menu])
;; ns-win.el said: Change text to be more consistent with
;; surrounding menu items `paste', etc."
`(menu-item ,(if (featurep 'ns) "Select and Paste" "Paste from Kill Menu")
yank-menu
:help "Choose a string from the kill ring and paste it")))
(let ((submenu (make-sparse-keymap (propertize "Paste from Kill Menu"))))
(dolist (item yank-menu)
(when (consp item)
(define-key-after submenu (vector (car item))
`(menu-item ,(cadr item)
,(lambda () (interactive)
(mouse-yank-from-menu click (car item)))))))
(define-key-after menu (if (featurep 'ns) [select-paste] [paste-from-menu])
`(menu-item ,(if (featurep 'ns) "Select and Paste" "Paste from Kill Menu")
,submenu
:help "Choose a string from the kill ring and paste it"))))
(when (and mark-active (not buffer-read-only))
(define-key-after menu [clear]
'(menu-item "Clear" delete-active-region
:help
"Delete text in region between mark and current position")))
(define-key-after menu [mark-whole-buffer]
'(menu-item "Select All" mark-whole-buffer
:help "Mark the whole buffer for a subsequent cut/copy"))
(let ((submenu (make-sparse-keymap (propertize "Select"))))
(define-key-after submenu [mark-whole-buffer]
`(menu-item "All"
,(lambda (e) (interactive "e") (mark-thing-at-mouse e 'buffer))
:help "Mark the whole buffer for a subsequent cut/copy"))
(define-key-after submenu [mark-line]
`(menu-item "Line"
,(lambda (e) (interactive "e") (mark-thing-at-mouse e 'line))
:help "Mark the line at click for a subsequent cut/copy"))
(define-key-after submenu [mark-defun]
`(menu-item "Defun"
,(lambda (e) (interactive "e") (mark-thing-at-mouse e 'defun))
:help "Mark the defun at click for a subsequent cut/copy"))
(define-key-after submenu [mark-list]
`(menu-item "List"
,(lambda (e) (interactive "e") (mark-thing-at-mouse e 'list))
:help "Mark the list at click for a subsequent cut/copy"))
(define-key-after submenu [mark-symbol]
`(menu-item "Symbol"
,(lambda (e) (interactive "e") (mark-thing-at-mouse e 'symbol))
:help "Mark the symbol at click for a subsequent cut/copy"))
(when (region-active-p)
(define-key-after submenu [mark-none]
`(menu-item "None"
,(lambda (_e) (interactive "e") (deactivate-mark))
:help "Deactivate the region")))
(define-key-after menu [select-region]
`(menu-item "Select" ,submenu)))
menu)
(defun context-menu-ffap (menu click)
@ -517,6 +548,26 @@ This is the keyboard interface to \\[context-menu-map]."
(global-set-key [S-f10] 'context-menu-open)
(defun mark-thing-at-mouse (click thing)
"Activate the region around THING found near the mouse CLICK."
(let ((bounds (bounds-of-thing-at-mouse click thing)))
(when bounds
(goto-char (if mouse-select-region-move-to-beginning
(car bounds) (cdr bounds)))
(push-mark (if mouse-select-region-move-to-beginning
(cdr bounds) (car bounds))
t 'activate))))
(defun mouse-yank-from-menu (click string)
"Insert STRING at mouse CLICK."
;; Give temporary modes such as isearch a chance to turn off.
(run-hooks 'mouse-leave-buffer-hook)
(when select-active-regions
(deactivate-mark))
(or mouse-yank-at-point (mouse-set-point click))
(push-mark)
(insert string))
;; Commands that operate on windows.

View file

@ -158,22 +158,13 @@ All commands in `lisp-mode-shared-map' are inherited by this map.")
(when (thing-at-mouse click 'symbol)
(define-key-after menu [elisp-separator] menu-bar-separator
'middle-separator)
(define-key-after menu [info-lookup-symbol]
'(menu-item "Look up in Manual"
(lambda (click) (interactive "e")
(info-lookup-symbol
(intern (thing-at-mouse click 'symbol t))))
:help "Display definition in relevant manual")
'elisp-separator)
(let* ((string (thing-at-mouse click 'symbol t))
(symbol (when (stringp string) (intern string)))
(title (cond
((not (symbolp symbol)) nil)
((and (facep symbol) (not (fboundp symbol)))
"Face")
((and (fboundp symbol) (boundp symbol)
(memq symbol minor-mode-list))
"Mode")
((and (fboundp symbol)
(not (or (boundp symbol) (facep symbol))))
"Function")
@ -183,11 +174,17 @@ All commands in `lisp-mode-shared-map' are inherited by this map.")
((or (fboundp symbol) (boundp symbol) (facep symbol))
"Symbol"))))
(when title
(define-key-after menu [info-lookup-symbol]
`(menu-item "Look up in Manual"
(lambda (_click) (interactive "e")
(info-lookup-symbol ',symbol))
:help ,(format "Find `%s' in relevant manual" symbol))
'elisp-separator)
(define-key-after menu [describe-symbol]
`(menu-item (format "Describe %s" ,title)
(lambda (_click) (interactive "e")
(describe-symbol ',symbol))
:help "Display the full documentation of symbol")
:help ,(format "Display the documentation of `%s'" symbol))
'elisp-separator))))
menu)

View file

@ -48,27 +48,26 @@
(require 'xref)
(define-key-after menu [prog-separator] menu-bar-separator
'middle-separator)
(when (not (xref-marker-stack-empty-p))
(unless (xref-marker-stack-empty-p)
(define-key-after menu [xref-pop]
'(menu-item "Back Definition" xref-pop-marker-stack
:help "Back to the position of the last search")
'prog-separator))
(when (save-excursion
(mouse-set-point click)
(xref-backend-identifier-at-point
(xref-find-backend)))
(define-key-after menu [xref-find-ref]
'(menu-item "Find References" xref-find-references-at-mouse
:help "Find references to identifier")
'prog-separator))
(when (save-excursion
(mouse-set-point click)
(xref-backend-identifier-at-point
(xref-find-backend)))
(define-key-after menu [xref-find-def]
'(menu-item "Find Definition" xref-find-definitions-at-mouse
:help "Find definition of identifier")
'prog-separator))
(let ((identifier (save-excursion
(mouse-set-point click)
(xref-backend-identifier-at-point
(xref-find-backend)))))
(when identifier
(define-key-after menu [xref-find-ref]
`(menu-item "Find References" xref-find-references-at-mouse
:help ,(format "Find references to `%s'" identifier))
'prog-separator)
(define-key-after menu [xref-find-def]
`(menu-item "Find Definition" xref-find-definitions-at-mouse
:help ,(format "Find definition of `%s'" identifier))
'prog-separator)))
menu)
(defvar prog-mode-map

View file

@ -151,15 +151,6 @@ positions of the thing found."
(if (and (<= real-beg orig) (<= orig end) (< real-beg end))
(cons real-beg end))))))))))
;;;###autoload
(defun thing-at-mouse (event thing &optional no-properties)
"Return the THING at mouse click.
Like `thing-at-point', but tries to use the event
where the mouse button is clicked to find a thing nearby."
(save-excursion
(mouse-set-point event)
(thing-at-point thing no-properties)))
;;;###autoload
(defun thing-at-point (thing &optional no-properties)
"Return the THING at point.
@ -196,6 +187,24 @@ a symbol as a valid THING."
(set-text-properties 0 (length text) nil text))
text)))
;;;###autoload
(defun bounds-of-thing-at-mouse (event thing)
"Determine the start and end locations for the THING at mouse click.
Like `bounds-of-thing-at-point', but tries to use the EVENT
where the mouse button is clicked to find the thing nearby."
(save-excursion
(mouse-set-point event)
(bounds-of-thing-at-point thing)))
;;;###autoload
(defun thing-at-mouse (event thing &optional no-properties)
"Return the THING at mouse click.
Like `thing-at-point', but tries to use the EVENT
where the mouse button is clicked to find the thing nearby."
(save-excursion
(mouse-set-point event)
(thing-at-point thing no-properties)))
;; Go to beginning/end
(defun beginning-of-thing (thing)