This repository has been archived by the owner on Aug 5, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 17
/
Copy pathlean-right-click.el
84 lines (74 loc) · 3.43 KB
/
lean-right-click.el
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
;; -*- lexical-binding: t -*-
;;
;;; lean-right-click.el
;;
;; Copyright (c) 2017 David Christiansen. All rights reserved.
;;
;; Author: David Christiansen
;; Released under Apache 2.0 license as described in the file LICENSE.
;;
;;; Code:
(defvar lean-right-click-item-functions nil
"A list of functions to compute menu items from source locations.
The functions take no arguments. They will be run in a context
where `current-buffer' gives the buffer in which the click
occurred. The function should return a three-element list, where
the first is a Lean server command, the second is its parameter
list, and the third is a continuation that will compute a list of
menu items.
Each menu item is a plist that maps the key :name to the string
to show in the menu and the key :action to a zero-argument
function that implements the action.")
(make-variable-buffer-local 'lean-right-click-item-functions)
(defvar lean-right-click--unique-val-counter 0
"A global counter for unique values for lean-right-click.")
(defun lean-right-click--unique-val ()
"Get a unique value for internal tagging."
(cl-incf lean-right-click--unique-val-counter))
(defun lean-right-click--items-for-location ()
"Return the menu items for point in the current buffer."
(let ((commands (cl-loop for fun in lean-right-click-item-functions
collecting (funcall fun))))
(let ((timeout 0.15)
(items '())
(start-time (time-to-seconds))
(command-count (length commands))
(commands-returned 0))
(cl-loop for (cmd args cont) in commands
do (progn (lean-server-send-command
cmd args
(lambda (&rest result)
(setq items (append items (apply cont result)))
(cl-incf commands-returned))
(lambda (&rest _whatever)
(cl-incf commands-returned)))
;; This is necessary to ensure that async IO happens.
(sit-for 0.02)))
(while (and (< (time-to-seconds) (+ timeout start-time))
(< commands-returned command-count))
(sit-for 0.02))
items)))
(defun lean-right-click-show-menu (click)
"Show a menu based on the location of CLICK, computed from the `lean-right-click-functions'."
(interactive "e")
(let* ((window (posn-window (event-end click)))
(buffer (window-buffer window))
(where (posn-point (event-end click)))
(menu-items (with-current-buffer buffer
(save-excursion
(goto-char where)
(lean-right-click--items-for-location)))))
(when menu-items
(let* ((menu (make-sparse-keymap))
(todo (cl-loop for item in menu-items
collecting (let ((sym (lean-right-click--unique-val)))
(define-key-after menu `[,sym]
`(menu-item ,(plist-get item :name)
(lambda () (interactive)))
t)
(cons sym (plist-get item :action)))))
(selection (x-popup-menu click menu)))
(when selection
(funcall (cdr (assoc (car selection) todo))))))))
(provide 'lean-right-click)
;;; lean-right-click.el ends here