Ensure clipmenu/list-clips output matches clipmenu

clipmenu/list-clips previously didn't sort or deduplicate entries in the same
way that the existing clipmenu list_clips function did. After running some
tests, clipmenu/list-clips matches the output except I'm unsure my duplicate
algorithm is identical.
This commit is contained in:
William Carroll 2020-01-16 01:22:05 +00:00
parent b20fe610a4
commit 25314ff20c

View file

@ -66,33 +66,41 @@
"Glob pattern matching the locations on disk for clipmenu's labels.") "Glob pattern matching the locations on disk for clipmenu's labels.")
(defcustom clipmenu/history-length (defcustom clipmenu/history-length
(or (getenv "CM_HISTLENGTH") 20) (or (getenv "CM_HISTLENGTH") 50)
"Limit the number of clips in the history. "Limit the number of clips in the history.
This value defaults to 20.") This value defaults to 50.")
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Functions ;; Functions
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; TODO: Ensure the clips are sorted in a LRU order. (defun clipmenu/parse-line (x)
;; TODO: Ensure entries are deduped. "Parse the entry in the clipmenu's line-cache."
;; TODO: Ensure multiline entries can be handled. (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 () (defun clipmenu/list-clips ()
"Return a list of the content of all of the clips." "Return a list of the content of all of the clips."
(->> clipmenu/cache-file-pattern (->> clipmenu/cache-file-pattern
f-glob f-glob
(-map (lambda (path) (-map (lambda (path)
(->> path f-read (s-split "\n")))) (s-split "\n" (f-read path) t)))
-flatten -flatten
(-reject #'s-blank?)
(-sort (lambda (a b) (-sort (lambda (a b)
(> (->> a (s-split " ") (nth 0) string-to-number) (< (clipmenu/parse-line a)
(->> b (s-split " ") (nth 0) string-to-number)))) (clipmenu/parse-line b))))
(-map (lambda (entry) (-map #'clipmenu/parse-content)
(->> entry (s-split " ") (nth 1)))) list/dedupe-adjacent
;; TODO: Here we should actually only be deleting adjacent
;; duplicates. This will be both faster and more similar to the behavior
;; of the clipmenu program the author wrote.
delete-dups
(-take clipmenu/history-length))) (-take clipmenu/history-length)))
;; TODO: Add tests. ;; TODO: Add tests.
@ -102,55 +110,38 @@ This value defaults to 20.")
(s-replace "\"" "\\\"") (s-replace "\"" "\\\"")
(s-replace "'" "\\'"))) (s-replace "'" "\\'")))
;; TODO: Properly handle errors when the file doesn't exist.
(defun clipmenu/line-to-clip (line) (defun clipmenu/line-to-clip (line)
"Map the chosen LINE to a clip stored on disk." "Map the chosen LINE to a clip stored on disk."
(->> line (->> line
clipmenu/cksum clipmenu/checksum
(f-join clipmenu/cache-directory) (f-join clipmenu/cache-directory)
f-read f-read
clipboard/copy)) clipboard/copy))
;; TODO: Consider supporting :history keyword. ;; TODO: Consider supporting :history keyword.
;; TODO: Ensure ivy maintains the sort from `clipmenu/list-clips'.
;; TODO: Ensure you can handle special characters like: ;; TODO: Ensure you can handle special characters like:
;; r}_rh,pmj~kCR.<5w"PUk#Z^>. ;; r}_rh,pmj~kCR.<5w"PUk#Z^>.
;; TODO: Consider adding tests.
(defun clipmenu/ivy-copy () (defun clipmenu/ivy-copy ()
"Use `ivy-read' to select and copy a clip." "Use `ivy-read' to select and copy a clip."
(interactive) (interactive)
(let ((ivy-sort-functions-alist nil))
(ivy-read "Clipmenu: " (ivy-read "Clipmenu: "
(clipmenu/list-clips) (clipmenu/list-clips)
:action #'clipmenu/line-to-clip)) :action #'clipmenu/line-to-clip)))
;; TODO: Delete this once `clipmenu/ivy-copy' is working as expected. (defun clipmenu/checksum (content)
;; TODO: Use this to compare behavior with `clipmenu/ivy-copy'. These functions
;; should behave in almost exactly the same way.
(defun clipmenu/dmenu-copy ()
"Call clipmenu with dmenu as the client."
(interactive)
(prelude/start-process
:name "clipboard/select"
:command "clipmenu"))
;; TODO: Write a faster alternative because this currently takes 1/2s to run,
;; which is ridiculous. Perhaps `call-process' is what we need.
(defun clipmenu/cksum (content)
"Return the CRC checksum of CONTENT." "Return the CRC checksum of CONTENT."
(->> (shell-command-to-string (s-trim-right
(format "zsh -c 'cksum <<<\"%s\"'" (prelude/call-process-to-string
;; TODO: I'm not sure this is working as intended. "/bin/bash" "-c" (string/format "/usr/bin/cksum <<<'%s'" content))))
(clipmenu/escape-quotes content)))
s-trim-right))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Keybindings ;; Keybindings
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(when clipmenu/install-kbds? (when clipmenu/install-kbds?
;; TODO: Delete this once `clipmenu/ivy-copy' is working as expected.
(exwm-input-set-key
(kbd "C-M-S-v") #'clipmenu/dmenu-copy)
(exwm-input-set-key (exwm-input-set-key
(kbd "C-M-v") #'clipmenu/ivy-copy)) (kbd "C-M-v") #'clipmenu/ivy-copy))