2020-01-16 15:49:50 +01:00
|
|
|
;;; ivy-clipmenu.el --- Emacs client for clipmenu -*- lexical-binding: t -*-
|
2020-09-01 11:17:43 +02:00
|
|
|
|
2020-01-16 15:49:50 +01:00
|
|
|
;; Author: William Carroll <wpcarro@gmail.com>
|
2020-09-01 11:17:43 +02:00
|
|
|
;; Version: 0.0.1
|
|
|
|
;; Package-Requires: ((emacs "25.1"))
|
2020-01-16 15:49:50 +01:00
|
|
|
|
|
|
|
;;; 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
|
2020-09-01 11:17:43 +02:00
|
|
|
;; manager, so I call `exwm-input-set-key' and map it to `ivy-clipmenu-copy'.
|
2020-01-16 15:49:50 +01:00
|
|
|
;;
|
|
|
|
;; 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)
|
|
|
|
|
2020-09-01 11:17:43 +02:00
|
|
|
(defcustom ivy-clipmenu-directory
|
2020-01-16 15:49:50 +01:00
|
|
|
(or (getenv "XDG_RUNTIME_DIR")
|
|
|
|
(getenv "TMPDIR")
|
|
|
|
"/tmp")
|
|
|
|
"Base directory for clipmenu's data."
|
|
|
|
:type 'string
|
|
|
|
:group 'ivy-clipmenu)
|
|
|
|
|
2020-09-01 11:17:43 +02:00
|
|
|
(defconst ivy-clipmenu-executable-version 5
|
2020-01-16 15:49:50 +01:00
|
|
|
"The major version number for the clipmenu executable.")
|
|
|
|
|
2020-09-01 11:17:43 +02:00
|
|
|
(defconst ivy-clipmenu-cache-directory
|
|
|
|
(f-join ivy-clipmenu-directory
|
2020-01-16 15:49:50 +01:00
|
|
|
(format "clipmenu.%s.%s"
|
2020-09-01 11:17:43 +02:00
|
|
|
ivy-clipmenu-executable-version
|
2020-01-16 15:49:50 +01:00
|
|
|
(getenv "USER")))
|
|
|
|
"Directory where the clips are stored.")
|
|
|
|
|
2020-09-01 11:17:43 +02:00
|
|
|
(defconst ivy-clipmenu-cache-file-pattern
|
|
|
|
(f-join ivy-clipmenu-cache-directory "line_cache_*")
|
2020-01-16 15:49:50 +01:00
|
|
|
"Glob pattern matching the locations on disk for clipmenu's labels.")
|
|
|
|
|
2020-09-01 11:17:43 +02:00
|
|
|
(defcustom ivy-clipmenu-history-length
|
2020-01-16 15:49:50 +01:00
|
|
|
(or (getenv "CM_HISTLENGTH") 25)
|
|
|
|
"Limit the number of clips in the history.
|
|
|
|
This value defaults to 25.")
|
|
|
|
|
2020-09-01 11:17:43 +02:00
|
|
|
(defvar ivy-clipmenu-history nil
|
|
|
|
"History for `ivy-clipmenu-copy'.")
|
2020-01-16 15:49:50 +01:00
|
|
|
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
;; Functions
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
|
2020-09-01 11:17:43 +02:00
|
|
|
(defun ivy-clipmenu-parse-content (x)
|
2020-09-01 14:44:18 +02:00
|
|
|
"Parse the label from the entry, X, in clipmenu's line-cache."
|
2020-01-16 15:49:50 +01:00
|
|
|
(->> (s-split " " x)
|
|
|
|
(-drop 1)
|
|
|
|
(s-join " ")))
|
|
|
|
|
2020-09-01 11:17:43 +02:00
|
|
|
(defun ivy-clipmenu-list-clips ()
|
2020-01-16 15:49:50 +01:00
|
|
|
"Return a list of the content of all of the clips."
|
2020-09-01 11:17:43 +02:00
|
|
|
(->> ivy-clipmenu-cache-file-pattern
|
2020-01-16 15:49:50 +01:00
|
|
|
f-glob
|
|
|
|
(-map (lambda (path)
|
|
|
|
(s-split "\n" (f-read path) t)))
|
|
|
|
-flatten
|
|
|
|
(-reject #'s-blank?)
|
|
|
|
(-sort #'string>)
|
2020-09-01 11:17:43 +02:00
|
|
|
(-map #'ivy-clipmenu-parse-content)
|
2020-01-16 15:49:50 +01:00
|
|
|
delete-dups
|
2020-09-01 11:17:43 +02:00
|
|
|
(-take ivy-clipmenu-history-length)))
|
2020-01-16 15:49:50 +01:00
|
|
|
|
2020-09-01 11:17:43 +02:00
|
|
|
(defun ivy-clipmenu-checksum (content)
|
2020-01-16 15:49:50 +01:00
|
|
|
"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))))
|
|
|
|
|
2020-09-01 11:17:43 +02:00
|
|
|
(defun ivy-clipmenu-line-to-content (line)
|
2020-01-16 15:49:50 +01:00
|
|
|
"Map the chosen LINE from the line cache its content from disk."
|
|
|
|
(->> line
|
2020-09-01 11:17:43 +02:00
|
|
|
ivy-clipmenu-checksum
|
|
|
|
(f-join ivy-clipmenu-cache-directory)
|
2020-01-16 15:49:50 +01:00
|
|
|
f-read))
|
|
|
|
|
2020-09-01 11:17:43 +02:00
|
|
|
(defun ivy-clipmenu-do-copy (x)
|
2020-01-16 15:49:50 +01:00
|
|
|
"Copy string, X, to the system clipboard."
|
|
|
|
(kill-new x)
|
|
|
|
(message "[ivy-clipmenu.el] Copied!"))
|
|
|
|
|
2020-09-01 11:17:43 +02:00
|
|
|
(defun ivy-clipmenu-copy ()
|
2020-01-16 15:49:50 +01:00
|
|
|
"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: "
|
2020-09-01 11:17:43 +02:00
|
|
|
(ivy-clipmenu-list-clips)
|
|
|
|
:history 'ivy-clipmenu-history
|
2020-01-16 15:49:50 +01:00
|
|
|
:action (lambda (line)
|
|
|
|
(->> line
|
2020-09-01 11:17:43 +02:00
|
|
|
ivy-clipmenu-line-to-content
|
|
|
|
ivy-clipmenu-do-copy)))))
|
2020-01-16 15:49:50 +01:00
|
|
|
|
|
|
|
(provide 'ivy-clipmenu)
|
|
|
|
;;; ivy-clipmenu.el ends here
|