In order for this to scale, I need to solve two things: 1. Ad-hoc ignore fill-column rules for URLs and other exceptions. 2. Run Elisp flychecker without evaluating my Elisp code and firing its side-effects.
		
			
				
	
	
		
			138 lines
		
	
	
	
		
			4.5 KiB
		
	
	
	
		
			EmacsLisp
		
	
	
	
	
	
			
		
		
	
	
			138 lines
		
	
	
	
		
			4.5 KiB
		
	
	
	
		
			EmacsLisp
		
	
	
	
	
	
;;; ivy-clipmenu.el --- Emacs client for clipmenu -*- lexical-binding: t -*-
 | 
						|
 | 
						|
;; Author: William Carroll <wpcarro@gmail.com>
 | 
						|
;; Version: 0.0.1
 | 
						|
;; URL: https://git.wpcarro.dev/wpcarro/briefcase
 | 
						|
;; Package-Requires: ((emacs "25.1"))
 | 
						|
 | 
						|
;;; 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, X, 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
 |