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…
	
	Add table
		Add a link
		
	
		Reference in a new issue