├── COPYING ├── README.org └── hippie-completing-read.el /COPYING: -------------------------------------------------------------------------------- 1 | Copyright (C) 2021--2022 Case Duckworth 2 | 3 | Usage of the works is permitted provided that this instrument is retained with the works, so that any entity that uses the works is notified of this instrument. 4 | 5 | DISCLAIMER: THE WORKS ARE WITHOUT WARRANTY. 6 | -------------------------------------------------------------------------------- /README.org: -------------------------------------------------------------------------------- 1 | #+title: Hippie Completing Read 2 | #+subtitle: toward a unified Emacs completing UI 3 | 4 | I use ~completing-read~ in Emacs. I even use it in lieu of popular completion packages like =company= and such, for ~completion-in-region~. The one final thorn in my side was using =hippie-expand=, which completes some things better, or at least … /different-er/, than regular ~completion-in-region~ commands. So I went searching for how to combine both things. 5 | 6 | Deep in the back waters of EmacsWiki, I found it: code for an [[https://www.emacswiki.org/emacs/HippieExpand#h5o-11][=ido= interface to =completing-read=]]. It was easy to adapt to ~completing-read~ code, so I did, and here's the package. 7 | 8 | * Install 9 | 10 | You should honestly know how to install packages in Emacs, but you can use =straight.el=: 11 | 12 | #+begin_src emacs-lisp 13 | (straight-use-package 14 | '(hippie-completing-read 15 | :host nil 16 | :repo "https://codeberg.org/acdw/hippie-completing-read.el")) 17 | #+end_src 18 | 19 | and you should be good to go. 20 | 21 | * Using 22 | 23 | =hippie-completing-read= exposes one function, aptly called ~hippie-completing- read~. I bind it thusly: 24 | 25 | #+begin_src emacs-lisp 26 | (global-set-key (kbd "M-/") #'hippie-completing-read) 27 | #+end_src 28 | 29 | * Customizing 30 | 31 | There are a number of customization options available for =hippie-completing- read=, of which this is a not-definitely up-to-date list. For the definitive list, see the Easy Customization group for this package. 32 | 33 | - ~hippie-completing-read-prompt~ :: The prompt to display with ~hippie-completing-read-expand-with~. Default: =Hippie:=. 34 | - ~hippie-completing-read-function~ :: Function to use to display and select from ~hippie-expand~ selections. Should be compatible with ~completing-read~. Default: ~completing-read~. 35 | - ~hippie-completing-read-function-parameters~ :: Further parameters to pass to ~hippie-completing-read-function~. By default, add ~he-search-string~ (the thing we're completing) as initial input. This variable is risky, since its values are evaluated when passed to ~hippie-completing-read~. 36 | - ~hippie-completing-read-threshold~ :: Number of expansion candidates needed before using ~completing-read~. The more traditional "cycling" behavior for hippie-complete will be used so long as there are not more completion candidates than in this number. 37 | 38 | * Contributing 39 | 40 | IDK, open an issue, or whatever. 41 | 42 | * License 43 | 44 | Copyright (C) 2021--2022 Case Duckworth 45 | 46 | Usage of the works is permitted provided that this instrument is retained with the works, so that any entity that uses the works is notified of this instrument. 47 | 48 | DISCLAIMER: THE WORKS ARE WITHOUT WARRANTY. 49 | -------------------------------------------------------------------------------- /hippie-completing-read.el: -------------------------------------------------------------------------------- 1 | ;;; hippie-completing-read.el --- Peace love complete -*- lexical-binding: t; -*- 2 | 3 | ;; Copyright (C) 2021--2022 Case Duckworth 4 | 5 | ;; Author: Case Duckworth 6 | ;; License: Fair 7 | ;; URL: https://codeberg.org/acdw/hippie-completing-read.el 8 | ;; Package-Version: 0.3 9 | ;; Package-Requires: ((emacs "24.3")) 10 | 11 | ;;; Commentary: 12 | 13 | ;; Adapted from https://www.emacswiki.org/emacs/HippieExpand#h5o-11, this 14 | ;; allows completing with `hippie-expand' using `completing-read'. 15 | 16 | ;;; Code: 17 | 18 | (require 'cl-lib) 19 | (require 'hippie-exp) 20 | 21 | (defgroup hippie-completing-read nil 22 | "Use Hippie Expansion from a Completing Read interface." 23 | :group 'hippie-expand 24 | :group 'completion 25 | :prefix "hippie-completing-read-") 26 | 27 | (defcustom hippie-completing-read-prompt "Hippie: " 28 | "The prompt to display with `hippie-completing-read-expand-with'." 29 | :type 'string) 30 | 31 | (defcustom hippie-completing-read-function 'completing-read 32 | "Function to use to display and select from `hippie-expand' selections. 33 | Should be compatible with `completing-read'." 34 | :type 'function) 35 | 36 | (defcustom hippie-completing-read-function-parameters '(nil ; predicate 37 | nil ; require-match 38 | ;; initial-input 39 | he-search-string) 40 | "Further parameters to pass to `hippie-completing-read-function'. 41 | By default, add `he-search-string' (the thing we're completing) 42 | as initial input. 43 | 44 | This variable is risky, since its values are evaluated when passed to `hippie-completing-read'." 45 | :type 'list 46 | :risky t) 47 | 48 | (defcustom hippie-completing-read-threshold 0 49 | "Number of expansion candidates needed before using `completing-read'. 50 | The more traditional \"cycling\" behavior for hippie-complete 51 | will be used so long as there are not more completion candidates 52 | than in this number." 53 | :type '(integer :tag "Threshold")) 54 | 55 | (define-obsolete-variable-alias 'hippie-completing-read-cycle-threshold 56 | 'hippie-completing-read-threshold 57 | "0.3" 58 | "Number of expansion candidates needed before using `completing-read'.") 59 | 60 | (defun hippie-completing-read-expand-completions 61 | (&optional hippie-expand-function) 62 | "Return the full list of possible completions generated by `hippie-expand'. 63 | The optional HIPPIE-EXPAND-FUNCTION argument can be generated 64 | with `make-hippie-expand-function'." 65 | (let ((this-command 'hippie-completing-read-expand-completions) 66 | (last-command last-command) 67 | (buffer-modified (buffer-modified-p)) 68 | (hippie-expand-function (or hippie-expand-function 'hippie-expand))) 69 | (cl-letf (((symbol-function 'ding) #'ignore)) 70 | ;; inhibit ding when `hippie-expand' exhausts completions 71 | (while (progn 72 | (funcall hippie-expand-function nil) 73 | (setq last-command 'hippie-completing-read-expand-completions) 74 | (not (equal he-num -1))))) 75 | ;; Evaluating the completions modifies the buffer, however we will finish 76 | ;; up in the same state that we began. 77 | (set-buffer-modified-p buffer-modified) 78 | ;; Provide the options in the order in which they are normally generated. 79 | (delete he-search-string (reverse he-tried-table)))) 80 | 81 | (defun hippie-completing-read-expand-with (hippie-expand-function) 82 | "Offer `completing-read' based completion using `hippie-expand'. 83 | The supplied HIPPIE-EXPAND-FUNCTION will provide completion items." 84 | (let ((collection (hippie-completing-read-expand-completions 85 | hippie-expand-function))) 86 | (if collection 87 | (if (> (length collection) 88 | ;; This test is necessary for full backward-compatibility; 89 | ;; originally the variable was 90 | ;; `hippie-completing-read-cycle-threshold' and could also take 91 | ;; values t, nil, and `inherit' (where it would inherit from 92 | ;; `completing-read-cycle-threshold' --- which turns out to be 93 | ;; nonexistent, at least in Emacs 28. So this code checks if 94 | ;; `hippie-completing-read-threshold' is a number, and if not, 95 | ;; uses 0 --- effectively enabling the completing-read UI in all 96 | ;; cases. (CD 2022-07-26) 97 | (if (numberp hippie-completing-read-threshold) 98 | hippie-completing-read-threshold 99 | 0)) 100 | (let ((selection 101 | (apply hippie-completing-read-function 102 | hippie-completing-read-prompt 103 | collection 104 | (mapcar 'eval ; is this safe??? hmmmm 105 | hippie-completing-read-function-parameters)))) 106 | (when selection 107 | (he-substitute-string selection t))) 108 | (hippie-expand nil)) 109 | (user-error "No expansion found for %s" he-search-string)))) 110 | 111 | ;;;###autoload 112 | (defun hippie-completing-read () 113 | "Offer `completing-read' based completion for word at point." 114 | (interactive) 115 | (hippie-completing-read-expand-with 'hippie-expand)) 116 | 117 | (provide 'hippie-completing-read) 118 | ;;; hippie-completing-read.el ends here 119 | --------------------------------------------------------------------------------