* poplife-mode
@ 2017-11-05 1:00 Tak Kunihiro
2017-11-05 5:52 ` poplife-mode Drew Adams
2017-11-11 12:47 ` poplife-mode Charles A. Roelli
0 siblings, 2 replies; 50+ messages in thread
From: Tak Kunihiro @ 2017-11-05 1:00 UTC (permalink / raw)
To: emacs-devel; +Cc: Kunihiro Tak
[-- Attachment #1: Type: text/plain, Size: 937 bytes --]
With following line, one can cut and paste text using a pop-up menu
triggered by right click.
(define-key global-map [mouse-3] menu-bar-edit-menu)
I noticed that menu-bar items that lead visiting files, buffers,
frames, bookmarks, and recentf can be gathered into a pop-up menu.
I wrote a minor mode `poplife' that provides an integrated pop-up menu
triggered by right click. Also this minor mode offers contextual
pop-up menus. When a thing under mouse click is file/directory, word,
and url, this provides pop-up menus of list of files, candidates of
words, and url-opening-menu, respectively.
(require 'poplife)
(setq poplife-word-flag t)
(setq poplife-url-flag t)
(setq poplife-edit-cottager '(:imenu t :buffer t :frame t :bookmark t :recentf t))
(poplife-mode 1)
Contextual pop-up menu by right click is very common interface
nowadays and I propose to include this (or something like this) to
Emacs.
[-- Attachment #2: poplife.el --]
[-- Type: application/octet-stream, Size: 46815 bytes --]
;;; poplife.el --- Pop files up on mouse click
;; Author: Tak Kunihiro <tkk@misasa.okayama-u.ac.jp>
;; Keywords: mouse
;; Package: emacs
;; This file is NOT part of GNU Emacs.
;; 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 <http://www.gnu.org/licenses/>.
;; Usage:
;;
;; To interactively toggle the mode:
;;
;; M-x poplife-mode RET
;;
;; To make the mode permanent, put these in your init file:
;;
;; (require 'poplife)
;; (poplife-mode 1)
;;; Commentary:
;;
;; This package pops contextual menu triggered by right click. On a
;; click, depending on a thing under the mouse event, (1)
;; FILE/DIRECTORY menu, (2) WORD menu, (3) URL menu, or (4) EDIT menu
;; will be popped. The edit menu lets you revise buffer and visit a
;; file in a directory. As an option, the edit menu also lets you
;; jump by iMenu, switch to a buffer, switch to a frame, visit a
;; bookmark, and visit a recent file. The four menus are detailed as
;; below.
;;
;; (1) FILE/DIRECTORY menu
;;
;; List how-to-open-a-file menu or files in
;; default-directory under a mouse event.
;;
;; (2) WORD menu
;;
;; Pop word candidates when word under a mouse event is incorrect,
;; when `poplife-word-flag' is non-nil.
;;
;; (3) URL menu
;;
;; Pop how-to-open-an-url menu under a mouse event, when
;; `poplife-url-flag' is non-nil.
;;
;; (4) EDIT menu
;;
;; List basic edition-commands, optional edition-commands,
;; and visiting menus.
;;
;; Basic edition-commands are defined by `poplife-edit-cmd-0'.
;;
;; Optional edition-commands are defined by `poplife-edit-cmd-1'.
;; with format similar to `recentf-menu-items-for-commands'.
;;
;; Visiting menu to visit files in default-directory is included by
;; default. To include a series of visiting menus, set each item of
;; `poplife-edit-cottager' to non-nil, as listed below.
;;
;; :buffer List buffers by `global-buffers-menu-map'.
;; :imenu List table of contents of current buffer by iMenu.
;; :frame List frames by `global-buffers-menu-map'.
;; :bookmark List bookmarks by `bookmark-all-names'.
;; :recentf List recent files by `recentf-menu-elements'.
;;; References
;; Following discussions were referred to paste text with erasing
;; active region.
;;
;; http://lists.gnu.org/archive/html/bug-gnu-emacs/2017-07/msg00086.html
;; http://lists.gnu.org/archive/html/emacs-devel/2017-07/msg00796.html
;;
;; Following codes from Emacs core are useful for development.
;;
;; (define-key global-map [mouse-3] menu-bar-edit-menu)
;; (popup-menu menu-bar-edit-menu)
;; (popup-menu (mouse-menu-bar-map))
;; (popup-menu (mouse-menu-major-mode-map))
;; (popup-menu menu-bar-bookmark-map)
;; (popup-menu global-buffers-menu-map)
;; (define-key global-map [mouse-3] 'mouse-buffer-menu)
;; (buffer-menu-open)
;;; Templates of keymap
;;
;; Keymaps from imenu, menu-bar, bookmark, and recentf are united.
;; They are formatted to be easymenu from standard keymap. Typical
;; easymenu and standard keymap are shown below for convenience.
;;
;; (label
;; [label callback]
;; (label
;; [label callback]
;; ["--" ignore]
;; [label callback])
;; [label callback])
;;
;; (keymap
;; label
;; (symbol menu-item label callback)
;; [(label lambda nil (interactive) commands)
;; (label keymap
;; (symbol menu-item label callback)
;; (symbol menu-item label callback))
;; (label lambda nil (interactive) commands)]
;; (symbol "--")
;; (symbol menu-item label
;; (keymap label
;; (symbol menu-item label callback)
;; (symbol menu-item label callback)))
;; (symbol menu-item label callback))
;;; Code:
(defcustom poplife-word-flag nil
"Popup words under mouse event using `flyspell-correct-word'."
:group 'mouse
:type 'boolean
:version "26.1")
(defcustom poplife-url-flag nil
"Popup URL menu under mouse event using `eww'."
:group 'mouse
:type 'boolean
:version "26.1")
(defcustom poplife-edit-cmd-0 '(cut copy paste select-paste paste-from-menu clear mark-whole-buffer)
"Basic edition-commands in edit menu.
Items must be one listed in `menu-bar-edit-menu'."
:group 'mouse
:type '(repeat symbol)
:version "26.1")
(defvar poplife-edit-cmd-1
(list
["Close"
(lambda () (interactive)
(if (one-window-p)
(if (> (length (visible-frame-list)) 1)
(call-interactively 'delete-frame)
(quit-window)) ; (kill-buffer (window-buffer))
(delete-window)))
:help "Remove this window or kill this buffer"
:visible (not (region-active-p))
:active t]
["Spell-Check"
flyspell-correct-word-before-point
:help "Spell check word at point"
:visible (and poplife-word-flag
(fboundp 'flyspell-correct-word-before-point)
(not (region-active-p)))
:active t]
["Spell-Check"
ispell-region
:help "Spell check selected text"
:visible (and poplife-word-flag
(region-active-p))
:active t]
["Search Web"
(lambda () (interactive)
(let ((keyword (buffer-substring-no-properties (region-beginning) (region-end))))
(switch-to-buffer-other-window (generate-new-buffer "*eww*"))
(eww-mode)
(eww keyword)))
:help "Search selected text by online service"
:visible (and poplife-url-flag
(region-active-p))
:active t]
["--"
ignore
:visible (and (region-active-p)
(or poplife-word-flag poplife-url-flag))
:active t])
"Optional commands in edit menu.")
(defvar poplife-edit-cottager
'(:imenu nil :buffer nil :frame nil :bookmark nil :recentf nil)
"Extra menus to be included in edit menu besides file.")
\f
(defvar poplife-file-max-menu-items 25
"Maximum number of items in file menu.
See also `recentf-max-menu-items', `buffers-menu-max-size', and
`imenu-max-items'.")
(defvar poplife-file-recursive 1
"Depth of directory scan on directory menu.")
(defvar poplife-dir-do-not-scan-regexp "inbox"
"Contents of directory matching this regexp will not be shown.
Instead contents of home directory are displayed.")
(defvar poplife-file-do-not-show-regexp
"^\\.\\.?$\\|^#\\|\\.elc\\'\\|\\.exe\\'\\|^\\.[^e]\\|\\.lnk\\'\\|\\~\\'\\|^desktop\\.ini\\'\\|^\\.DS_store\\'\\|^\\.dropbox\\'\\|^auto\\'\\|^ntuser\\|^_master_\\|^_region_\\|\\.aux\\'\\|\\.bbl\\'\\|\\.blg\\'\\|\\.fdb_latexmk\\'\\|\\.fls\\'\\|\\.lof\\'\\|\\.lot\\'\\|\\.out\\'\\|\\.toc\\'\\|\\.synctex\\.gz\\'\\|\\.synctex\\.ico\\'\\|^Thumbs\\.db\\'\\|^Icon"
"Filenames matching this regexp will not be displayed in file menu.") ; dired-trivial-filenames, dired-omit-files
(defvar poplife-file-do-not-open-regexp
"\\.pdf\\'\\|\\.doc\\'\\|\\.docx\\'\\|\\.xls\\'\\|\\.xlsx\\'\\|\\.ppt\\'\\|\\.pptx\\'\\|\\.jpg\\'\\|\\.png\\'\\|\\.tif\\'\\|\\.tiff\\'\\|\\.bmp\\'\\|\\.aif\\'\\|\\.wav\\'\\|\\.7z\\'\\|\\.tar\\'\\|\\.dll\\'\\|\\.zip\\'\\|\\.info\\'\\|\\.igpi\\'\\|\\.ttf\\'\\|\\.otf\\'\\|\\.pkg\\'"
"Filenames matching this regexp will not be suggested to open by file menu.")
(defvar poplife-func-find-file 'find-file
"Function to visit a file, and a Recentf element.
Depending on context, this is internally overwritten to be
`find-file', `find-file-other-window', and
`find-file-other-frame'. This is referred to visit a buffer, an
imenu element, and a bookmark element via
`poplife-func-switch-to-buffer'. A buffer is visited by
`menu-bar-select-buffer-function' on `global-buffers-menu-map'.
An imenu element is always visited on current buffer. A bookmark
element is visited by `display-func' on `bookmark-jump'.")
(defvar poplife-func-find-file-by-default-app 'poplife-find-file-by-default-app
"Function to visit file by default application.")
\f
(require 'ffap)
(require 'easymenu)
;;;###autoload
(define-minor-mode poplife-mode
"A global minor-mode to show contextual menu by right click."
:init-value nil
:group 'mouse
:global t
:keymap (let ((map (make-sparse-keymap)))
(define-key map [mouse-3]
`(menu-item "Edit menu" poplife-menu-keymap
:filter ,(lambda (_) (poplife-menu-keymap (aref (this-command-keys) 0)))))
(define-key map [drag-mouse-3]
`(menu-item "Edit menu" poplife-menu-keymap
:filter ,(lambda (_) (poplife-menu-keymap (aref (this-command-keys) 0)))))
(define-key map [C-down-mouse-1] 'ignore)
(define-key map [C-mouse-1]
`(menu-item "Edit menu" poplife-menu-keymap
:filter ,(lambda (_) (poplife-menu-keymap (aref (this-command-keys) 0)))))
(define-key map [C-double-mouse-1]
`(menu-item "Edit menu" poplife-menu-keymap
:filter ,(lambda (_) (poplife-menu-keymap (aref (this-command-keys) 0)))))
(define-key map [C-triple-mouse-1]
`(menu-item "Edit menu" poplife-menu-keymap
:filter ,(lambda (_) (poplife-menu-keymap (aref (this-command-keys) 0)))))
(define-key map [C-drag-mouse-1]
`(menu-item "Edit menu" poplife-menu-keymap
:filter ,(lambda (_) (poplife-menu-keymap (aref (this-command-keys) 0)))))
(define-key map [remap buffer-menu-open] 'poplife-menu-open)
(define-key map [C-S-down-mouse-1] 'mouse-buffer-menu)
(define-key map [C-M-mouse-1] 'poplife-what-mouse-position)
map))
(defun poplife-menu-open ()
"Start key navigation of the poplife menu.
This is the keyboard interface to \\[poplife-menu-keymap]. This is
fork of `buffer-menu-open'."
(interactive)
(popup-menu (poplife-menu-keymap last-nonmenu-event)
(posn-at-x-y 0 0 nil t)))
(defun poplife-menu-keymap (event)
"Define keymap for contextual edit menu on mouse click EVENT.
When point in on word that is misspelled, return symbol
flyspell-correct-word. When mouse click EVENT is on file or
directory, return file-menu map. Otherwise return edit-menu
map."
(let (file-easymap
dir-easymap
faces-at-point
url-easymap
(no-region (not (region-active-p))))
(cond
;; FILE menu
((and no-region
(setq file-easymap (if (equal major-mode 'dired-mode)
(and
(mouse-posn-property (event-start event) 'dired-filename)
(poplife-file-easymap (save-excursion
(mouse-set-point event)
(dired-get-file-for-visit))
t))
(poplife-file-on-click-easymap event))))
(easy-menu-create-menu (car file-easymap) (cdr file-easymap)))
;; DIRECTORY menu
((and no-region
(if (equal major-mode 'dired-mode)
(mouse-posn-property (event-start event) 'dired-filename)
t)
(setq dir-easymap
(poplife-dir-on-click-easymap event)))
(easy-menu-create-menu (car dir-easymap) (cdr dir-easymap)))
;; WORD menu
((and no-region
poplife-word-flag
;; Check face by (what-cursor-position t) or C-u C-x =.
(setq faces-at-point (mapcar (lambda (xxx) (overlay-get xxx 'face))
(overlays-at (posn-point (event-start event)))))
(or (member 'flyspell-incorrect faces-at-point)
(member 'flyspell-duplicate faces-at-point)))
#'flyspell-correct-word) ; flyspell-correct-word-before-point
;; URL menu
((and no-region
poplife-url-flag
(setq url-easymap (poplife-url-on-click-easymap event)))
(easy-menu-create-menu (car url-easymap) (cdr url-easymap)))
;; else
(t
;; menu-bar-edit-menu
(poplife-edit-map event)))))
(defun poplife-what-mouse-position (event)
"Evaluate text properties under mouse click."
(interactive "e")
;; Check also `C-u C-x ='.
(with-output-to-temp-buffer "*Result*"
(princ (format "Event was %S\n" event))
(princ (format "Click was on face <%S>.\n"
(mouse-posn-property (event-start event) 'face)))
(princ (format "Click was on dired-filename <%S>.\n"
(mouse-posn-property (event-start event) 'dired-filename)))))
(defun poplife-file-on-click-easymap (event)
"Define easymenu of a file that is under mouse click EVENT.
The file is identified by `ffap-guesser'."
(save-excursion
(mouse-set-point event) ; ~/.emacs.d/init.el
(let ((file (ffap-guesser))) ; https://www.gnu.org/software/emacs/
; ffap-guesser cannot guess file with asterisk such as "bookmark.html*"
(when (and file
(not (ffap-file-remote-p file)))
(poplife-file-easymap file t)))))
(defun poplife-dir-on-click-easymap (event)
"Define easymenu of files and directories in directory that is under mouse click EVENT.
The directory is identified by `ffap-guesser'."
(save-excursion
(mouse-set-point event) ; ~/.emacs.d/
(let ((dir (ffap-guesser))) ; https://www.gnu.org/software/emacs/
(when (and dir
(not (ffap-file-remote-p dir)))
(poplife-dir-easymap (file-name-as-directory dir) t)))))
(defun poplife-edit-map (event)
"Define edit menu on mouse click EVENT."
;; initialize
(when (plist-get poplife-edit-cottager :bookmark)
(require 'bookmark))
(when (plist-get poplife-edit-cottager :recentf)
(require 'recentf)
(recentf-mode 1))
(when (plist-get poplife-edit-cottager :imenu)
(require 'imenu))
(save-excursion
(mouse-set-point event)
(let ((map (make-sparse-keymap "Edit")))
(unless (region-active-p)
;; Buffers with iMenu
(when (plist-get poplife-edit-cottager :buffer)
(easy-menu-add-item map nil (poplife-buffer-easymap)))
;; Frames
(when (plist-get poplife-edit-cottager :frame)
(easy-menu-add-item map nil (poplife-frame-easymap)))
;; Bookmark
(when (plist-get poplife-edit-cottager :bookmark)
(easy-menu-add-item map nil (poplife-bookmark-easymap)))
;; Recentf
(when (plist-get poplife-edit-cottager :recentf)
(easy-menu-add-item map nil (poplife-recentf-easymap)))
;; File
(let ((dir-map (poplife-dir-easymap default-directory)))
(setcar dir-map "File") ; "File" instead of ".emacs.d/"
(easy-menu-add-item map nil dir-map))
;; Separator
(define-key map [separator-edit] menu-bar-separator))
;; Option
(when poplife-edit-cmd-1
(dolist (item poplife-edit-cmd-1)
(setq item (append item nil)) ; Convert vector to list.
(let ((name (car item)))
(bindings--define-key map (vector (easy-menu-make-symbol name))
(append `(menu-item ,name) (cdr item))))))
;; Main
(dolist (item (reverse (cdr menu-bar-edit-menu)))
(when (and (listp item)
(member (car item) poplife-edit-cmd-0)) ; pick some
(bindings--define-key map (vector (car item)) (cdr item))))
map)))
;; (let ((foo (poplife-edit-map last-nonmenu-event))) (describe-variable 'foo))
\f
;;; iMenu
(defun poplife-imenu-easymap (&optional submenu)
"Define easymenu to list index by iMenu.
When SUBMENU is non-nil, this returns an easymenu with multiple actions."
(let* ((imenu-max-items poplife-file-max-menu-items) ; 25
(map-0 (ignore-errors
(imenu--split-menu
(delq nil (cdr (imenu--make-index-alist t))) ; remove "*Rescan*"
(buffer-name))))
(map (poplife-imenu-alist-to-easymap (car map-0) (cdr map-0)
'imenu--menubar-select)))
(when (>= (length map) 2) ; Return map only when map is with useful items.
(if submenu
(poplife-imenu-submenufy-easymap map)
(let ((map-rev (reverse map)))
(push (vector "More..."
'(popup-menu (poplife-imenu-easymap t)
(popup-menu-normalize-position last-nonmenu-event)))
map-rev)
(reverse map-rev))))))
;; (let ((foo (poplife-imenu-easymap))) (describe-variable 'foo))
;; (let* ((poplife-func-find-file 'find-file-other-frame) (foo (poplife-imenu-easymap))) (describe-variable 'foo))
;; (let ((foo (poplife-imenu-easymap t))) (describe-variable 'foo))
;; (popup-menu (poplife-imenu-easymap))
(defun poplife-imenu-alist-to-easymap (title alist &optional cmd)
"Create easymenu from alist by iMenu to display index by CMD.
This is fork of `imenu--create-keymap'."
(let (map)
(dolist (item alist)
(push (cond
((imenu--subalist-p item)
(poplife-imenu-alist-to-easymap (car item) (cdr item) cmd))
(t
(if cmd
;; ["poplife-word-flag" (imenu--menubar-select '("poplife-edit-cottager" . #<marker at 3207 in poplife.el>))]
;; (vector (car item) (list cmd `(quote ,item)))
(vector (car item)
(list 'let
'((display-buffer--other-frame-action ; hack for switch-to-buffer-other-frame
'((display-buffer-pop-up-frame)
(inhibit-same-window . t))))
`(funcall (quote ,(poplife-func-switch-to-buffer)) ,(current-buffer))
`(,cmd (quote ,item))))
(list 'quote item))))
map))
(setq map (reverse map))
(push title map)
map))
(defun poplife-imenu-submenufy-easymap (map)
"Return easymenu of iMenu MAP with recursive structure."
(let (map-1)
(dolist (item map)
(push (cond
((listp item) ; when an item is a list such for ("Variables"...), resolve it until atom
(poplife-imenu-submenufy-easymap item))
((vectorp item) ; when an item is vector such for ["poplife-word-flag" (imenu--menubar-select...)]
(poplife-imenu-elt-easymap item))
(t item)) ; else such for "poplife.el"
map-1))
(reverse map-1)))
(defun poplife-imenu-elt-easymap (elt)
"Return easymenu of iMenu ELT with submenu added."
(let ((label (aref elt 0)) ; "poplife-edit-cottager"
(cmd (nth 3 (aref elt 1))) ; (imenu--menubar-select '("poplife-edit-cottager" . #<marker at 3207 in poplife.el>))
(buf (current-buffer))) ; #<buffer poplife.el>
(list label
(vector "Open" `(progn (switch-to-buffer ,buf) ,cmd))
["--" ignore]
(vector "Open in Other Window" `(progn (switch-to-buffer-other-window ,buf) ,cmd))
;; (vector "Open in Frame" `(progn (switch-to-buffer-other-frame ,buf) ,cmd))
(vector "Open in Frame" `(progn (pop-to-buffer ,buf '((display-buffer-pop-up-frame) (inhibit-same-window . t))) ,cmd)))))
\f
;;; Frame
(defun poplife-frame-easymap ()
"Define easymenu to list frames."
(let ((frame-vec (nth 2 (cadddr (assoc 'frames global-buffers-menu-map))))
(poplife-func-find-file 'find-file-other-frame)
map)
(dolist (elt (append frame-vec nil)) ; Convert vector to list.
(let* ((nickname (car elt))
(cmd (nth 4 elt))
(frame (cadr cmd)))
(push (vector nickname cmd :active (not (equal frame (selected-frame)))) map)))
(push ["New" (make-frame-command)] map)
(let* ((dir-map (poplife-dir-easymap default-directory)))
(push ["--" ignore] map)
(when (plist-get poplife-edit-cottager :buffer)
(push (poplife-buffer-easymap) map))
(when (plist-get poplife-edit-cottager :bookmark)
(push (poplife-bookmark-easymap) map))
(when (plist-get poplife-edit-cottager :recentf)
(push (poplife-recentf-easymap) map))
(setcar dir-map "File") ; "Directory"
(push dir-map map))
(setq map (reverse map))
(push "Frames" map)
map))
;; (let ((foo (poplife-frame-easymap))) (describe-variable 'foo))
\f
;;; Buffer
(defun poplife-buffer-easymap (&optional submenu)
"Define easymenu to list buffers.
This extracts list of buffers from `global-buffers-menu-map'.
When SUBMENU is non-nil, this returns an easymenu with multiple actions."
(let ((buffer-vec (nth 2 global-buffers-menu-map))
(menu-bar-select-buffer-function (poplife-func-switch-to-buffer))
map)
;; Add submenu on request.
(dolist (elt (append buffer-vec nil)) ; Convert vector to list.
(push (poplife-buffer-elt-easymap elt submenu) map))
;; Add option.
(push (vector "More..."
'(let (buffer-full-map)
(let (buffers-menu-max-size)
(menu-bar-update-buffers t)
(setq buffer-full-map
(poplife-buffer-easymap t)))
(menu-bar-update-buffers t)
(popup-menu buffer-full-map
(popup-menu-normalize-position last-nonmenu-event)))
:visible t
:active (not submenu))
map)
(let* ((dir-map (poplife-dir-easymap default-directory)))
(push ["--" ignore] map)
(when (plist-get poplife-edit-cottager :bookmark)
(push (poplife-bookmark-easymap) map))
(when (plist-get poplife-edit-cottager :recentf)
(push (poplife-recentf-easymap) map))
(setcar dir-map "File") ; "Open", "Directory", "File"
(push dir-map map))
;; Reverse map and add a key.
(setq map (reverse map))
(push "Buffers" map)
map))
;; (let ((foo (poplife-buffer-easymap))) (describe-variable 'foo))
;; (let ((foo (poplife-buffer-easymap t))) (describe-variable 'foo))
(defun poplife-buffer-elt-easymap (elt &optional submenu)
"Define easymenu a buffer ELT.
When SUBMENU is non-nil, this returns an easymenu with multiple actions."
;; on 25.2, pick 4th out of 5 items
;; ("menu-bar.el.gz " lambda nil (interactive) (funcall menu-bar-select-buffer-function #<buffer menu-bar.el.gz>))
;; on 24.5, pick 5th out of 6 items
;; ("menu-bar.el.gz " (nil) lambda nil (interactive) (funcall menu-bar-select-buffer-function #<buffer menu-bar.el.gz>))
(let* ((len245 6)
(nth252 4)
(nth245 5)
(nickname (car elt))
(buf (nth 2 (nth (if (equal (length elt) len245) nth245 nth252) elt))))
(if (not submenu)
(let* (imenu-map)
(if (and (plist-get poplife-edit-cottager :imenu)
(equal (current-buffer) buf)
(setq imenu-map (poplife-imenu-easymap)))
imenu-map
(vector nickname `(funcall (quote ,menu-bar-select-buffer-function) ,buf)
:active `(not (equal ,(current-buffer) ,buf)))))
(list nickname
(vector "Open" `(switch-to-buffer ,buf) :active `(not (equal ,(current-buffer) ,buf)))
["--" ignore]
(vector "Open in Other Window" `(switch-to-buffer-other-window ,buf))
(vector "Open in Frame" `(switch-to-buffer-other-frame ,buf))))))
\f
;;; Recentf
(defun poplife-recentf-easymap (&optional submenu)
"Define easymenu to list recentf.
When SUBMENU is non-nil, this returns an easymenu with multiple actions."
(let (map
(recentf-menu-shortcuts 0)
(elements (recentf-menu-elements recentf-max-menu-items)))
;; See `recentf-make-menu-items'.
(setq map (mapcar (lambda (elt)
(funcall 'poplife-recentf-elt-easymap elt submenu))
(recentf-apply-menu-filter
recentf-menu-filter
elements)))
(let ((map-rev (reverse map)))
(push (vector "More..."
'(let ((recentf-max-menu-items recentf-max-saved-items))
(popup-menu (poplife-recentf-easymap t)
(popup-menu-normalize-position last-nonmenu-event)))
:help "Show more Recentf"
:visible t
:active (not submenu))
map-rev)
(push ["--" ignore] map-rev)
(push ["Edit List..."
recentf-edit-list
:help "Manually remove files from the recent list"
:active t]
map-rev)
(push ["Save List Now"
recentf-save-list
:help "Save the list of recently opened files now"
:active t]
map-rev)
(setq map (reverse map-rev)))
(cons "Recent" map)))
;; (let ((foo (poplife-recentf-easymap))) (describe-variable 'foo))
(defun poplife-recentf-elt-easymap (elt &optional submenu)
"Define easymenu to popup recentf item ELT.
When SUBMENU is non-nil, this returns an easymenu with multiple actions."
;; This is fork of `recentf-make-menu-item'.
(let ((name (recentf-menu-element-item elt))
(file (recentf-menu-element-value elt)))
(if (recentf-sub-menu-element-p elt)
(cons name (mapcar (lambda (elt) (funcall 'poplife-recentf-elt-easymap elt)) file)) ; for `recentf-arrange-by-dir'
;; (vector name
;; `(,recentf-menu-action ,file) ; poplife-func-find-file
;; :help (concat "Open " file)
;; :active t)
(let ((map
(if (file-directory-p file)
(poplife-dir-easymap file submenu) ; directory
(poplife-file-easymap file submenu)))) ; file
(when (listp map)
(setcar map name))
map))))
\f
;;; Bookmark
(defun poplife-bookmark-easymap (&optional submenu)
"Define easymenu to list bookmarks.
When SUBMENU is non-nil, this returns an easymenu with multiple actions."
(let ((map
(list
(vector "More..." '(popup-menu (poplife-bookmark-easymap t)
(popup-menu-normalize-position last-nonmenu-event))
:visible t
:active (not submenu)
:help "Set a bookmark named inside a file.")
["--" ignore]
["Add..." bookmark-set :visible t :active (or (buffer-file-name) (eq major-mode 'dired-mode))
:help "Set a bookmark named inside a file."]
["Edit List..." bookmark-bmenu-list :visible t :active t
:help "Display a list of existing bookmarks"]
["Save List Now" bookmark-save :visible t :active t
:help "Save currently defined bookmarks"])))
(dolist (bookmark (bookmark-all-names))
(push (poplife-bookmark-elt-easymap bookmark submenu) map))
(cons "Bookmark" map)))
;; (let ((foo (poplife-bookmark-easymap))) (describe-variable 'foo))
;; (let ((foo (poplife-bookmark-easymap t))) (describe-variable 'foo))
(defun poplife-bookmark-elt-easymap (bookmark &optional submenu)
"Define easymenu to list a BOOKMARK.
When SUBMENU it non-nil, this returns an easymenu with multiple actions."
(let (map)
(if (not submenu)
(let ((file (bookmark-get-filename bookmark)))
(if (and (not (file-remote-p file)) ; when bookmark is directory
(file-exists-p file)
(file-directory-p file))
(poplife-dir-easymap file submenu) ; offer directory menu
(vector bookmark
;; `(bookmark-jump ,bookmark DISPLAY-FUNC)
`(bookmark-jump ,bookmark (quote ,(poplife-func-switch-to-buffer))) ; switch-to-buffer
:visible t
:active (not (string= ; gray the vising file out
(and (buffer-file-name) (expand-file-name (buffer-file-name)))
(expand-file-name (bookmark-get-filename bookmark))))
:help (format "Jump to %s" bookmark))))
;; (push (vector "Show Annotation..." `(bookmark-show-annotation ,bookmark) :visible t :active `(bookmark-get-annotation ,bookmark) :help bookmark) map)
;; (push (vector "Edit Annotation..." `(bookmark-edit-annotation ,bookmark) :visible t :help bookmark) map)
(let ((annot-map (poplife-bookmark-annotation-easymap bookmark)))
(if (vectorp annot-map) ; with no annotation and with "Add Annotation..."
(push annot-map map)
(dolist (annot-item (reverse (cdr annot-map)))
(push annot-item map))
(push ["--" ignore] map)
(push (vector "Edit Annotation..." `(bookmark-edit-annotation ,bookmark) :visible t :help bookmark) map)))
(push (vector "Delete..." `(and (y-or-n-p (format "Are you sure you want to delete a bookmark %s? " ,bookmark)) (bookmark-delete ,bookmark)) :visible t :help bookmark) map)
(push (vector "Edit Location..." `(bookmark-relocate ,bookmark) :visible t :help bookmark) map)
(push (vector "Rename..." `(bookmark-rename ,bookmark) :visible t :help bookmark) map)
(push (vector "Insert Location" `(bookmark-locate ,bookmark) :visible t :help bookmark) map)
(push (vector "Insert Contents" `(bookmark-insert ,bookmark) :visible t :help bookmark) map)
(push (vector "Open in File Browser" `(poplife-find-location (expand-file-name (bookmark-get-filename ,bookmark))) :visible t :active t :help bookmark) map)
(push (vector "Open in Frame" `(bookmark-jump ,bookmark 'switch-to-buffer-other-frame) :visible t :help bookmark) map)
(push (vector "Open in Other Window" `(bookmark-jump-other-window ,bookmark) :visible t :help bookmark) map)
(push ["--" ignore] map)
(push (vector "Open" `(bookmark-jump ,bookmark) :visible t :help bookmark) map) ; switch-to-buffer
(push (vector ".." `(let ((poplife-file-recursive ,poplife-file-recursive)
(poplife-func-find-file (quote ,poplife-func-find-file)))
(poplife-find-dir (expand-file-name "../" (bookmark-get-filename ,bookmark)) ,submenu))
:visible t :active t) map)
(let ((annotation (bookmark-get-annotation bookmark)))
(cons (format "%s%s" bookmark (if (and annotation (not (string-equal annotation ""))) "*" "")) map)))))
;; (let ((foo (poplife-bookmark-elt-easymap "poplife.el\\site-lisp"))) (describe-variable 'foo))
;; (let ((foo (poplife-bookmark-elt-easymap "poplife.el\\site-lisp" t))) (describe-variable 'foo))
(defvar poplife-bookmark-annotation-detail-flag t
"Show full contents of annotation in popup-menu.")
(defun poplife-bookmark-annotation-easymap (bookmark)
"Define easymenu to list annotation."
(let ((annot (bookmark-get-annotation bookmark))
(annot-column 36)) ; 36 is arbitrary number or (length "Open in Other Window")
(if (and annot (not (string-equal annot "")))
(if poplife-bookmark-annotation-detail-flag
(let ((lines (poplife-split-string annot annot-column))
map)
(dolist (line (reverse lines))
(push (vector line `(bookmark-edit-annotation ,bookmark) :visible t :active t :help bookmark) map))
(cons "Edit Annotation..." map))
(let (annot-name)
(setq annot-name (format "Edit Annotation `%s'..." (if (> (length annot) annot-column) (substring annot 0 annot-column) annot)))
(vector annot-name `(bookmark-edit-annotation ,bookmark) :visible t :active t :help bookmark)))
(vector "Add Annotation..." `(bookmark-edit-annotation ,bookmark) :visible t :active t :help bookmark))))
(defun poplife-split-string (string fill-length)
"Split STRING into list of string.
Argument FILL-LENGTH determines length of each line."
(setq string (replace-regexp-in-string
(rx (* (any " \t\n")) eos) "" string)) ; Chomp text.
(with-temp-buffer
(insert string)
(let ((fill-column fill-length) ; Replace text.
(find-repl-list '(("^$" . " ") (" +" . " ")))) ; Avoid having "--" on menu.
(fill-region (point-min) (point-max))
(dolist (find-repl find-repl-list)
(goto-char (point-min))
(while (re-search-forward (car find-repl) nil t)
(replace-match (cdr find-repl)))))
(split-string (buffer-string) "\n"))) ; List of text lines.
\f
;;; File
(defun poplife-file-easymap (file &optional submenu)
"Define easymenu to list a FILE.
When SUBMENU it non-nil, this returns an easymenu with multiple actions."
(setq file (expand-file-name file))
(and (not (file-directory-p file))
(let* (map
(file-nickname (file-name-nondirectory file))
(file-readable-flag (and (file-regular-p file)
(file-readable-p file)))
(open-file-flag (and (not (string-match-p poplife-file-do-not-open-regexp file))
file-readable-flag))
(dir (file-name-directory file))
(open-dir-flag (and (file-directory-p dir)
(file-accessible-directory-p dir))))
(if (not submenu)
(vector file-nickname
`(funcall (if ,open-file-flag
(quote ,poplife-func-find-file)
(quote ,poplife-func-find-file-by-default-app)) ,file)
:active (and file-readable-flag ; gray the vising file out
(not (string=
(and (buffer-file-name) (expand-file-name (buffer-file-name)))
file)))
:help file)
(push (vector "Open in File Browser" `(poplife-find-location ,file)
:visible t
:active open-dir-flag
:help dir) map)
(push (vector "Open by Default App" `(,poplife-func-find-file-by-default-app ,file)
:visible t
:active t
:help file) map)
(push (vector "Open with Bookmarked..." `(progn (find-file ,file) (bookmark-set))
:visible (fboundp 'bookmark-set)
:active open-file-flag
:help "Open and Add to Bookmarks") map)
(push (vector "Open in Frame" `(find-file-other-frame ,file)
:visible t
:active open-file-flag
:help file) map)
(push (vector "Open in Other Window" `(find-file-other-window ,file)
:visible t
:active open-file-flag
:help file) map)
(push ["--" ignore] map)
(push (vector "Open" `(find-file ,file)
:visible t
:active (and open-file-flag ; gray the vising file out
(not (string=
(and (buffer-file-name) (expand-file-name (buffer-file-name)))
file)))
:help file) map)
(push (vector ".." `(let ((poplife-file-recursive ,poplife-file-recursive)
(poplife-func-find-file (quote ,poplife-func-find-file)))
(poplife-find-dir ,dir, submenu))
:visible t :active open-dir-flag :help dir) map)
(cons file-nickname map)))))
;; (let ((foo (poplife-file-easymap "~/.emacs.d/init.el"))) (describe-variable 'foo))
;; (let ((foo (poplife-file-easymap "~/.emacs.d/init.el" t))) (describe-variable 'foo))
(defun poplife-dir-easymap (dir &optional submenu depth)
"Define easymenu to list files and directories in DIR.
When SUBMENU is non-nil, this returns an easymenu with multiple actions.
When DEPTH is more than 1, DIR is recursively scanned."
(when (string-match-p poplife-dir-do-not-scan-regexp dir)
(setq dir "~"))
(setq dir (directory-file-name (expand-file-name dir))) ; Remove slash at the end.
(or depth (setq depth 1))
(let (map base-dir parent-dir rawfiles menufiles)
(setq base-dir (file-name-as-directory (file-name-nondirectory dir))) ; Add slash at the end.
(setq parent-dir (directory-file-name (file-name-directory dir)))
;; Obtain a file list.
(setq rawfiles (ignore-errors (directory-files dir t)))
;; Filter out trivial files.
(dolist (fullfile rawfiles)
(let ((file-nickname (file-name-nondirectory fullfile)))
(unless (string-match-p poplife-file-do-not-show-regexp file-nickname)
(push fullfile menufiles))))
;; Limit number of menufiles
(when (and poplife-file-max-menu-items
(not submenu))
(let ((nfile (length menufiles)))
(setq menufiles (nthcdr (- nfile poplife-file-max-menu-items) menufiles))))
;; Add More menu.
(push (vector "More..." ; Item to open a current directory.
`(let (poplife-file-max-menu-items
;; (poplife-file-recursive ,(1+ poplife-file-recursive))
(poplife-file-recursive ,poplife-file-recursive)
(poplife-func-find-file (quote ,poplife-func-find-file)))
(poplife-find-dir ,dir t))
:active `(not ,submenu)
:visible t
:help dir)
map)
;; Create map with files and directories.
(dolist (fullfile menufiles)
(let ((file-nickname (file-name-nondirectory fullfile)))
(if (file-directory-p fullfile) ; when item is directory
(push (if (or (>= depth poplife-file-recursive)
(not (file-accessible-directory-p fullfile)))
(vector (file-name-as-directory file-nickname)
`(let ((poplife-file-recursive ,poplife-file-recursive)
(poplife-func-find-file (quote ,poplife-func-find-file)))
(poplife-find-dir ,fullfile ,submenu))
:active (file-accessible-directory-p fullfile) :help fullfile)
(poplife-dir-easymap fullfile submenu (1+ depth))) ; recursive
map)
(push ; when item is file (that is defined as `not a directory')
(poplife-file-easymap fullfile submenu)
map))))
(push ["--" ignore] map)
(push (if (not submenu)
;; Single item
(vector "." ; item to open current directory
`(,poplife-func-find-file ,dir ,submenu)
:visible t :active t :help dir)
;; Multiple items in submenu.
(delq nil
(list "."
(vector "Open" ; item to open current directory
`(find-file ,dir) ; ,poplife-func-find-file
:visible t :active t :help dir)
["--" ignore]
(vector "Open in Other Window"
`(find-file-other-window ,dir)
:visible t :active t :help dir)
(vector "Open in Frame"
`(find-file-other-frame ,dir)
:visible t :active t :help dir)
(vector "Open with Bookmarked..."
`(progn (find-file ,dir) (bookmark-set))
:visible (fboundp 'bookmark-set) :active t :help "Open and Add to Bookmarks")
(vector "Open in File Browser"
`(,poplife-func-find-file-by-default-app ,dir)
:visible t
:active t
:help dir))))
map)
(push (vector ".." ; Item to open parent directory.
`(let ((poplife-file-recursive ,poplife-file-recursive)
(poplife-func-find-file (quote ,poplife-func-find-file)))
(poplife-find-dir ,parent-dir ,submenu))
:active t :help parent-dir)
map)
(setq base-dir (replace-regexp-in-string "^@" "at" base-dir t t))
(cons base-dir map)))
;; (let ((foo (poplife-dir-easymap "~/.emacs.d"))) (describe-variable 'foo))
;; (let ((foo (poplife-dir-easymap "~/.emacs.d" t))) (describe-variable 'foo))
;; (popup-menu (poplife-dir-easymap "~/"))
\f
;;; Util
(defun poplife-func-switch-to-buffer ()
"Return switch-to-buffer function that corresponds to `poplife-func-find-file'."
(cdr (assoc poplife-func-find-file
'((find-file . switch-to-buffer)
(find-file-other-window . switch-to-buffer-other-window)
(find-file-other-frame . switch-to-buffer-other-frame)))))
;; (let ((foo (poplife-func-switch-to-buffer))) (describe-variable 'foo))
(defun poplife-find-dir (dir &optional submenu)
"Visit directory DIR using `popup-menu'.
When SUBMENU is non-nil, this offers multiple actions."
;; (interactive (list (read-directory-name "Find directory: ")))
(popup-menu (poplife-dir-easymap dir submenu)
(popup-menu-normalize-position last-nonmenu-event)))
(defun poplife-find-location (file)
"Visit directory that contains FILE."
(cond
((eq system-type 'darwin)
;; Select file in Finder.
(ns-do-applescript
(format "tell application \"Finder\"
set thePath to POSIX file \"%s\" as string
activate
reveal thePath
end tell" file)))
((eq system-type 'windows-nt)
;; Select file in File Explore.
(w32-shell-execute "open" "explorer"
(concat "/e,/select,"
(poplife-convert-w32-filename file))))
((eq system-type 'gnu/linux)
;; Visit dir that contains file by default-app.
;; (start-process "select-file-by-nautilus" nil "nautilus" file)
(start-process "open-dir-by-xdg-open" nil "xdg-open" (file-name-directory file)))
(t
;; Select file in Dired
(dired-other-frame (file-name-directory file)) ; Visit dir that contains file
(dired-goto-file file)))) ; Move point to file
(defun poplife-convert-w32-filename (file-name)
"Mirror slash characters in file names into backslashes."
;; https://debbugs.gnu.org/cgi/bugreport.cgi?bug=24387
;; https://debbugs.gnu.org/cgi/bugreport.cgi?bug=28883
(let ((start 0))
(while (string-match "/" file-name start)
(aset file-name (match-beginning 0) ?\\)
(setq start (match-end 0)))
file-name))
(defun poplife-find-file-by-default-app (file)
"Visit FILE by default application or default file browser."
(when (plist-get poplife-edit-cottager :recentf)
(recentf-push file))
(cond
((eq system-type 'gnu/linux)
(start-process "find-file-by-default-app" nil "xdg-open" file)) ; Visit file by default-app
((eq system-type 'darwin)
(start-process "find-file-by-default-app" nil "open" file)) ; Visit file by default-app
((eq system-type 'cygwin)
(start-process "find-file-by-default-app" nil "cygstart" file)) ; Visit file by default-app
((eq system-type 'windows-nt)
(w32-shell-execute "open" "explorer" (poplife-convert-w32-filename file))) ; visit file by default-app
(t
(find-file-other-frame file))))
(defun poplife-url-on-click-easymap (event)
"Define easymenu of an URL that is under mouse click EVENT.
The URL is identified by `thing-at-point-url-at-point'."
(save-excursion
(mouse-set-point event)
;; https://www.gnu.org/software/emacs/
(let ((url (or (thing-at-point-url-at-point t)
(get-text-property (point) 'shr-url)
(get-text-property (point) 'image-url))))
(when url
(list url
(vector "Open"
`(eww ,url)
:visible t :active t :help url)
["--" ignore]
(vector "Copy Link Location"
`(kill-new ,url)
:visible t :active t :help url)
(vector "Open in Other Window"
;; eww-browse-url, eww-open-in-new-buffer
`(progn
(switch-to-buffer-other-window (generate-new-buffer "*eww*"))
(eww-mode)
(eww ,url))
:visible t :active t :help url)
(vector "Open in Frame"
`(progn
(switch-to-buffer-other-frame (generate-new-buffer "*eww*"))
(eww-mode)
(eww ,url))
:visible t :active t :help url)
(vector "Open by Default App"
`(let ((browse-url-browser-function 'browse-url-default-browser))
(browse-url ,url))
:visible t
:active t
:help url))))))
(provide 'poplife)
;;; poplife.el ends here
^ permalink raw reply [flat|nested] 50+ messages in thread
* RE: poplife-mode
2017-11-05 1:00 poplife-mode Tak Kunihiro
@ 2017-11-05 5:52 ` Drew Adams
2017-11-11 12:47 ` poplife-mode Charles A. Roelli
1 sibling, 0 replies; 50+ messages in thread
From: Drew Adams @ 2017-11-05 5:52 UTC (permalink / raw)
To: Tak Kunihiro, emacs-devel
> With following line, one can cut and paste text using a pop-up menu
> triggered by right click.
> (define-key global-map [mouse-3] menu-bar-edit-menu)
>
> I noticed that menu-bar items that lead visiting files, buffers,
> frames, bookmarks, and recentf can be gathered into a pop-up menu.
>
> I wrote a minor mode `poplife' that provides an integrated pop-up menu
> triggered by right click. Also this minor mode offers contextual
> pop-up menus. When a thing under mouse click is file/directory, word,
> and url, this provides pop-up menus of list of files, candidates of
> words, and url-opening-menu, respectively.
>
> (require 'poplife)
> (setq poplife-word-flag t)
> (setq poplife-url-flag t)
> (setq poplife-edit-cottager '(:imenu t :buffer t :frame t :bookmark t
> :recentf t))
> (poplife-mode 1)
>
> Contextual pop-up menu by right click is very common interface
> nowadays and I propose to include this (or something like this) to Emacs.
Related:
https://www.emacswiki.org/emacs/Mouse3 (description, screenshots)
https://www.emacswiki.org/emacs/download/mouse3.el (code)
Examples of specialized use:
* `*Completions*' window - actions on candidates and general actions:
https://www.emacswiki.org/emacs/Icicles_-_Screenshots#CompletionPopupMenu
* Dired - two menus, single file or region of file names:
https://www.emacswiki.org/emacs/DiredPlus#RegionMenuWithMouse3Library
^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: poplife-mode
2017-11-05 1:00 poplife-mode Tak Kunihiro
2017-11-05 5:52 ` poplife-mode Drew Adams
@ 2017-11-11 12:47 ` Charles A. Roelli
2017-11-11 15:01 ` poplife-mode Stefan Monnier
[not found] ` <<jwvy3ncx3kx.fsf-monnier+gmane.emacs.devel@gnu.org>
1 sibling, 2 replies; 50+ messages in thread
From: Charles A. Roelli @ 2017-11-11 12:47 UTC (permalink / raw)
To: Tak Kunihiro; +Cc: tkk, emacs-devel
> From: Tak Kunihiro <tkk@misasa.okayama-u.ac.jp>
> Date: Sun, 5 Nov 2017 10:00:06 +0900
>
> With following line, one can cut and paste text using a pop-up menu
> triggered by right click.
>
> (define-key global-map [mouse-3] menu-bar-edit-menu)
>
> I noticed that menu-bar items that lead visiting files, buffers,
> frames, bookmarks, and recentf can be gathered into a pop-up menu.
>
> I wrote a minor mode `poplife' that provides an integrated pop-up menu
> triggered by right click. Also this minor mode offers contextual
> pop-up menus. When a thing under mouse click is file/directory, word,
> and url, this provides pop-up menus of list of files, candidates of
> words, and url-opening-menu, respectively.
>
> (require 'poplife)
> (setq poplife-word-flag t)
> (setq poplife-url-flag t)
> (setq poplife-edit-cottager '(:imenu t :buffer t :frame t :bookmark t :recentf t))
> (poplife-mode 1)
>
> Contextual pop-up menu by right click is very common interface
> nowadays and I propose to include this (or something like this) to
> Emacs.
I also hope we can include something like this in Emacs one day. But
I would not want to usurp the current binding of mouse-3, which is
handy in its own right. We could instead trigger the pop-up menu by,
for example, depressing both mouse buttons (mouse-1 and mouse-3) at
the same time. This feature is apparently already used on the Windows
build to fake a mouse-2 event using a mouse that does not have a third
button:
The variable ‘w32-mouse-button-tolerance’ specifies the time
interval, in milliseconds, for faking middle mouse button press on
2-button mice. If both mouse buttons are depressed within this time
interval, Emacs generates a middle mouse button click event instead of a
double click on one of the buttons.
from (emacs) Windows Mouse
But maybe it would not be ideal, especially since we don't yet have a
notation for pressing two keys at once.
Also, I would recommend to file a bug for your suggestion so that we
can better keep track of it. Even if such a feature is not added
right away, the discussion can be useful many years later.
^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: poplife-mode
2017-11-11 12:47 ` poplife-mode Charles A. Roelli
@ 2017-11-11 15:01 ` Stefan Monnier
2017-11-12 13:55 ` poplife-mode Charles A. Roelli
[not found] ` <<jwvy3ncx3kx.fsf-monnier+gmane.emacs.devel@gnu.org>
1 sibling, 1 reply; 50+ messages in thread
From: Stefan Monnier @ 2017-11-11 15:01 UTC (permalink / raw)
To: emacs-devel
> I also hope we can include something like this in Emacs one day. But
> I would not want to usurp the current binding of mouse-3, which is
> handy in its own right. We could instead trigger the pop-up menu by,
Have you tried C-mouse-3? It already offers something similar, so it
would make sense to tweak it do what the OP needs.
Stefan
^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: poplife-mode
2017-11-11 15:01 ` poplife-mode Stefan Monnier
@ 2017-11-12 13:55 ` Charles A. Roelli
2017-11-12 16:46 ` poplife-mode Stefan Monnier
0 siblings, 1 reply; 50+ messages in thread
From: Charles A. Roelli @ 2017-11-12 13:55 UTC (permalink / raw)
To: Stefan Monnier; +Cc: tkk, drew.adams, emacs-devel
> From: Stefan Monnier <monnier@iro.umontreal.ca>
> Date: Sat, 11 Nov 2017 10:01:29 -0500
>
> > I also hope we can include something like this in Emacs one day. But
> > I would not want to usurp the current binding of mouse-3, which is
> > handy in its own right. We could instead trigger the pop-up menu by,
>
> Have you tried C-mouse-3? It already offers something similar, so it
> would make sense to tweak it do what the OP needs.
That could work. I'd still rather not require both a hand on the
keyboard and the mouse to pop up a contextual menu, though.
I just read up on how Drew's library `mouse3' solves the problem. If
I understood it right, it redefines mouse-save-then-kill (mouse-3's
normal binding) to respond differently to either a double-click of
mouse-3 or two single-clicks of mouse-3 in the same spot. A
double-click kills the region as it usually does, whereas two
single-clicks pop up a contextual menu with menu items based on either
the "thing at point" (if no region is selected) or the selected
region. This also seems like o good solution.
^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: poplife-mode
2017-11-12 13:55 ` poplife-mode Charles A. Roelli
@ 2017-11-12 16:46 ` Stefan Monnier
2017-11-12 16:54 ` poplife-mode Eli Zaretskii
` (3 more replies)
0 siblings, 4 replies; 50+ messages in thread
From: Stefan Monnier @ 2017-11-12 16:46 UTC (permalink / raw)
To: emacs-devel
> I just read up on how Drew's library `mouse3' solves the problem. If
> I understood it right, it redefines mouse-save-then-kill (mouse-3's
> normal binding) to respond differently to either a double-click of
> mouse-3 or two single-clicks of mouse-3 in the same spot. A
> double-click kills the region as it usually does, whereas two
> single-clicks pop up a contextual menu with menu items based on either
> the "thing at point" (if no region is selected) or the selected
> region. This also seems like o good solution.
FWIW, I think a better UI is to pop a menu for a "long press".
I.e. bind it to down-mouse-3 but wait a little and if there's not been
any "mouse-up" event with 1s or so, then pop up the contextual menu.
I think this should actually be provided in core: down-mouse-3 should be
bound to a command implementing this, with some standardized way to find
a contextual menu (looking at local char-properties, and if not
found, buffer-local variable).
Stefan
^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: poplife-mode
2017-11-12 16:46 ` poplife-mode Stefan Monnier
@ 2017-11-12 16:54 ` Eli Zaretskii
2017-11-12 17:47 ` poplife-mode Stefan Monnier
2017-11-12 18:06 ` poplife-mode Stefan Monnier
` (2 subsequent siblings)
3 siblings, 1 reply; 50+ messages in thread
From: Eli Zaretskii @ 2017-11-12 16:54 UTC (permalink / raw)
To: Stefan Monnier; +Cc: emacs-devel
> From: Stefan Monnier <monnier@iro.umontreal.ca>
> Date: Sun, 12 Nov 2017 11:46:50 -0500
>
> FWIW, I think a better UI is to pop a menu for a "long press".
> I.e. bind it to down-mouse-3 but wait a little and if there's not been
> any "mouse-up" event with 1s or so, then pop up the contextual menu.
Is it a good idea to invent a UI that is unlike anything out there in
any other GUI application, at least AFAIK? Last time Emacs did that
there was no other app around, but not so nowadays...
^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: poplife-mode
2017-11-12 16:54 ` poplife-mode Eli Zaretskii
@ 2017-11-12 17:47 ` Stefan Monnier
2017-11-12 19:17 ` poplife-mode Yuri Khan
0 siblings, 1 reply; 50+ messages in thread
From: Stefan Monnier @ 2017-11-12 17:47 UTC (permalink / raw)
To: emacs-devel
> Is it a good idea to invent a UI that is unlike anything out there in
> any other GUI application, at least AFAIK? Last time Emacs did that
> there was no other app around, but not so nowadays...
AFAIK "long click brings up a context menu" was used in macOS some years
ago (no idea if it is still used), so it's not a completely new idea.
The only existing standard I know for context menus is to use mouse-3,
but that clashes with existing Emacs behavior. Of course, we could
simply drop that existing Emacs behavior.
Stefan
^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: poplife-mode
2017-11-12 17:47 ` poplife-mode Stefan Monnier
@ 2017-11-12 19:17 ` Yuri Khan
2017-11-12 20:32 ` poplife-mode Charles A. Roelli
2017-11-12 20:36 ` poplife-mode Stefan Monnier
0 siblings, 2 replies; 50+ messages in thread
From: Yuri Khan @ 2017-11-12 19:17 UTC (permalink / raw)
To: Stefan Monnier; +Cc: Emacs developers
On Mon, Nov 13, 2017 at 12:47 AM, Stefan Monnier
<monnier@iro.umontreal.ca> wrote:
>> Is it a good idea to invent a UI that is unlike anything out there in
>> any other GUI application, at least AFAIK? Last time Emacs did that
>> there was no other app around, but not so nowadays...
>
> AFAIK "long click brings up a context menu" was used in macOS some years
> ago (no idea if it is still used), so it's not a completely new idea.
Also, on mobile devices (starting at least as far back as Pocket PC
around 2002), as a poor man’s substitute for secondary mouse button
click. Inefficient as hell, since instead of just clicking a button
you have to hold your finger until the timeout elapses and watch the
little ring around your cursor fill.
> The only existing standard I know for context menus is to use mouse-3,
> but that clashes with existing Emacs behavior. Of course, we could
> simply drop that existing Emacs behavior.
Those same applications that show a context menu on the secondary
mouse button click also select a region on Shift+primary click.
Emacs as is:
* <mouse-3> marks region, one more <mouse-3> at the same position kills it
* <S-mouse-1> pops up buffer appearance menu
Emacs mimicking other applications could do this:
* <mouse-3> pops up context menu which includes buffer appearance as
part or submenu
* <S-mouse-1> marks region, one more <S-mouse-1> at the same position kills it
^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: poplife-mode
2017-11-12 19:17 ` poplife-mode Yuri Khan
@ 2017-11-12 20:32 ` Charles A. Roelli
2017-11-12 20:36 ` poplife-mode Stefan Monnier
1 sibling, 0 replies; 50+ messages in thread
From: Charles A. Roelli @ 2017-11-12 20:32 UTC (permalink / raw)
To: Yuri Khan; +Cc: monnier, emacs-devel
> From: Yuri Khan <yuri.v.khan@gmail.com>
> Date: Mon, 13 Nov 2017 02:17:14 +0700
>
> On Mon, Nov 13, 2017 at 12:47 AM, Stefan Monnier
> <monnier@iro.umontreal.ca> wrote:
> >> Is it a good idea to invent a UI that is unlike anything out there in
> >> any other GUI application, at least AFAIK? Last time Emacs did that
> >> there was no other app around, but not so nowadays...
> >
> > AFAIK "long click brings up a context menu" was used in macOS some years
> > ago (no idea if it is still used), so it's not a completely new idea.
>
> Also, on mobile devices (starting at least as far back as Pocket PC
> around 2002), as a poor man’s substitute for secondary mouse button
> click. Inefficient as hell, since instead of just clicking a button
> you have to hold your finger until the timeout elapses and watch the
> little ring around your cursor fill.
Those were the days! But in contrast, 450 ms is not long to wait for
a context menu, as you can test in Stefan's patch.
> > The only existing standard I know for context menus is to use mouse-3,
> > but that clashes with existing Emacs behavior. Of course, we could
> > simply drop that existing Emacs behavior.
>
> Those same applications that show a context menu on the secondary
> mouse button click also select a region on Shift+primary click.
>
> Emacs as is:
>
> * <mouse-3> marks region, one more <mouse-3> at the same position kills it
> * <S-mouse-1> pops up buffer appearance menu
>
> Emacs mimicking other applications could do this:
>
> * <mouse-3> pops up context menu which includes buffer appearance as
> part or submenu
> * <S-mouse-1> marks region, one more <S-mouse-1> at the same position kills it
Actually, in Emacs under macOS, S-mouse-1 already runs
mouse-save-then-kill, as mouse-3 (and the buffer appearance menu is by
default not accessible, I think). It was apparently done to maintain
consistency with other macOS apps.
^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: poplife-mode
2017-11-12 19:17 ` poplife-mode Yuri Khan
2017-11-12 20:32 ` poplife-mode Charles A. Roelli
@ 2017-11-12 20:36 ` Stefan Monnier
2017-11-13 5:03 ` poplife-mode Yuri Khan
1 sibling, 1 reply; 50+ messages in thread
From: Stefan Monnier @ 2017-11-12 20:36 UTC (permalink / raw)
To: emacs-devel
> * <S-mouse-1> marks region,
Could you explain what that means. S-mouse-1 is a punctual event, so
I don't see how it can delimit a region. Or do you mean like current
mouse-3 (i.e. places the mark where you click and activate it)?
Stefan
^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: poplife-mode
2017-11-12 20:36 ` poplife-mode Stefan Monnier
@ 2017-11-13 5:03 ` Yuri Khan
0 siblings, 0 replies; 50+ messages in thread
From: Yuri Khan @ 2017-11-13 5:03 UTC (permalink / raw)
To: Stefan Monnier; +Cc: Emacs developers
On Mon, Nov 13, 2017 at 3:36 AM, Stefan Monnier
<monnier@iro.umontreal.ca> wrote:
>> * <S-mouse-1> marks region,
>
> Could you explain what that means. S-mouse-1 is a punctual event, so
> I don't see how it can delimit a region. Or do you mean like current
> mouse-3 (i.e. places the mark where you click and activate it)?
Similar to current mouse-3, yes.
More precisely: (1) if there is no region active, put mark where point
is, otherwise leave mark where it is; (2) move point to where you
click; (3) activate mark.
^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: poplife-mode
2017-11-12 16:46 ` poplife-mode Stefan Monnier
2017-11-12 16:54 ` poplife-mode Eli Zaretskii
@ 2017-11-12 18:06 ` Stefan Monnier
2017-11-12 20:24 ` poplife-mode Charles A. Roelli
2017-11-13 1:36 ` poplife-mode Drew Adams
2017-11-13 3:40 ` poplife-mode Drew Adams
3 siblings, 1 reply; 50+ messages in thread
From: Stefan Monnier @ 2017-11-12 18:06 UTC (permalink / raw)
To: emacs-devel
> I think this should actually be provided in core: down-mouse-3 should be
> bound to a command implementing this, with some standardized way to find
> a contextual menu (looking at local char-properties, and if not
> found, buffer-local variable).
Maybe with something like the patch below.
Stefan
diff --git a/lisp/mouse.el b/lisp/mouse.el
index 5eeee1ec52..90357806a1 100644
--- a/lisp/mouse.el
+++ b/lisp/mouse.el
@@ -50,10 +49,15 @@ mouse-drag-copy-region
This affects `mouse-save-then-kill' (\\[mouse-save-then-kill]) in
addition to mouse drags."
:type 'boolean
- :version "24.1"
- :group 'mouse)
+ :version "24.1")
+
+(defcustom mouse-long-click-time 450
+ "Time after which a click is considered long.")
-(defcustom mouse-1-click-follows-link 450
+(defcustom mouse-1-click-follows-link
+ ;; FIXME: Maybe values 1 and -1 should be used to mean
+ ;; "use mouse-long-click-time".
+ mouse-long-click-time
"Non-nil means that clicking Mouse-1 on a link follows the link.
With the default setting, an ordinary Mouse-1 click on a link
@@ -2455,12 +2451,22 @@ function-key-map
(if (not (eq system-type 'ms-dos))
(global-set-key [S-down-mouse-1] 'mouse-appearance-menu))
;; C-down-mouse-2 is bound in facemenu.el.
-(global-set-key [C-down-mouse-3]
- `(menu-item ,(purecopy "Menu Bar") ignore
- :filter (lambda (_)
- (if (zerop (or (frame-parameter nil 'menu-bar-lines) 0))
- (mouse-menu-bar-map)
- (mouse-menu-major-mode-map)))))
+(let ((default-context-menu
+ `(menu-item ,(purecopy "Menu Bar") ignore
+ :filter (lambda (_)
+ (if (zerop (or (frame-parameter nil 'menu-bar-lines) 0))
+ (mouse-menu-bar-map)
+ (mouse-menu-major-mode-map))))))
+ (global-set-key [C-down-mouse-3] default-context-menu)
+ (global-set-key [context-menu] default-context-menu))
+
+(global-set-key [down-mouse-3] #'mouse-maybe-context-menu)
+(defun mouse-maybe-context-menu (event)
+ "Bring up a context menu for a long click.
+See `mouse-long-click-time' and `mouse-context-menu-function'."
+ (interactive "@e")
+ (if (sit-for (/ mouse-long-click-time 1000.0))
+ (push (cons 'context-menu (cdr event)) unread-command-events)))
;; Binding mouse-1 to mouse-select-window when on mode-, header-, or
;; vertical-line prevents Emacs from signaling an error when the mouse
^ permalink raw reply related [flat|nested] 50+ messages in thread
* Re: poplife-mode
2017-11-12 18:06 ` poplife-mode Stefan Monnier
@ 2017-11-12 20:24 ` Charles A. Roelli
2017-11-13 8:11 ` poplife-mode Tak Kunihiro
0 siblings, 1 reply; 50+ messages in thread
From: Charles A. Roelli @ 2017-11-12 20:24 UTC (permalink / raw)
To: Stefan Monnier; +Cc: emacs-devel
> From: Stefan Monnier <monnier@iro.umontreal.ca>
> Date: Sun, 12 Nov 2017 13:06:56 -0500
>
> > I think this should actually be provided in core: down-mouse-3 should be
> > bound to a command implementing this, with some standardized way to find
> > a contextual menu (looking at local char-properties, and if not
> > found, buffer-local variable).
>
> Maybe with something like the patch below.
I like it. We have a lot of existing code that sort of begs for
better mouse integration (find-file-at-point, thing-at-point,
completions buffers, isearch highlights, s-expression/balanced
expression manipulation, dired listings, ...). I wonder what others
think.
^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: poplife-mode
2017-11-12 20:24 ` poplife-mode Charles A. Roelli
@ 2017-11-13 8:11 ` Tak Kunihiro
2017-11-13 14:36 ` poplife-mode Drew Adams
0 siblings, 1 reply; 50+ messages in thread
From: Tak Kunihiro @ 2017-11-13 8:11 UTC (permalink / raw)
To: Charles A. Roelli; +Cc: Stefan Monnier, emacs-devel
> I like it. We have a lot of existing code that sort of begs for
> better mouse integration (find-file-at-point, thing-at-point,
> completions buffers, isearch highlights, s-expression/balanced
> expression manipulation, dired listings, ...). I wonder what others
> think.
I like the long-click too.
I think that a context menu should be created from list of functions
because each person wants to have his own context menu. I suppose that
the list would look like below. Each function should return keymap or
nil. They will be evaluated in the order of the list. A function
should accept mouse EVENT, and return keymap or nil. The last candidate
should return valid keymap.
(defvar poplife-context-candidates
'(poplife-mouse-file-menu ; FILE menu
poplife-mouse-dir-menu ; DIR menu
poplife-mouse-word-menu ; WORD menu
poplife-mouse-url-menu ; URL menu
poplife-mouse-edit-menu)) ; EDIT menu (default)
(1) FILE menu -- Pop how-to-open-a-file menu. The file is detected
by find-file-at-point.
(2) DIR menu -- Pop files in a directory. The directory is detected
by find-file-at-point.
(3) WORD menu -- Pop words by #'flyspell-correct-word
when face of a word under a mouse is flyspell-incorrect.
(4) URL menu -- Pop how-to-open-an-url menu. The url is detected
by thing-at-point-url-at-point.
(5) EDIT menu -- Pop edit-menu with extra commands. This menu can be
gigantic.
Note that this is just an example.
^ permalink raw reply [flat|nested] 50+ messages in thread
* RE: poplife-mode
2017-11-13 8:11 ` poplife-mode Tak Kunihiro
@ 2017-11-13 14:36 ` Drew Adams
2017-11-13 23:03 ` poplife-mode Tak Kunihiro
0 siblings, 1 reply; 50+ messages in thread
From: Drew Adams @ 2017-11-13 14:36 UTC (permalink / raw)
To: Tak Kunihiro, charles; +Cc: emacs-devel
> I think that a context menu should be created from list of
> functions because each person wants to have his own context
> menu
Did you look at or try mouse3.el? It makes it very
easy to have your own contextual `mouse-3' menus,
whatever the context (a mode or anything else).
There are even two different ways to do define the
menu - choose whichever you want by a user option.
The default choice is to use keymaps to define the
menu. The other choice lets you use a definition
specific to `x-popup-menu'. The default choice is
more flexible.
https://www.emacswiki.org/emacs/Mouse3#LibraryMouse3
^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: poplife-mode
2017-11-13 14:36 ` poplife-mode Drew Adams
@ 2017-11-13 23:03 ` Tak Kunihiro
2017-11-14 0:48 ` poplife-mode Drew Adams
0 siblings, 1 reply; 50+ messages in thread
From: Tak Kunihiro @ 2017-11-13 23:03 UTC (permalink / raw)
To: Drew Adams; +Cc: Tak Kunihiro, charles, emacs-devel
>> I think that a context menu should be created from list of
>> functions because each person wants to have his own context
>> menu
>
> Did you look at or try mouse3.el? It makes it very
> easy to have your own contextual `mouse-3' menus,
> whatever the context (a mode or anything else).
Yes, I checked your mouse3. Actually I tried to import "Thing at
Pointer".
I meant it is good if one can call other possible key's definition (or
keymaps) before mouse3 as below.
(defvar context-candidates
'(poplife-mouse-file-menu ; FILE menu
poplife-mouse-dir-menu ; DIR menu
poplife-mouse-ispell-menu ; iSpell menu
poplife-mouse-url-menu ; URL menu
mouse3-region-menu ; REGION menu
mouse3-noregion-menu)) ; DEFAULT menu
^ permalink raw reply [flat|nested] 50+ messages in thread
* RE: poplife-mode
2017-11-13 23:03 ` poplife-mode Tak Kunihiro
@ 2017-11-14 0:48 ` Drew Adams
2017-11-14 23:26 ` poplife-mode Tak Kunihiro
0 siblings, 1 reply; 50+ messages in thread
From: Drew Adams @ 2017-11-14 0:48 UTC (permalink / raw)
To: Tak Kunihiro; +Cc: charles, emacs-devel
> >> I think that a context menu should be created from list of
> >> functions because each person wants to have his own context
> >> menu
> >
> > Did you look at or try mouse3.el? It makes it very
> > easy to have your own contextual `mouse-3' menus,
> > whatever the context (a mode or anything else).
>
> Yes, I checked your mouse3.
Thank you.
> Actually I tried to import "Thing at Pointer".
Not sure what that means.
> I meant it is good if one can call other possible key's definition (or
> keymaps) before mouse3 as below.
>
> (defvar context-candidates
> '(poplife-mouse-file-menu ; FILE menu
> poplife-mouse-dir-menu ; DIR menu
> poplife-mouse-ispell-menu ; iSpell menu
> poplife-mouse-url-menu ; URL menu
> mouse3-region-menu ; REGION menu
> mouse3-noregion-menu)) ; DEFAULT menu
You can incorporate any existing menus you want, with `mouse3.el'.
See how the current major-mode menu is incorporated, for example.
Or the menu-bar menus (all of them, under a menu `Menu Bar', when
the menu-bar itself is not visible).
To incorporate an existing menu, all you need is its keymap.
^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: poplife-mode
2017-11-14 0:48 ` poplife-mode Drew Adams
@ 2017-11-14 23:26 ` Tak Kunihiro
2017-11-14 23:40 ` poplife-mode Drew Adams
0 siblings, 1 reply; 50+ messages in thread
From: Tak Kunihiro @ 2017-11-14 23:26 UTC (permalink / raw)
To: Drew Adams; +Cc: Tak Kunihiro, charles, emacs-devel
> You can incorporate any existing menus you want, with `mouse3.el'.
>
> See how the current major-mode menu is incorporated, for example.
> Or the menu-bar menus (all of them, under a menu `Menu Bar', when
> the menu-bar itself is not visible).
>
> To incorporate an existing menu, all you need is its keymap.
I want to pop a keymap that is created dynamically such for directory
listing. To do so, functions that return keymap should be evaluated
sequentially.
I think IO of a function for context menu should accept event and return
a keymap or nil. As a result, a function that returns context-menu
would be written like below.
(global-set-key [mouse-3] 'context-menu)
(defun context-menu (event)
(interactive "e")
(or (poplife-mouse-file-menu event) ; FILE menu
(poplife-mouse-dir-menu event) ; DIR menu
(poplife-mouse-ispell-menu event) ; iSpell menu
(poplife-mouse-url-menu event) ; URL menu
(mouse3-region-menu event) ; region menu
(mouse3-noregion-menu event))) ; default menu
^ permalink raw reply [flat|nested] 50+ messages in thread
* RE: poplife-mode
2017-11-14 23:26 ` poplife-mode Tak Kunihiro
@ 2017-11-14 23:40 ` Drew Adams
0 siblings, 0 replies; 50+ messages in thread
From: Drew Adams @ 2017-11-14 23:40 UTC (permalink / raw)
To: Tak Kunihiro; +Cc: charles, emacs-devel
> > You can incorporate any existing menus you want, with `mouse3.el'.
> >
> > See how the current major-mode menu is incorporated, for example.
> > Or the menu-bar menus (all of them, under a menu `Menu Bar', when
> > the menu-bar itself is not visible).
> >
> > To incorporate an existing menu, all you need is its keymap.
>
> I want to pop a keymap that is created dynamically such for directory
> listing. To do so, functions that return keymap should be evaluated
> sequentially.
That shouldn't be hard to do with `mouse3.el'. Perhaps
it is enough to add a clause to the `cond' in function
`mouse3-region-popup-custom-entries'.
That function iterates over the value of option
`mouse3-region-popup-entries'. Currently it expects
an entry to be a keymap, a keymap variable, or
(SYMBOL menu-item NAME MENU-KEYMAP . KEYWORDS) or
(SYMBOL NAME . MENU-KEYMAP), with MENU-KEYMAP being a
keymap variable.
Adding a `cond' clause that checks for a function, and
invokes it to get the actual entry to test, might be
all that's needed.
^ permalink raw reply [flat|nested] 50+ messages in thread
* RE: poplife-mode
2017-11-12 16:46 ` poplife-mode Stefan Monnier
2017-11-12 16:54 ` poplife-mode Eli Zaretskii
2017-11-12 18:06 ` poplife-mode Stefan Monnier
@ 2017-11-13 1:36 ` Drew Adams
2017-11-13 3:40 ` poplife-mode Drew Adams
3 siblings, 0 replies; 50+ messages in thread
From: Drew Adams @ 2017-11-13 1:36 UTC (permalink / raw)
To: Stefan Monnier, emacs-devel
> > I just read up on how Drew's library `mouse3' solves the problem. If
> > I understood it right, it redefines mouse-save-then-kill (mouse-3's
> > normal binding) to respond differently to either a double-click of
> > mouse-3 or two single-clicks of mouse-3 in the same spot. A
> > double-click kills the region as it usually does, whereas two
> > single-clicks pop up a contextual menu with menu items based on either
> > the "thing at point" (if no region is selected) or the selected
> > region. This also seems like o good solution.
>
> FWIW, I think a better UI is to pop a menu for a "long press".
> I.e. bind it to down-mouse-3 but wait a little and if there's not been
> any "mouse-up" event with 1s or so, then pop up the contextual menu.
That is similar, yes. But in practice what happens (in my
experience) is that a second click follows, which might or
might not be quick enough to be considered a double-click.
IOW, a "faulty" double-click is handled by `mouse3.el'
as an extension of a successful/true double-click.
Since double-click for `mouse-3' kills the selected text,
if a region is active and the second click is not quick
enough to be the second part of a double-click, you can
still kill the text, by choosing `Kill', which is the
first item in the (default) menu provided by `mouse3.el'.
This is also a good way for users to discover the
possibilities of a mouse-3 contextual menu: stumble
on it by double-clicking too slowly (and choosing `Kill'
to finish it off). (Someone who clicks slowly or unevenly
might also be a particularly good candidate as someone who
appreciates being able to use the menu.)
Note too that with `mouse3.el' a second click of `mouse-3'
provides different menus, depending on whether the active
region is empty. If it is empty then the menu applies to
the mouse-click position (it is the same position for both
clicks). If the region is non-empty then the menu applies
to the region.
(Sure, that two-menu system could be transferred to the
long-mouse-3-press that you suggest instead.)
FWIW, I've never been a fan of of a
longer-press-means-different-behavior UI. My impression
(but I'm not a user of it) is that this behavior is clunky
in CUA-mode, for example.
Better, I think, to depend on the single timing that users
are alrady used to, which applies to all of their apps
equally, and which they have already configured if they
don't want the default delay: the double-click delay.
What I just said also echoes what Eli said about your
suggestion:
Is it a good idea to invent a UI that is unlike anything
out there in any other GUI application, at least AFAIK?
Last time Emacs did that there was no other app around,
but not so nowadays...
The double-click delay, on the other hand, is something
that pretty much everyone is used to.
> I think this should actually be provided in core: down-mouse-3 should be
> bound to a command implementing this, with some standardized way to find
> a contextual menu (looking at local char-properties, and if not
> found, buffer-local variable).
I don't think I can agree, here, if only because in some
contexts users/libraries end up defining a behavior for
`down-mouse-3', with an `ignore' behavior of `mouse-3',
and in other contexts (or other users or other libraries)
do the opposite: act upon `mouse-3' and ignore on
`down-mouse-3'. Even the platform can make a difference
in such a choice, IIRC.
In any case, there must be some way for users to opt out
of any such mouse-3 behavior. The behavior of `mouse3.el',
which is highly configurable, is 100% optional.
^ permalink raw reply [flat|nested] 50+ messages in thread
* RE: poplife-mode
2017-11-12 16:46 ` poplife-mode Stefan Monnier
` (2 preceding siblings ...)
2017-11-13 1:36 ` poplife-mode Drew Adams
@ 2017-11-13 3:40 ` Drew Adams
2017-11-13 4:06 ` poplife-mode Stefan Monnier
3 siblings, 1 reply; 50+ messages in thread
From: Drew Adams @ 2017-11-13 3:40 UTC (permalink / raw)
To: Stefan Monnier, emacs-devel
> > I just read up on how Drew's library `mouse3' solves the problem. If
> > I understood it right, it redefines mouse-save-then-kill (mouse-3's
> > normal binding) to respond differently to either a double-click of
> > mouse-3 or two single-clicks of mouse-3 in the same spot. A
> > double-click kills the region as it usually does, whereas two
> > single-clicks pop up a contextual menu with menu items based on either
> > the "thing at point" (if no region is selected) or the selected
> > region. This also seems like o good solution.
>
> FWIW, I think a better UI is to pop a menu for a "long press".
^^^^^^^^^^^
Why do you think so?
> I.e. bind it to down-mouse-3 but wait a little and if there's not been
> any "mouse-up" event with 1s or so, then pop up the contextual menu.
The active region is not visible as such until `mouse-3' is
released (the up event). So even if this could be made to
provide a menu for acting on the region, the region would
not be visible. A user could try to guess where its other
end is, but why?
The `mouse3.el' code intentionally provides for two menus:
* One for actions on the active region, or actions that
take it into account in some way.
* One for other actions, unrelated to the region. This
includes general actions and actions related to the
click position - for example, action on a thing-at-point.
^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: poplife-mode
2017-11-13 3:40 ` poplife-mode Drew Adams
@ 2017-11-13 4:06 ` Stefan Monnier
2017-11-13 14:36 ` poplife-mode Drew Adams
0 siblings, 1 reply; 50+ messages in thread
From: Stefan Monnier @ 2017-11-13 4:06 UTC (permalink / raw)
To: Drew Adams; +Cc: emacs-devel
>> I.e. bind it to down-mouse-3 but wait a little and if there's not been
>> any "mouse-up" event with 1s or so, then pop up the contextual menu.
> The active region is not visible as such until `mouse-3' is
> released (the up event).
It doesn't matter, in my UI suggestion.
You can either do:
(short) click => do good ol' mouse-save-then-kill
press-and-hold => pop up a contextual menu
> So even if this could be made to provide a menu for acting on the
> region, the region would not be visible.
It's visible if it was activated by an earlier command, of course.
E.g. "mouse-3" followed by "down-mouse-3".
> The `mouse3.el' code intentionally provides for two menus:
My suggestion doesn't attempt to provide that. It could provide a menu
whose content depends on whether the region is active (and whether the
click was made in the region), of course, but that's a bit different.
Stefan
^ permalink raw reply [flat|nested] 50+ messages in thread
* RE: poplife-mode
2017-11-13 4:06 ` poplife-mode Stefan Monnier
@ 2017-11-13 14:36 ` Drew Adams
2017-11-13 15:24 ` poplife-mode Stefan Monnier
0 siblings, 1 reply; 50+ messages in thread
From: Drew Adams @ 2017-11-13 14:36 UTC (permalink / raw)
To: Stefan Monnier; +Cc: emacs-devel
> >> I.e. bind it to down-mouse-3 but wait a little and if there's
> >> not been any "mouse-up" event with 1s or so, then pop up the
> >> contextual menu.
> >
> > The active region is not visible as such until `mouse-3'
> > is released (the up event).
>
> It doesn't matter, in my UI suggestion. You can either
> do: (short) click => do good ol' mouse-save-then-kill
> press-and-hold => pop up a contextual menu
The point was not about simply killing the region text.
Of course you can kill it using a single, normal click.
That's true of `mouse3.el', as well. That's nothing new.
The point was about being able to act on the active
region in other ways, with a contextual menu appropriate
to the region being active.
(Being able to. Nothing _requires_ you to have a menu
that is sensitive to the region being active.)
Again: the region is not highlighted until `mouse-3'
is released (up event). You should be able to see
the region if you intend to act on it.
> > So even if this could be made to provide a menu for
> > acting on the region, the region would not be visible.
>
> It's visible if it was activated by an earlier command,
> of course. E.g. "mouse-3" followed by "down-mouse-3".
Pressing and holding down `mouse-3' does _not_ highlight
the region. That happens only when `mouse-3' is released.
If you mean first click `mouse-3' (press and release)
and then press and hold `mouse-3', then you are talking
about _two_ `mouse-3' clicks (it will be released) -
similar to what `mouse3.el' does.
Besides not highlighting the region that is active and
can be acted on, your approach has the disadvantage of
mistakenly killing the region when an intended long
press happens to be a bit too short.
With the `mouse3.el' approach you can't mistakenly
kill the region. Instead, the menu is available if
you mistakenly click too slowly, giving you another
chance to kill the region. IOW, it's the other way
around.
> > The `mouse3.el' code intentionally provides for
> > two menus:
> > * One for actions on the active region...
> > * One for other actions...
>
> My suggestion doesn't attempt to provide that.
Right. Nothing to reflect/distinguish the context
of the region being active.
So again:
>> I think a better UI is to pop a menu for a "long press".
> ^^^^^^^^^^^
> Why do you think so?
What's better about it?
^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: poplife-mode
2017-11-13 14:36 ` poplife-mode Drew Adams
@ 2017-11-13 15:24 ` Stefan Monnier
2017-11-13 17:08 ` poplife-mode Drew Adams
2017-11-13 23:16 ` poplife-mode Tak Kunihiro
0 siblings, 2 replies; 50+ messages in thread
From: Stefan Monnier @ 2017-11-13 15:24 UTC (permalink / raw)
To: emacs-devel
>> It's visible if it was activated by an earlier command,
>> of course. E.g. "mouse-3" followed by "down-mouse-3".
> Pressing and holding down `mouse-3' does _not_ highlight
> the region. That happens only when `mouse-3' is released.
`mouse-3` is an "up", so it implies releasing the button.
> If you mean first click `mouse-3' (press and release)
> and then press and hold `mouse-3',
That's right.
> then you are talking about _two_ `mouse-3' clicks (it will be
> released) - similar to what `mouse3.el' does.
But that's only if you want to use the `mouse-3` event first.
My suggestion is mostly about providing *another* operation on that same
button (I expect it will rarely be used together with a mouse-3 event
(i.e. with mouse-save-then-kill)).
> Besides not highlighting the region that is active and
> can be acted on, your approach has the disadvantage of
> mistakenly killing the region when an intended long
> press happens to be a bit too short.
This risk only exists in the case you use down-mouse-3 right after
mouse-3, which I expect will be rare.
And from where I stand, a too-short click is *very* unlikely: the user will
simply down-mouse-3 and "wait for the menu to appear" (as opposed to
"wait 450ms"). And this user will even keep the button pressed
significantly longer: he will only release the button after selecting
the entry he's interested in.
> What's better about it?
No need to double click, hence (except for a 450ms delay) it behaves
just like the "standard" context menu of other applications.
Stefan
^ permalink raw reply [flat|nested] 50+ messages in thread
* RE: poplife-mode
2017-11-13 15:24 ` poplife-mode Stefan Monnier
@ 2017-11-13 17:08 ` Drew Adams
2017-11-13 20:20 ` poplife-mode Stefan Monnier
2017-11-13 23:16 ` poplife-mode Tak Kunihiro
1 sibling, 1 reply; 50+ messages in thread
From: Drew Adams @ 2017-11-13 17:08 UTC (permalink / raw)
To: Stefan Monnier, emacs-devel
> >> It's visible if it was activated by an earlier command,
> >> of course. E.g. "mouse-3" followed by "down-mouse-3".
> > Pressing and holding down `mouse-3' does _not_ highlight
> > the region. That happens only when `mouse-3' is released.
>
> `mouse-3` is an "up", so it implies releasing the button.
Sure - when we mean the _event_. `mouse-3' is also the
name of the button - as in "pressing and holding down
`mouse-3'. If that wasn't clear, please reread what I
wrote, substituting "3rd mouse button" for such occurrences.
> > If you mean first click `mouse-3' (press and release)
> > and then press and hold `mouse-3',
>
> That's right.
>
> > then you are talking about _two_ `mouse-3' clicks (it will be
> > released) - similar to what `mouse3.el' does.
>
> But that's only if you want to use the `mouse-3` event first.
> My suggestion is mostly about providing *another* operation on that same
> button (I expect it will rarely be used together with a mouse-3 event
> (i.e. with mouse-save-then-kill)).
Not sure what you are trying to say. You seemed to be
saying that the region is highlighted with your feature
also. My point was that the region is highlighted only
after the button is release, which is as many clicks
with your approach as with the mouse3.el approach (which
shows the menu upon button release, not upon long press).
With your approach, simply pressing and holding the button
down a long time will show the menu, but it won't highlight
the region. So it is not appropriate for menu items that
act on the region or otherwise take the region into account.
> > Besides not highlighting the region that is active and
> > can be acted on, your approach has the disadvantage of
> > mistakenly killing the region when an intended long
> > press happens to be a bit too short.
>
> This risk only exists in the case you use down-mouse-3
> right after mouse-3, which I expect will be rare.
AFAICT, it's the only way, with your approach, to see
the region you will act on get highlighted. Are you
relegating your approach to menus that don't have items
that act on the region?
> > What's better about it?
>
> No need to double click, hence (except for a 450ms delay)
As I pointed out, there is just as much need to click twice,
if you want to see the region. (It's not a double-click
event in either case; it's two click events in both cases.)
> it behaves just like the "standard" context menu of other
> applications.
At least on MS Windows, the apps I use all show the
menu upon button-release, not upon button press. (And
press-and-hold is surely not standard for showing a menu
anywhere, is it?)
And if there is anywhere where a `mouse-3' menu is used
ubiquitously it is on Windows. Windows users are used to
`mouse-3' showing a context menu when it is clicked, not
when it is pressed and held.
So I'd say that the mouse3.el approach is at least as
"standard-context-menu"-like as your approach.
^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: poplife-mode
2017-11-13 17:08 ` poplife-mode Drew Adams
@ 2017-11-13 20:20 ` Stefan Monnier
2017-11-13 21:56 ` poplife-mode Drew Adams
2017-11-13 23:08 ` Changing default mouse bindings (was: poplife-mode) Alex
0 siblings, 2 replies; 50+ messages in thread
From: Stefan Monnier @ 2017-11-13 20:20 UTC (permalink / raw)
To: Drew Adams; +Cc: emacs-devel
> AFAICT, it's the only way, with your approach, to see
> the region you will act on get highlighted. Are you
> relegating your approach to menus that don't have items
> that act on the region?
My suggestion is for a context menu. I.e. a menu of things to apply
locally. Nothing specifically to do with the region. The region is but
one particular kind of "local" thing (and the down-mouse-3 event is not
necessarily placed near the region). I don't expect that the region
would/will be the main use of this functionality.
Stefan
^ permalink raw reply [flat|nested] 50+ messages in thread
* RE: poplife-mode
2017-11-13 20:20 ` poplife-mode Stefan Monnier
@ 2017-11-13 21:56 ` Drew Adams
2017-11-13 23:13 ` poplife-mode Stefan Monnier
2017-11-13 23:08 ` Changing default mouse bindings (was: poplife-mode) Alex
1 sibling, 1 reply; 50+ messages in thread
From: Drew Adams @ 2017-11-13 21:56 UTC (permalink / raw)
To: Stefan Monnier; +Cc: emacs-devel
> > AFAICT, it's the only way, with your approach, to see
> > the region you will act on get highlighted. Are you
> > relegating your approach to menus that don't have items
> > that act on the region?
>
> My suggestion is for a context menu. I.e. a menu of things to apply
> locally. Nothing specifically to do with the region. The region is but
> one particular kind of "local" thing (and the down-mouse-3 event is not
> necessarily placed near the region). I don't expect that the region
> would/will be the main use of this functionality.
I don't think acting on the region should be the _only_
use of a mouse-3 contextual menu, by any means. That's
why mouse3.el, by default, gives you a non-region-oriented
menu if the region is not active and non-empty. And you
can use any menus whatsoever - the menu to use in any
given context need not have anything to do with the region.
If option `mouse3-popup-include-global-menus-flag'
is non-nil, which it is by default, the mouse-3 menu
starts with the major-mode menu (or the `Menu Bar' menus
if the menu-bar is not visible). And that comes first
in the mouse-3 menu. So clearly there is nothing that
requires the menus to be related to the region.
But the general use of mouse-3 in Emacs is to act on the
region (extend, restrict, cut). It makes sense, I think,
to at least provide for acting on the active region, and
be able to see it highlighted before doing so.
With mouse3.el, the menu that pops up when the region is
active is titled `Region', to point out that the current
context is one where the region is active. Menu items
that make sense when the region is active are in general
natural candidates for that context.
When the region is empty or inactive, the menu title
is `No Region'. But it is trivial to make these menu
titles customizable or to have only one mouse-3 menu
in any given context, regardless of whether the region
is active.
^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: poplife-mode
2017-11-13 21:56 ` poplife-mode Drew Adams
@ 2017-11-13 23:13 ` Stefan Monnier
0 siblings, 0 replies; 50+ messages in thread
From: Stefan Monnier @ 2017-11-13 23:13 UTC (permalink / raw)
To: emacs-devel
> But the general use of mouse-3 in Emacs is to act on the
> region (extend, restrict, cut). It makes sense, I think,
> to at least provide for acting on the active region, and
> be able to see it highlighted before doing so.
I'm not claiming it doesn't make sense, but it's definitely not the
purpose of my suggestion. My only purpose is to provide a contextual
menu bound to the down-mouse-3 event like many other applications do,
and try to do so without getting in the way of the pre-existing uses of
`mouse-3` in Emacs.
To a large extent, the content of this contextual menu is nor
that important. I'd expect various applications to make use of it
(flyspell, xref, ...).
Stefan
^ permalink raw reply [flat|nested] 50+ messages in thread
* Changing default mouse bindings (was: poplife-mode)
2017-11-13 20:20 ` poplife-mode Stefan Monnier
2017-11-13 21:56 ` poplife-mode Drew Adams
@ 2017-11-13 23:08 ` Alex
2017-11-14 2:50 ` Changing default mouse bindings Stefan Monnier
` (2 more replies)
1 sibling, 3 replies; 50+ messages in thread
From: Alex @ 2017-11-13 23:08 UTC (permalink / raw)
To: Stefan Monnier; +Cc: Eli Zaretskii, John Wiegley, Drew Adams, emacs-devel
Stefan Monnier <monnier@iro.umontreal.ca> writes:
>> AFAICT, it's the only way, with your approach, to see
>> the region you will act on get highlighted. Are you
>> relegating your approach to menus that don't have items
>> that act on the region?
>
> My suggestion is for a context menu. I.e. a menu of things to apply
> locally. Nothing specifically to do with the region. The region is but
> one particular kind of "local" thing (and the down-mouse-3 event is not
> necessarily placed near the region). I don't expect that the region
> would/will be the main use of this functionality.
>
>
> Stefan
Is it completely out of the question to just bind right-click directly
to this context menu by default instead of using double clicks or long
clicks? If so, will it ever be considered? It would be a shame if
Emacs is never able to shed some of its old baggage.
Drew mentioned that this context menu is shown only on mouse release in
Windows (it's on the down event on my GTK system), so perhaps it should
be dependent on the system?
I understand being hesitant to change longstanding default bindings, but
I would imagine that most people that use the mouse would prefer more
"standard" mouse bindings; though without conducting a poll, this is of
course wild speculation.
Here are the two main changes that I think would make sense:
1. (down-)mouse-3 should open a context menu.
2. S-down-mouse-1 should extend the region as it does in many other
programs. If the non-standard kill behaviour is to be
kept, then S-down-mouse-1 could just be bound directly to
`mouse-save-then-kill', but it would have to be modified to handle a
down and drag events.
As for the old binding of S-down-mouse-1, its contents should probably
go in the menu-bar somewhere (perhaps in a new View menu as is common in
other programs).
Shift modified mouse clicks don't work in text terminals, so perhaps
this shouldn't happen in such terminals.
The above should still satisfy most use-cases that
`mouse-save-then-kill' satisfies (either with S-down-mouse-1 or by
dragging mouse-1 and selecting `cut' in the context menu), as well as
providing, with a "standard" UI, the common additional functionality
that context menus bring.
^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: Changing default mouse bindings
2017-11-13 23:08 ` Changing default mouse bindings (was: poplife-mode) Alex
@ 2017-11-14 2:50 ` Stefan Monnier
2017-11-14 7:07 ` Yuri Khan
` (3 more replies)
2017-11-14 20:26 ` Changing default mouse bindings (was: poplife-mode) Charles A. Roelli
2017-11-17 16:25 ` Sam Steingold
2 siblings, 4 replies; 50+ messages in thread
From: Stefan Monnier @ 2017-11-14 2:50 UTC (permalink / raw)
To: Alex; +Cc: Eli Zaretskii, John Wiegley, Drew Adams, emacs-devel
> Is it completely out of the question to just bind right-click directly
> to this context menu by default instead of using double clicks or long
> clicks?
I have no idea. My proposal was designed to avoid having to answer this
question ;-)
> Drew mentioned that this context menu is shown only on mouse release in
> Windows,
Sounds like a bug. I'd expect that it's easy to fix (tho I admittedly
have no experience with Emacs under Windows).
Stefan
^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: Changing default mouse bindings
2017-11-14 2:50 ` Changing default mouse bindings Stefan Monnier
@ 2017-11-14 7:07 ` Yuri Khan
2017-11-14 16:34 ` Stefan Monnier
2017-11-14 15:13 ` Eli Zaretskii
` (2 subsequent siblings)
3 siblings, 1 reply; 50+ messages in thread
From: Yuri Khan @ 2017-11-14 7:07 UTC (permalink / raw)
To: Stefan Monnier
Cc: Eli Zaretskii, John Wiegley, Drew Adams, Alex, Emacs developers
On Tue, Nov 14, 2017 at 9:50 AM, Stefan Monnier
<monnier@iro.umontreal.ca> wrote:
>> Drew mentioned that this context menu is shown only on mouse release in
>> Windows,
>
> Sounds like a bug. I'd expect that it's easy to fix (tho I admittedly
> have no experience with Emacs under Windows).
No, that sounds like a feature. In general, showing the context menu
on a mouse up makes it possible to perform several different gestures
of varying complexity:
* Simple secondary click: mouse down, followed by a movement not
exceeding a few pixels, followed by mouse up. This normally just shows
the context menu.
* Secondary drag-select: mouse down at a position A in text buffer,
followed by a movement across buffer text to another position B,
followed by mouse up. Normally selects a region spanning from A up to
B and shows the context menu applicable to it.
* Secondary drag-and-drop: mouse down within a marked region, followed
by movement to a position outside the region, possibly in a different
window, frame or application, followed by mouse up. Shows a menu that
offers multiple actions that could be done to the region and the
target position (move or copy text between buffers; move, copy, hard-
or symlink files across the file system; feed text or file as input to
a program).
* Mouse gestures: mouse down, followed by movement in a well-defined
geometric shape, followed by mouse up. The action performed then
depends on the shape of movement.
(Firefox 57 is scheduled to be released today. There is much wailing
and gnashing of teeth over not being able to use mouse gestures any
more because on GTK3/GNU/Linux and macOS the context menu pops up on
mouse down and the new extension model does not allow extensions to
override that.)
^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: Changing default mouse bindings
2017-11-14 7:07 ` Yuri Khan
@ 2017-11-14 16:34 ` Stefan Monnier
0 siblings, 0 replies; 50+ messages in thread
From: Stefan Monnier @ 2017-11-14 16:34 UTC (permalink / raw)
To: Yuri Khan; +Cc: Eli Zaretskii, John Wiegley, Drew Adams, Alex, Emacs developers
> No, that sounds like a feature. In general, showing the context menu
> on a mouse up makes it possible to perform several different gestures
> of varying complexity:
> * Simple secondary click: mouse down, followed by a movement not
> exceeding a few pixels, followed by mouse up. This normally just shows
> the context menu.
> * Secondary drag-select: mouse down at a position A in text buffer,
> followed by a movement across buffer text to another position B,
> followed by mouse up. Normally selects a region spanning from A up to
> B and shows the context menu applicable to it.
> * Secondary drag-and-drop: mouse down within a marked region, followed
> by movement to a position outside the region, possibly in a different
> window, frame or application, followed by mouse up. Shows a menu that
> offers multiple actions that could be done to the region and the
> target position (move or copy text between buffers; move, copy, hard-
> or symlink files across the file system; feed text or file as input to
> a program).
> * Mouse gestures: mouse down, followed by movement in a well-defined
> geometric shape, followed by mouse up. The action performed then
> depends on the shape of movement.
Funnily enough, that still leaves "mouse down, with (almost) no movement
and stay there for a while" unused so it can be used for a "context menu
on long-mouse-down".
Stefan
^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: Changing default mouse bindings
2017-11-14 2:50 ` Changing default mouse bindings Stefan Monnier
2017-11-14 7:07 ` Yuri Khan
@ 2017-11-14 15:13 ` Eli Zaretskii
2017-11-14 16:35 ` Stefan Monnier
[not found] ` <<838tf8lwqn.fsf@gnu.org>
[not found] ` <<<838tf8lwqn.fsf@gnu.org>
3 siblings, 1 reply; 50+ messages in thread
From: Eli Zaretskii @ 2017-11-14 15:13 UTC (permalink / raw)
To: Stefan Monnier; +Cc: johnw, drew.adams, agrambot, emacs-devel
> From: Stefan Monnier <monnier@iro.umontreal.ca>
> Cc: Drew Adams <drew.adams@oracle.com>, Eli Zaretskii <eliz@gnu.org>, "John Wiegley" <johnw@gnu.org>, emacs-devel@gnu.org
> Date: Mon, 13 Nov 2017 21:50:48 -0500
>
> > Drew mentioned that this context menu is shown only on mouse release in
> > Windows,
>
> Sounds like a bug. I'd expect that it's easy to fix (tho I admittedly
> have no experience with Emacs under Windows).
I think Drew was talking about other Windows applications, and I very
much doubt that we want to fix bugs in those ;-)
^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: Changing default mouse bindings
2017-11-14 15:13 ` Eli Zaretskii
@ 2017-11-14 16:35 ` Stefan Monnier
2017-11-14 16:38 ` Eli Zaretskii
0 siblings, 1 reply; 50+ messages in thread
From: Stefan Monnier @ 2017-11-14 16:35 UTC (permalink / raw)
To: Eli Zaretskii; +Cc: johnw, drew.adams, agrambot, emacs-devel
>> > Drew mentioned that this context menu is shown only on mouse release in
>> > Windows,
>> Sounds like a bug. I'd expect that it's easy to fix (tho I admittedly
>> have no experience with Emacs under Windows).
> I think Drew was talking about other Windows applications, and I very
> much doubt that we want to fix bugs in those ;-)
Aha, so the context menus are usually sown on `mouse-3` rather than on
`down-mouse-3` under Windows? Then indeed, I agree that using a "long
click" wouldn't work very well because the user will then train herself
to live close to the 450ms edge.
Stefan
^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: Changing default mouse bindings
2017-11-14 16:35 ` Stefan Monnier
@ 2017-11-14 16:38 ` Eli Zaretskii
0 siblings, 0 replies; 50+ messages in thread
From: Eli Zaretskii @ 2017-11-14 16:38 UTC (permalink / raw)
To: Stefan Monnier; +Cc: johnw, drew.adams, agrambot, emacs-devel
> From: Stefan Monnier <monnier@IRO.UMontreal.CA>
> Cc: agrambot@gmail.com, drew.adams@oracle.com, johnw@gnu.org,
> emacs-devel@gnu.org
> Date: Tue, 14 Nov 2017 11:35:31 -0500
>
> >> > Drew mentioned that this context menu is shown only on mouse release in
> >> > Windows,
> >> Sounds like a bug. I'd expect that it's easy to fix (tho I admittedly
> >> have no experience with Emacs under Windows).
> > I think Drew was talking about other Windows applications, and I very
> > much doubt that we want to fix bugs in those ;-)
>
> Aha, so the context menus are usually sown on `mouse-3` rather than on
> `down-mouse-3` under Windows?
As much as I could see, yes.
^ permalink raw reply [flat|nested] 50+ messages in thread
[parent not found: <<838tf8lwqn.fsf@gnu.org>]
* RE: Changing default mouse bindings
[not found] ` <<838tf8lwqn.fsf@gnu.org>
@ 2017-11-14 15:35 ` Drew Adams
2017-11-14 16:58 ` Eli Zaretskii
0 siblings, 1 reply; 50+ messages in thread
From: Drew Adams @ 2017-11-14 15:35 UTC (permalink / raw)
To: Eli Zaretskii, Stefan Monnier; +Cc: johnw, drew.adams, agrambot, emacs-devel
> > > Drew mentioned that this context menu is shown only on mouse release in
> > > Windows,
> >
> > Sounds like a bug. I'd expect that it's easy to fix (tho I admittedly
> > have no experience with Emacs under Windows).
>
> I think Drew was talking about other Windows applications,
> and I very much doubt that we want to fix bugs in those ;-)
Other Windows apps, AS WELL as Emacs, yes. Emacs fits
Windows here, which is what Windows users expect. See
also Yuri's list of reasons why displaying a contextual
menu on mouse-up instead of mouse-down makes sense.
(But I'm not proposing that we fix all the non-Windows
design-bugged behavior of showing the menu upon mouse-down
- at least not outside Emacs. ;-))
^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: Changing default mouse bindings
2017-11-14 15:35 ` Drew Adams
@ 2017-11-14 16:58 ` Eli Zaretskii
0 siblings, 0 replies; 50+ messages in thread
From: Eli Zaretskii @ 2017-11-14 16:58 UTC (permalink / raw)
To: Drew Adams; +Cc: johnw, monnier, agrambot, emacs-devel
> Date: Tue, 14 Nov 2017 07:35:38 -0800 (PST)
> From: Drew Adams <drew.adams@oracle.com>
> Cc: johnw@gnu.org, drew.adams@oracle.com, agrambot@gmail.com,
> emacs-devel@gnu.org
>
> > I think Drew was talking about other Windows applications,
> > and I very much doubt that we want to fix bugs in those ;-)
>
> Other Windows apps, AS WELL as Emacs, yes. Emacs fits
> Windows here, which is what Windows users expect.
No, in Emacs the menu pops up at down-mouse-3, at least by default.
E.g., try C-mouse-3 in "emacs -Q": the menu pops up even if you don't
release the button, and the echo area says "C-down-mouse-3-".
^ permalink raw reply [flat|nested] 50+ messages in thread
[parent not found: <<<838tf8lwqn.fsf@gnu.org>]
* Re: Changing default mouse bindings (was: poplife-mode)
2017-11-13 23:08 ` Changing default mouse bindings (was: poplife-mode) Alex
2017-11-14 2:50 ` Changing default mouse bindings Stefan Monnier
@ 2017-11-14 20:26 ` Charles A. Roelli
2017-11-14 23:11 ` Changing default mouse bindings Tak Kunihiro
2017-11-17 16:25 ` Sam Steingold
2 siblings, 1 reply; 50+ messages in thread
From: Charles A. Roelli @ 2017-11-14 20:26 UTC (permalink / raw)
To: Alex; +Cc: eliz, johnw, monnier, drew.adams, emacs-devel
> From: Alex <agrambot@gmail.com>
> Cc: Drew Adams <drew.adams@oracle.com>, Eli Zaretskii <eliz@gnu.org>,
> "John Wiegley" <johnw@gnu.org>, emacs-devel@gnu.org
> Date: Mon, 13 Nov 2017 17:08:12 -0600
>
> Stefan Monnier <monnier@iro.umontreal.ca> writes:
>
> >> AFAICT, it's the only way, with your approach, to see
> >> the region you will act on get highlighted. Are you
> >> relegating your approach to menus that don't have items
> >> that act on the region?
> >
> > My suggestion is for a context menu. I.e. a menu of things to apply
> > locally. Nothing specifically to do with the region. The region is but
> > one particular kind of "local" thing (and the down-mouse-3 event is not
> > necessarily placed near the region). I don't expect that the region
> > would/will be the main use of this functionality.
> >
> >
> > Stefan
>
> Is it completely out of the question to just bind right-click directly
> to this context menu by default instead of using double clicks or long
> clicks? If so, will it ever be considered? It would be a shame if
> Emacs is never able to shed some of its old baggage.
I hope it would be considered. Originally I thought it would be best
to work around the current bindings (via either the long press or
double click of mouse-3), but if we can instead provide multiple
functionalities with mouse-3 by differentiating between simple clicks
and drags as Yuri suggested, that could be an even better solution.
^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: Changing default mouse bindings
2017-11-14 20:26 ` Changing default mouse bindings (was: poplife-mode) Charles A. Roelli
@ 2017-11-14 23:11 ` Tak Kunihiro
2017-11-15 3:16 ` Stefan Monnier
0 siblings, 1 reply; 50+ messages in thread
From: Tak Kunihiro @ 2017-11-14 23:11 UTC (permalink / raw)
To: Charles A. Roelli; +Cc: johnw, emacs-devel, Alex, monnier, eliz, drew.adams
>> Is it completely out of the question to just bind right-click
>> directly to this context menu by default instead of using double
>> clicks or long clicks? If so, will it ever be considered? It would
>> be a shame if Emacs is never able to shed some of its old baggage.
>
> I hope it would be considered. Originally I thought it would be best
> to work around the current bindings (via either the long press or
> double click of mouse-3), but if we can instead provide multiple
> functionalities with mouse-3 by differentiating between simple clicks
> and drags as Yuri suggested, that could be an even better solution.
My proposal is before changing the default binding, to have minor mode
such like `poplife-mode' that provides the mouse-3 binding with a series
of context menu. I think context menu itself is as important as how to
trigger.
(define-minor-mode poplife-mode
"A global minor-mode to show context menu by right click."
:init-value nil
:global t
:keymap (let ((map (make-sparse-keymap))
(context-menu
`(menu-item "Context menu" poplife-context-menu
:filter ,(lambda (_) (poplife-context-menu (aref (this-command-keys) 0))))))
(define-key map [mouse-3] context-menu)
(define-key map [drag-mouse-3] context-menu)
(define-key map [C-down-mouse-1] 'ignore)
(define-key map [C-mouse-1] context-menu)
(define-key map [C-double-mouse-1] context-menu)
(define-key map [C-triple-mouse-1] context-menu)
(define-key map [C-drag-mouse-1] context-menu)
map))
^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: Changing default mouse bindings
2017-11-14 23:11 ` Changing default mouse bindings Tak Kunihiro
@ 2017-11-15 3:16 ` Stefan Monnier
2017-11-16 23:21 ` Tak Kunihiro
0 siblings, 1 reply; 50+ messages in thread
From: Stefan Monnier @ 2017-11-15 3:16 UTC (permalink / raw)
To: Tak Kunihiro
Cc: Charles A. Roelli, johnw, emacs-devel, Alex, eliz, drew.adams
> My proposal is before changing the default binding, to have minor mode
> such like `poplife-mode' that provides the mouse-3 binding with a series
> of context menu. I think context menu itself is as important as how to
> trigger.
I agree, there are two separate issues:
- define a context menu (i.e. provide ways for packages to control what
appears in the context menu).
- make it available via some binding.
Stefan
^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: Changing default mouse bindings
2017-11-15 3:16 ` Stefan Monnier
@ 2017-11-16 23:21 ` Tak Kunihiro
2017-11-17 7:23 ` Eli Zaretskii
[not found] ` <<838tf5id1e.fsf@gnu.org>
0 siblings, 2 replies; 50+ messages in thread
From: Tak Kunihiro @ 2017-11-16 23:21 UTC (permalink / raw)
To: Stefan Monnier
Cc: Charles A. Roelli, johnw, emacs-devel, Tak Kunihiro, Alex, eliz,
drew.adams
> I agree, there are two separate issues:
> - define a context menu (i.e. provide ways for packages to control what
> appears in the context menu).
> - make it available via some binding.
I think context menu would be created by something like below. To
discuss items for the default context-menu is the first step.
(global-set-key [mouse-3] 'mouse-context-menu)
(defun mouse-context-menu (event)
(interactive "e")
(or (poplife-mouse-dir-menu event) ; DIR menu
(poplife-mouse-url-menu event) ; URL menu
(mouse3-region-menu event) ; region menu
(mouse-context-menu-default event))) ; default menu <<<<<
I think mouse-context-menu-default should return selected items from
menu-bar-edit-menu.
^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: Changing default mouse bindings
2017-11-16 23:21 ` Tak Kunihiro
@ 2017-11-17 7:23 ` Eli Zaretskii
2017-11-17 15:28 ` Stefan Monnier
[not found] ` <<838tf5id1e.fsf@gnu.org>
1 sibling, 1 reply; 50+ messages in thread
From: Eli Zaretskii @ 2017-11-17 7:23 UTC (permalink / raw)
To: Tak Kunihiro
Cc: charles, johnw, emacs-devel, homeros.misasa, monnier, agrambot,
drew.adams
> From: Tak Kunihiro <homeros.misasa@gmail.com>
> Cc: Tak Kunihiro <homeros.misasa@gmail.com>, charles@aurox.ch (Charles A. Roelli), Alex <agrambot@gmail.com>, eliz@gnu.org, johnw@gnu.org, drew.adams@oracle.com, emacs-devel@gnu.org
> Date: Fri, 17 Nov 2017 08:21:02 +0900
>
> (global-set-key [mouse-3] 'mouse-context-menu)
> (defun mouse-context-menu (event)
> (interactive "e")
> (or (poplife-mouse-dir-menu event) ; DIR menu
> (poplife-mouse-url-menu event) ; URL menu
> (mouse3-region-menu event) ; region menu
> (mouse-context-menu-default event))) ; default menu <<<<<
I don't think binding this to mouse-3 by default can fly, because it
contradicts the usual GUI meaning of that button related to
selections, something that is honored by all well-behaving GUI
applications in the X world. It would be unwise for Emacs not to
comply.
^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: Changing default mouse bindings
2017-11-17 7:23 ` Eli Zaretskii
@ 2017-11-17 15:28 ` Stefan Monnier
2018-01-10 4:34 ` Tak Kunihiro
0 siblings, 1 reply; 50+ messages in thread
From: Stefan Monnier @ 2017-11-17 15:28 UTC (permalink / raw)
To: Eli Zaretskii
Cc: charles, johnw, emacs-devel, Tak Kunihiro, agrambot, drew.adams
>> (global-set-key [mouse-3] 'mouse-context-menu)
>> (defun mouse-context-menu (event)
>> (interactive "e")
>> (or (poplife-mouse-dir-menu event) ; DIR menu
>> (poplife-mouse-url-menu event) ; URL menu
>> (mouse3-region-menu event) ; region menu
>> (mouse-context-menu-default event))) ; default menu <<<<<
> I don't think binding this to mouse-3 by default can fly, because it
> contradicts the usual GUI meaning of that button related to
> selections, something that is honored by all well-behaving GUI
> applications in the X world. It would be unwise for Emacs not to
> comply.
Indeed, I think we should first focus on the command itself, and leave
the discussion about where to bind it to for later.
I don't think we want the command to hardcode things like dir-menu,
region-menu, ..., so we'll want to have a hook where we can add
a function that gives the region-part of the menu, and another for the
dir-part of a menu, ...
Maybe we could do something like the code below. The intention is to
make it reasonably easy to add functions to the hook that add a few
elements to the menu, and to also make it possible to add functions that
completely override the default menu (e.g. for flyspell's context menu).
This sample solution doesn't provide any direct way to specify the
context-menu from text-properties, so maybe we'd want to add to the
default definition of mouse-context-menu-function some function which
looks up some `context-menu` text-property, tho maybe we don't need that
and we can let packages add their own function to lookup their own
text-properties instead.
Stefan
(defvar mouse-context-menu-function #'mouse-default-context-menu
"Function that builds the context-menu.
Takes one argument (the EVENT that requests the menu) and should return
a list of menu items.")
(defun mouse-context-menu (event)
"Open up the context menu."
(interactive "@e")
(let* ((menu-items (funcall mouse-context-menu-function event))
(keymap `(keymap ,(apply #'vector menu-items))))
(popup-menu leymap event)))
^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: Changing default mouse bindings
2017-11-17 15:28 ` Stefan Monnier
@ 2018-01-10 4:34 ` Tak Kunihiro
0 siblings, 0 replies; 50+ messages in thread
From: Tak Kunihiro @ 2018-01-10 4:34 UTC (permalink / raw)
To: Stefan Monnier
Cc: charles, johnw, emacs-devel, Tak Kunihiro, agrambot,
Eli Zaretskii, drew.adams
> Maybe we could do something like the code below. The intention is to
> make it reasonably easy to add functions to the hook that add a few
> elements to the menu, and to also make it possible to add functions that
> completely override the default menu (e.g. for flyspell's context menu).
>
> (defvar mouse-context-menu-function #'mouse-default-context-menu
> "Function that builds the context-menu.
> Takes one argument (the EVENT that requests the menu) and should return
> a list of menu items.")
>
> (defun mouse-context-menu (event)
> "Open up the context menu."
> (interactive "@e")
> (let* ((menu-items (funcall mouse-context-menu-function event))
> (keymap `(keymap ,(apply #'vector menu-items))))
> (popup-menu leymap event)))
I tried to test the sample code but I cannot make it work.
Can you show me how to make it work?
(defvar mouse-context-menu-function #'mouse-default-context-menu
"Function that builds the context-menu.
Takes one argument (the EVENT that requests the menu) and should return
a list of menu items.")
(defun mouse-context-menu (event)
"Open up the context menu."
(interactive "@e")
(let* ((menu-items (funcall mouse-context-menu-function event))
(keymap `(keymap ,(apply #'vector menu-items))))
- (popup-menu leymap event)))
+ (popup-menu keymap event)))
+ (defun mouse-default-context-menu (event)
+ "Return default context menu."
+ (interactive "e")
+ menu-bar-edit-menu)
+
+ (define-key global-map [mouse-3] 'mouse-context-menu)
^ permalink raw reply [flat|nested] 50+ messages in thread
[parent not found: <<838tf5id1e.fsf@gnu.org>]
* RE: Changing default mouse bindings
[not found] ` <<838tf5id1e.fsf@gnu.org>
@ 2017-11-17 15:31 ` Drew Adams
0 siblings, 0 replies; 50+ messages in thread
From: Drew Adams @ 2017-11-17 15:31 UTC (permalink / raw)
To: Eli Zaretskii, Tak Kunihiro
Cc: charles, johnw, emacs-devel, agrambot, monnier, drew.adams
> I don't think binding this to mouse-3 by default can fly,
> because it contradicts the usual GUI meaning of that
> button related to selections, something that is honored
> by all well-behaving GUI applications in the X world.
> It would be unwise for Emacs not to comply.
There is that. And there is the fact that in Emacs
`mouse-3' does even more than usual with the selection
(region).
IMHO, the default Emacs behavior of `mouse-3' is a
good one, even if too few Emacs users know about it
and so make use of it. I don't see why we would
change the default behavior (and I haven't seen any
good argument here for doing that).
On the other hand, letting users and libraries easily
configure non-default behavior is a good idea.
The _first question_, I think, is whether, in
providing an easy way to do that, Emacs should at
least encourage users and libraries to respect the
existing default behavior. IOW, make it easy to
show a `mouse-3' menu _without_ preventing the
normal, default use of `mouse-3' to cut and extend
the region.
That's the approach taken in `mouse3.el'. I
did not want to interfere at all with the normal
behavior, and yet let users get any kind of menu
they want.
An approach to allowing customization that
starts with just binding `mouse-3' to a menu
does not accommodate the existing
cut/extend-region behavior - it effectively just
abandons that behavior. It lets you choose,
only at configuration/customization time: menu
or cut/extend-region. It doesn't let you choose
interactively. It's not very Emacsy, in that
respect.
It has the "advantage", I suppose, of easily
letting you _replace_ that behavior with a menu.
It has the disadvantage of _only_ replacing it.
If a user or library wants both the cut/extent
behavior and a menu, au choix interactively,
then they will need to bypass the provided
customization mechanism and come up with
their own complex code that does the job.
It's easy enough to _add_ the possibility of
replacing cut/extend behavior to something like
what `mouse3.el' does (which is to preserve it).
IOW, you can always impose a simple menu-only
customization.
But just _replacing_ with a menu should not be
all we offer, in terms of letting you get a menu.
I think the answer to this first question should
be to allow customization but make it easiest to
get a menu without interfering with the default
cut/extend-region behavior.
^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: Changing default mouse bindings
2017-11-13 23:08 ` Changing default mouse bindings (was: poplife-mode) Alex
2017-11-14 2:50 ` Changing default mouse bindings Stefan Monnier
2017-11-14 20:26 ` Changing default mouse bindings (was: poplife-mode) Charles A. Roelli
@ 2017-11-17 16:25 ` Sam Steingold
2 siblings, 0 replies; 50+ messages in thread
From: Sam Steingold @ 2017-11-17 16:25 UTC (permalink / raw)
To: emacs-devel
When discussing mouse binding, please keep in mind that not everyone has
3 button mice, and some of us have only one button.
Attempts to use modifiers fail because of bug#28955.
Thanks.
--
Sam Steingold (http://sds.podval.org/) on darwin Ns 10.3.1504
http://steingoldpsychology.com http://www.childpsy.net http://www.memritv.org
http://honestreporting.com http://americancensorship.org http://iris.org.il
Sinners can repent, but stupid is forever.
^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: poplife-mode
2017-11-13 15:24 ` poplife-mode Stefan Monnier
2017-11-13 17:08 ` poplife-mode Drew Adams
@ 2017-11-13 23:16 ` Tak Kunihiro
1 sibling, 0 replies; 50+ messages in thread
From: Tak Kunihiro @ 2017-11-13 23:16 UTC (permalink / raw)
To: Stefan Monnier; +Cc: charles, drew.adams, emacs-devel
>> What's better about it?
>
> No need to double click, hence (except for a 450ms delay) it behaves
> just like the "standard" context menu of other applications.
It is good idea to show context menu by long click (1000 ms) on mouse-1.
By this way, one can cut, copy, and paste by a button. Note that
already mouse-1 can cut and paste by drag-and-drop (in the same buffer
only).
^ permalink raw reply [flat|nested] 50+ messages in thread
[parent not found: <<jwvy3ncx3kx.fsf-monnier+gmane.emacs.devel@gnu.org>]
end of thread, other threads:[~2018-01-10 4:34 UTC | newest]
Thread overview: 50+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2017-11-05 1:00 poplife-mode Tak Kunihiro
2017-11-05 5:52 ` poplife-mode Drew Adams
2017-11-11 12:47 ` poplife-mode Charles A. Roelli
2017-11-11 15:01 ` poplife-mode Stefan Monnier
2017-11-12 13:55 ` poplife-mode Charles A. Roelli
2017-11-12 16:46 ` poplife-mode Stefan Monnier
2017-11-12 16:54 ` poplife-mode Eli Zaretskii
2017-11-12 17:47 ` poplife-mode Stefan Monnier
2017-11-12 19:17 ` poplife-mode Yuri Khan
2017-11-12 20:32 ` poplife-mode Charles A. Roelli
2017-11-12 20:36 ` poplife-mode Stefan Monnier
2017-11-13 5:03 ` poplife-mode Yuri Khan
2017-11-12 18:06 ` poplife-mode Stefan Monnier
2017-11-12 20:24 ` poplife-mode Charles A. Roelli
2017-11-13 8:11 ` poplife-mode Tak Kunihiro
2017-11-13 14:36 ` poplife-mode Drew Adams
2017-11-13 23:03 ` poplife-mode Tak Kunihiro
2017-11-14 0:48 ` poplife-mode Drew Adams
2017-11-14 23:26 ` poplife-mode Tak Kunihiro
2017-11-14 23:40 ` poplife-mode Drew Adams
2017-11-13 1:36 ` poplife-mode Drew Adams
2017-11-13 3:40 ` poplife-mode Drew Adams
2017-11-13 4:06 ` poplife-mode Stefan Monnier
2017-11-13 14:36 ` poplife-mode Drew Adams
2017-11-13 15:24 ` poplife-mode Stefan Monnier
2017-11-13 17:08 ` poplife-mode Drew Adams
2017-11-13 20:20 ` poplife-mode Stefan Monnier
2017-11-13 21:56 ` poplife-mode Drew Adams
2017-11-13 23:13 ` poplife-mode Stefan Monnier
2017-11-13 23:08 ` Changing default mouse bindings (was: poplife-mode) Alex
2017-11-14 2:50 ` Changing default mouse bindings Stefan Monnier
2017-11-14 7:07 ` Yuri Khan
2017-11-14 16:34 ` Stefan Monnier
2017-11-14 15:13 ` Eli Zaretskii
2017-11-14 16:35 ` Stefan Monnier
2017-11-14 16:38 ` Eli Zaretskii
[not found] ` <<838tf8lwqn.fsf@gnu.org>
2017-11-14 15:35 ` Drew Adams
2017-11-14 16:58 ` Eli Zaretskii
[not found] ` <<<838tf8lwqn.fsf@gnu.org>
[not found] ` <<69307385-5625-48dc-9611-ad7f0b6bd529@default>
[not found] ` <<83r2t0kdaz.fsf@gnu.org>
2017-11-14 19:47 ` Drew Adams
2017-11-14 20:26 ` Changing default mouse bindings (was: poplife-mode) Charles A. Roelli
2017-11-14 23:11 ` Changing default mouse bindings Tak Kunihiro
2017-11-15 3:16 ` Stefan Monnier
2017-11-16 23:21 ` Tak Kunihiro
2017-11-17 7:23 ` Eli Zaretskii
2017-11-17 15:28 ` Stefan Monnier
2018-01-10 4:34 ` Tak Kunihiro
[not found] ` <<838tf5id1e.fsf@gnu.org>
2017-11-17 15:31 ` Drew Adams
2017-11-17 16:25 ` Sam Steingold
2017-11-13 23:16 ` poplife-mode Tak Kunihiro
[not found] ` <<jwvy3ncx3kx.fsf-monnier+gmane.emacs.devel@gnu.org>
[not found] ` <<m2h8tzppod.fsf@aurox.ch>
2017-11-13 1:06 ` poplife-mode Drew Adams
Code repositories for project(s) associated with this public inbox
https://git.savannah.gnu.org/cgit/emacs.git
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).