Rename clipmenu.el to ivy-clipmenu.el
TL;DR: Preparing ivy-clipmenu for publishing. Also: - Removes lingering TODO items. - Clarifies module and function documentation. - Defines groups for custom variables. - Supports history variable for ivy-read.
This commit is contained in:
parent
47faf8d6f0
commit
a3077677f9
2 changed files with 134 additions and 149 deletions
|
@ -1,149 +0,0 @@
|
|||
;;; clipmenu.el --- Emacs client for clipmenu -*- lexical-binding: t -*-
|
||||
;; Author: William Carroll <wpcarro@gmail.com>
|
||||
|
||||
;;; Commentary:
|
||||
;; Ivy integration with the excellent program, clipmenu.
|
||||
;;
|
||||
;; clipmenu is a simple clipboard manager xsel. Usually clipmenu integrates with
|
||||
;; dmenu. This Emacs module integrates with ivy. Launch this when you want to
|
||||
;; select a clip.
|
||||
;;
|
||||
;; The following environment variables allow you to customize clipmenu's
|
||||
;; behavior:
|
||||
;;
|
||||
;; - CM_DIR: specify the base directory to store the cache dir in
|
||||
;; (default: $XDG_RUNTIME_DIR, $TMPDIR, or /tmp)
|
||||
;; - CM_HISTLENGTH: specify the number of lines to show in ivy. (default: 8)
|
||||
;;
|
||||
;; Other variables for customizing clipmenu are defined herein.
|
||||
;;
|
||||
;; For more information, see `clipmenu --help`.
|
||||
|
||||
;;; Code:
|
||||
|
||||
;; TODO: Support an ivy action of deleting an entry from clipmenu.
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; Dependencies
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
(require 'f)
|
||||
(require 's)
|
||||
(require 'dash)
|
||||
|
||||
(prelude/assert
|
||||
(prelude/executable-exists? "clipmenud"))
|
||||
|
||||
(prelude/assert
|
||||
(prelude/executable-exists? "clipmenu"))
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; Variables
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
;; TODO: Remove this if you're publishing it.
|
||||
(defcustom clipmenu/install-kbds? t
|
||||
"When t, install the keybindings defined herein")
|
||||
|
||||
(defcustom clipmenu/directory
|
||||
(or (getenv "XDG_RUNTIME_DIR")
|
||||
(getenv "TMPDIR")
|
||||
"/tmp")
|
||||
"Base directory for clipmenu data.")
|
||||
|
||||
(defconst clipmenu/major-version 5
|
||||
"The major version number for clipmenu.")
|
||||
|
||||
(defconst clipmenu/cache-directory
|
||||
(f-join clipmenu/directory
|
||||
(format "clipmenu.%s.%s"
|
||||
clipmenu/major-version
|
||||
(getenv "USER")))
|
||||
"Directory where the clips are stored.")
|
||||
|
||||
(defconst clipmenu/cache-file-pattern
|
||||
(f-join clipmenu/cache-directory "line_cache_*")
|
||||
"Glob pattern matching the locations on disk for clipmenu's labels.")
|
||||
|
||||
(defcustom clipmenu/history-length
|
||||
(or (getenv "CM_HISTLENGTH") 50)
|
||||
"Limit the number of clips in the history.
|
||||
This value defaults to 50.")
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; Functions
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
(defun clipmenu/parse-line (x)
|
||||
"Parse the entry in the clipmenu's line-cache."
|
||||
(string-to-number
|
||||
(list/join "" (parsec-with-input x (parsec-count 19 (parsec-digit))))))
|
||||
|
||||
(defun clipmenu/parse-content (x)
|
||||
"Parse the label from the entry in clipmenu's line-cache."
|
||||
(list/join
|
||||
""
|
||||
(parsec-with-input x
|
||||
(parsec-count 19 (parsec-digit))
|
||||
(parsec-str " ")
|
||||
(parsec-many (parsec-any-ch)))))
|
||||
|
||||
(defun clipmenu/list-clips ()
|
||||
"Return a list of the content of all of the clips."
|
||||
(->> clipmenu/cache-file-pattern
|
||||
f-glob
|
||||
(-map (lambda (path)
|
||||
(s-split "\n" (f-read path) t)))
|
||||
-flatten
|
||||
(-reject #'s-blank?)
|
||||
(-sort (lambda (a b)
|
||||
(< (clipmenu/parse-line a)
|
||||
(clipmenu/parse-line b))))
|
||||
(-map #'clipmenu/parse-content)
|
||||
list/dedupe-adjacent
|
||||
(-take clipmenu/history-length)))
|
||||
|
||||
;; TODO: Add tests.
|
||||
(defun clipmenu/escape-quotes (x)
|
||||
"Escape double and single quotes in X."
|
||||
(->> x
|
||||
(s-replace "\"" "\\\"")
|
||||
(s-replace "'" "\\'")))
|
||||
|
||||
(defun clipmenu/line-to-clip (line)
|
||||
"Map the chosen LINE to a clip stored on disk."
|
||||
(->> line
|
||||
clipmenu/checksum
|
||||
(f-join clipmenu/cache-directory)
|
||||
f-read
|
||||
clipboard/copy))
|
||||
|
||||
;; TODO: Consider supporting :history keyword.
|
||||
|
||||
;; TODO: Ensure you can handle special characters like:
|
||||
;; r}_rh,pmj~kCR.<5w"PUk#Z^>.
|
||||
|
||||
(defun clipmenu/ivy-copy ()
|
||||
"Use `ivy-read' to select and copy a clip."
|
||||
(interactive)
|
||||
(let ((ivy-sort-functions-alist nil))
|
||||
(ivy-read "Clipmenu: "
|
||||
(clipmenu/list-clips)
|
||||
:action #'clipmenu/line-to-clip)))
|
||||
|
||||
(defun clipmenu/checksum (content)
|
||||
"Return the CRC checksum of CONTENT."
|
||||
(s-trim-right
|
||||
(prelude/call-process-to-string
|
||||
"/bin/bash" "-c" (string/format "/usr/bin/cksum <<<'%s'" content))))
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; Keybindings
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
(when clipmenu/install-kbds?
|
||||
(exwm-input-set-key
|
||||
(kbd "C-M-v") #'clipmenu/ivy-copy))
|
||||
|
||||
(provide 'clipmenu)
|
||||
;;; clipmenu.el ends here
|
134
configs/shared/.emacs.d/wpc/ivy-clipmenu.el
Normal file
134
configs/shared/.emacs.d/wpc/ivy-clipmenu.el
Normal file
|
@ -0,0 +1,134 @@
|
|||
;;; ivy-clipmenu.el --- Emacs client for clipmenu -*- lexical-binding: t -*-
|
||||
;; Author: William Carroll <wpcarro@gmail.com>
|
||||
|
||||
;;; Commentary:
|
||||
;; Ivy integration with the clipboard manager, clipmenu. Essentially, clipmenu
|
||||
;; turns your system clipboard into a list.
|
||||
;;
|
||||
;; To use this module, you must first install clipmenu and ensure that the
|
||||
;; clipmenud daemon is running. Refer to the installation instructions at
|
||||
;; github.com/cdown/clipmenu for those details.
|
||||
;;
|
||||
;; This module intentionally does not define any keybindings since I'd prefer
|
||||
;; not to presume my users' preferences. Personally, I use EXWM as my window
|
||||
;; manager, so I call `exwm-input-set-key' and map it to `ivy-clipmenu/copy'.
|
||||
;;
|
||||
;; Usually clipmenu integrates with rofi or dmenu. This Emacs module integrates
|
||||
;; with ivy. Launch this when you want to select a clip.
|
||||
;;
|
||||
;; Clipmenu itself supports a variety of environment variables that allow you to
|
||||
;; customize its behavior. These variables are respected herein. If you'd
|
||||
;; prefer to customize clipmenu's behavior from within Emacs, refer to the
|
||||
;; variables defined in this module.
|
||||
;;
|
||||
;; For more information:
|
||||
;; - See `clipmenu --help`.
|
||||
;; - Visit github.com/cdown/clipmenu.
|
||||
|
||||
;;; Code:
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; Dependencies
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
(require 'f)
|
||||
(require 's)
|
||||
(require 'dash)
|
||||
(require 'ivy)
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; Variables
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
(defgroup ivy-clipmenu nil
|
||||
"Ivy integration for clipmenu."
|
||||
:group 'ivy)
|
||||
|
||||
(defcustom ivy-clipmenu/directory
|
||||
(or (getenv "XDG_RUNTIME_DIR")
|
||||
(getenv "TMPDIR")
|
||||
"/tmp")
|
||||
"Base directory for clipmenu's data."
|
||||
:type 'string
|
||||
:group 'ivy-clipmenu)
|
||||
|
||||
(defconst ivy-clipmenu/executable-version 5
|
||||
"The major version number for the clipmenu executable.")
|
||||
|
||||
(defconst ivy-clipmenu/cache-directory
|
||||
(f-join ivy-clipmenu/directory
|
||||
(format "clipmenu.%s.%s"
|
||||
ivy-clipmenu/executable-version
|
||||
(getenv "USER")))
|
||||
"Directory where the clips are stored.")
|
||||
|
||||
(defconst ivy-clipmenu/cache-file-pattern
|
||||
(f-join ivy-clipmenu/cache-directory "line_cache_*")
|
||||
"Glob pattern matching the locations on disk for clipmenu's labels.")
|
||||
|
||||
(defcustom ivy-clipmenu/history-length
|
||||
(or (getenv "CM_HISTLENGTH") 25)
|
||||
"Limit the number of clips in the history.
|
||||
This value defaults to 25.")
|
||||
|
||||
(defvar ivy-clipmenu/history nil
|
||||
"History for `ivy-clipmenu/copy'.")
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; Functions
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
(defun ivy-clipmenu/parse-content (x)
|
||||
"Parse the label from the entry in clipmenu's line-cache."
|
||||
(->> (s-split " " x)
|
||||
(-drop 1)
|
||||
(s-join " ")))
|
||||
|
||||
(defun ivy-clipmenu/list-clips ()
|
||||
"Return a list of the content of all of the clips."
|
||||
(->> ivy-clipmenu/cache-file-pattern
|
||||
f-glob
|
||||
(-map (lambda (path)
|
||||
(s-split "\n" (f-read path) t)))
|
||||
-flatten
|
||||
(-reject #'s-blank?)
|
||||
(-sort #'string>)
|
||||
(-map #'ivy-clipmenu/parse-content)
|
||||
delete-dups
|
||||
(-take ivy-clipmenu/history-length)))
|
||||
|
||||
(defun ivy-clipmenu/checksum (content)
|
||||
"Return the CRC checksum of CONTENT."
|
||||
(s-trim-right
|
||||
(with-temp-buffer
|
||||
(call-process "/bin/bash" nil (current-buffer) nil "-c"
|
||||
(format "cksum <<<'%s'" content))
|
||||
(buffer-string))))
|
||||
|
||||
(defun ivy-clipmenu/line-to-content (line)
|
||||
"Map the chosen LINE from the line cache its content from disk."
|
||||
(->> line
|
||||
ivy-clipmenu/checksum
|
||||
(f-join ivy-clipmenu/cache-directory)
|
||||
f-read))
|
||||
|
||||
(defun ivy-clipmenu/do-copy (x)
|
||||
"Copy string, X, to the system clipboard."
|
||||
(kill-new x)
|
||||
(message "[ivy-clipmenu.el] Copied!"))
|
||||
|
||||
(defun ivy-clipmenu/copy ()
|
||||
"Use `ivy-read' to select and copy a clip.
|
||||
It's recommended to bind this function to a globally available keymap."
|
||||
(interactive)
|
||||
(let ((ivy-sort-functions-alist nil))
|
||||
(ivy-read "Clipmenu: "
|
||||
(ivy-clipmenu/list-clips)
|
||||
:history 'ivy-clipmenu/history
|
||||
:action (lambda (line)
|
||||
(->> line
|
||||
ivy-clipmenu/line-to-content
|
||||
ivy-clipmenu/do-copy)))))
|
||||
|
||||
(provide 'ivy-clipmenu)
|
||||
;;; ivy-clipmenu.el ends here
|
Loading…
Reference in a new issue