[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[elpa] externals/do-at-point 26eba56f63 01/44: Initial revision
From: |
ELPA Syncer |
Subject: |
[elpa] externals/do-at-point 26eba56f63 01/44: Initial revision |
Date: |
Fri, 25 Aug 2023 18:57:45 -0400 (EDT) |
branch: externals/do-at-point
commit 26eba56f638a5ac7059e0f32219d1bb86eab50a2
Author: Philip Kaludercic <philip.kaludercic@fau.de>
Commit: Philip Kaludercic <philip.kaludercic@fau.de>
Initial revision
---
do-at-point.el | 172 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 172 insertions(+)
diff --git a/do-at-point.el b/do-at-point.el
new file mode 100644
index 0000000000..5ffdd32b46
--- /dev/null
+++ b/do-at-point.el
@@ -0,0 +1,172 @@
+;;; do-at-point.el --- Generic context-sensitive action dispatcher. -*-
lexical-binding: t; -*-
+
+;; Copyright (C) 2023 Philip Kaludercic
+
+;; Author: Philip Kaludercic <philipk@posteo.net>
+;; Maintainer: Philip Kaludercic <philipk@posteo.net>
+;; URL: https://wwwcip.cs.fau.de/~oj14ozun/src+etc/do-at-point.el
+;; Version: $Id$
+;; Package-Version: 1
+;; Package-Requires: ((emacs "26.1"))
+;; Keywords: convenience
+
+;; 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 <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; The command `do-at-point' is a generalised `find-file-at-point',
+;; both in the sense that it can understand more than just files, and
+;; do more than just open a file. Depending on the "thing" at point,
+;; different "actions" can be dispatched, e.g. opening a url using
+;; `browse-url' or occurring a symbol at point.
+
+;; The entry point of this package is `do-at-point'. Bind it to a
+;; convenient key:
+;;
+;; (global-set-key (kbd "C-'") #'do-at-point)
+;;
+;; Most of the behaviour is controlled via the user option
+;; `do-at-point-actions'.
+
+;;; Relation to "Embark"
+
+;; A similar package, that served as inspiration for `do-at-point' is
+;; called Embark (https://github.com/oantolin/embark), by Omar AntolĂn
+;; Camarena. I'll be honest, I don't get the hype but I find the core
+;; functionality nice. This package is a fraction of the size of
+;; Embark, but does pretty much exactly what I would want to use
+;; Embark for + it dispatches actions using `read-multiple-choice'
+;; instead of popping up a buffer of using `completing-read' -- which
+;; is a bad choice for users who aren't using narrowing-selecting
+;; completion frameworks.
+
+;;; Code:
+
+(require 'seq)
+
+(defgroup do-at-point '()
+ "Generic context-sensitive action dispatcher."
+ :group 'convenience)
+
+(defcustom do-at-point-actions
+ `((region
+ (?\C-i "Indent" ,#'indent-region)
+ (?s "Isearch"
+ ,(lambda (str)
+ (isearch-mode t)
+ (isearch-yank-string str)))
+ (?o "Occur" ,(lambda (str) (occur (regexp-quote str))))
+ (?w "Kill-Save" ,#'kill-new)
+ (?k "Kill" ,#'kill-region)
+ (?n "Narrow" ,#'narrow-to-region)
+ (?| "Pipe command"
+ ,(lambda (beg end)
+ (let ((cmd (read-shell-command "Command: ")))
+ (shell-command-on-region beg end cmd))))
+ (?! "Shell command" ,#'shell-command))
+ (email
+ (?m "Compose message" ,(lambda (to) (compose-mail to))))
+ (existing-filename
+ (?f "Find file" ,#'find-file)
+ (?4 "Find file other window" ,#'find-file-other-window))
+ (url
+ (?f "Open" ,#'browse-url)
+ (?d "Download" ,#'(lambda (url)
+ (start-process "*Download*" nil "wget" url))))
+ (symbol
+ (?. "Xref" ,#'xref-find-definitions)
+ (?o "Occur" ,(lambda (str)
+ (occur (concat "\\_<\\(" (regexp-quote str) "\\)\\_>")))))
+ (word
+ (?$ "Spell check" ,(lambda () (ispell-word)))
+ (?d "Dictionary" ,#'dictionary-search))
+ (sexp)
+ (defun
+ (?e "Evaluate" ,(lambda () (eval-defun nil)))))
+ "Association of things and their respective actions.
+Each element of the list has the form (THING . ACTIONS), where
+THING is a symbol as interpreted by `thing-at-point' and ACTIONS
+have the form (KEY NAME FUNC), where KEY is a dispatch character,
+NAME is a brief description of the action and FUNC is a function
+that will be dispatched when KEY is selected. FUNC can take
+zero, one or two arguments, which `do-at-point' will respectively
+interpret as function that is invoked without any arguments, or
+with a buffer substring or the bounds of THING. Actions listed
+under the \"thing\" `region' are shared among all \"things\".
+This is why a an entry does not require any actions to be
+associated with it, if it just serves as a specific kind of
+region worth selecting. The order of element in the list
+correspond to the order in which `do-at-point' will prompt the
+user for possible things at point."
+ :type '(alist :value-type
+ (alist :value-type
+ (list :tag "Action"
+ (string :tag "Description") function)
+ :key-type character)
+ :key-type symbol))
+
+(defcustom do-at-point-quick-select '(?\C-m)
+ "List of keys to quickly select the first action."
+ :type '(repeat character))
+
+(defconst do-at-point--overlay
+ (let ((ov (make-overlay 0 0)))
+ (overlay-put ov 'face 'highlight)
+ (delete-overlay ov)
+ ov))
+
+;;;###autoload
+(defun do-at-point ()
+ "Dispatch an action on the thing at point."
+ (interactive)
+ (unwind-protect
+ (let* ((things (mapcar #'car do-at-point-actions))
+ (cand (seq-filter #'thing-at-point things))
+ (last last-input-event) (key last) (i 0) thing)
+ (when (null cand)
+ (user-error "Nothing actionable at point"))
+ (while (eq key last)
+ (setq thing (nth (mod i (length cand)) cand))
+ (let ((bound (bounds-of-thing-at-point thing)))
+ (move-overlay do-at-point--overlay (car bound) (cdr bound))
+ (setq key (read-key (format "Act on %s?" thing)) i (1+ i))
+ (when (eq key ?\C-g) (keyboard-quit))))
+ (let* ((options (append
+ (and (not (eq thing 'region))
+ (alist-get thing do-at-point-actions))
+ (alist-get 'region do-at-point-actions)))
+ (choice
+ (if (memq key do-at-point-quick-select)
+ (car options)
+ (when (assq key options)
+ (push key unread-post-input-method-events))
+ (read-multiple-choice
+ (format "Action on %s" thing)
+ (seq-uniq
+ (mapcar (lambda (ent)
+ (list (car ent) (cadr ent) (cadddr ent)))
+ options)
+ (lambda (a b) (eq (car a) (car b)))))))
+ (func (cadr (alist-get (car choice) options)))
+ (bound (bounds-of-thing-at-point thing)))
+ (message nil) ;clear minibuffer
+ (pcase (car (func-arity func))
+ (0 (funcall func))
+ (1 (funcall func (buffer-substring (car bound) (cdr bound))))
+ (2 (funcall func (car bound) (cdr bound)))
+ (_ (error "Unsupported signature: %S" func)))))
+ (delete-overlay do-at-point--overlay)))
+
+(provide 'do-at-point)
+;;; do-at-point.el ends here
- [elpa] branch externals/do-at-point created (now 0fac1ce7fa), ELPA Syncer, 2023/08/25
- [elpa] externals/do-at-point 4ca1472e45 05/44: Simplify thing selection logic, ELPA Syncer, 2023/08/25
- [elpa] externals/do-at-point 1bf742ffaf 11/44: Pass proper input to 'read-multiple-choice', ELPA Syncer, 2023/08/25
- [elpa] externals/do-at-point ffd013c6d2 15/44: Add user option to disable quick bindings, ELPA Syncer, 2023/08/25
- [elpa] externals/do-at-point 26eba56f63 01/44: Initial revision,
ELPA Syncer <=
- [elpa] externals/do-at-point 7073fc1917 07/44: Invert event loop to allow movement during selection, ELPA Syncer, 2023/08/25
- [elpa] externals/do-at-point a6b52ebf53 08/44: Fix name-typo in "Embark" section, ELPA Syncer, 2023/08/25
- [elpa] externals/do-at-point b25f8ff64e 12/44: Rebind browse-url from "f" to "b" for URLs, ELPA Syncer, 2023/08/25
- [elpa] externals/do-at-point bfe1d53b31 19/44: Unbind RET from 'do-at-point--mode-map', ELPA Syncer, 2023/08/25
- [elpa] externals/do-at-point 9d2ead6890 21/44: Fix 'do-at-point-actions-type' to work with inherited actions, ELPA Syncer, 2023/08/25
- [elpa] externals/do-at-point 0117be3619 23/44: Fix (require ...) for 'calc-embedded-word', ELPA Syncer, 2023/08/25
- [elpa] externals/do-at-point b2808685d4 24/44: Simplify 'calc-embedded' invocation, ELPA Syncer, 2023/08/25
- [elpa] externals/do-at-point 767fe39d62 25/44: Rename 'do-at-point--shortcut-map' to '--quick-map', ELPA Syncer, 2023/08/25
- [elpa] externals/do-at-point b6d819a000 29/44: Note '-user-actions' and '-local-actions' in 'do-at-point-actions', ELPA Syncer, 2023/08/25
- [elpa] externals/do-at-point a01cee0d72 26/44: Do not set the face of 'do-at-point--overlay' twice, ELPA Syncer, 2023/08/25