diff options
Diffstat (limited to 'users/wpcarro/emacs/.emacs.d/wpc')
52 files changed, 295 insertions, 4036 deletions
diff --git a/users/wpcarro/emacs/.emacs.d/wpc/al.el b/users/wpcarro/emacs/.emacs.d/wpc/al.el deleted file mode 100644 index 3cf98fee29..0000000000 --- a/users/wpcarro/emacs/.emacs.d/wpc/al.el +++ /dev/null @@ -1,254 +0,0 @@ -;;; al.el --- Interface for working with associative lists -*- lexical-binding: t -*- - -;; Author: William Carroll <wpcarro@gmail.com> -;; Version: 0.0.1 -;; Package-Requires: ((emacs "25.1")) - -;;; Commentary: -;; Firstly, a rant: -;; In most cases, I find Elisp's APIs to be confusing. There's a mixture of -;; overloaded functions that leak the implementation details (TODO: provide an -;; example of this.) of the abstract data type, which I find privileges those -;; "insiders" who spend disproportionately large amounts of time in Elisp land, -;; and other functions with little-to-no pattern about the order in which -;; arguments should be applied. In theory, however, most of these APIs could -;; and should be much simpler. This module represents a step in that direction. -;; -;; I'm modelling these APIs after Elixir's APIs. -;; -;; On my wishlist is to create protocols that will allow generic interfaces like -;; Enum protocols, etc. Would be nice to abstract over... -;; - associative lists (i.e. alists) -;; - property lists (i.e. plists) -;; - hash tables -;; ...with some dictionary or map-like interface. This will probably end up -;; being quite similar to the kv.el project but with differences at the API -;; layer. -;; -;; Similar libraries: -;; - map.el: Comes bundled with recent versions of Emacs. -;; - asoc.el: Helpers for working with alists. asoc.el is similar to alist.el -;; because it uses the "!" convention for signalling that a function mutates -;; the underlying data structure. -;; - ht.el: Hash table library. -;; - kv.el: Library for dealing with key-value collections. Note that map.el -;; has a similar typeclass because it works with lists, hash-tables, or -;; arrays. -;; - a.el: Clojure-inspired way of working with key-value data structures in -;; Elisp. Works with alists, hash-tables, and sometimes vectors. -;; -;; Some API design principles: -;; - The "noun" (i.e. alist) of the "verb" (i.e. function) comes last to improve -;; composability with the threading macro (i.e. `->>') and to improve consumers' -;; intuition with the APIs. Learn this once, know it always. -;; -;; - Every function avoids mutating the alist unless it ends with !. -;; -;; - CRUD operations will be named according to the following table: -;; - "create" *and* "set" -;; - "read" *and* "get" -;; - "update" -;; - "delete" *and* "remove" -;; -;; For better or worse, all of this code expects alists in the form of: -;; ((first-name . "William") (last-name . "Carroll")) -;; -;; Special thanks to github.com/alphapapa/emacs-package-dev-handbook for some of -;; the idiomatic ways to update alists. -;; -;; TODO: Include a section that compares alist.el to a.el from -;; github.com/plexus/a.el. - -;;; Code: - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Dependencies: -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -(require 'macros) -(require 'dash) -(require 'tuple) -(require 'maybe) - -;; TODO: Support function aliases for: -;; - create/set -;; - read/get -;; - update -;; - delete/remove - -;; Support mutative variants of functions with an ! appendage to their name. - -;; Ensure that the same message about only updating the first occurrence of a -;; key is consistent throughout documentation using string interpolation or some -;; other mechanism. - -;; TODO: Consider wrapping all of this with `(cl-defstruct alist xs)'. - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Constants -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -(defconst al-enable-tests? t - "When t, run the test suite.") - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Library -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -;; TODO: Support a variadic version of this to easily construct alists. -(defun al-new () - "Return a new, empty alist." - '()) - -;; Create -;; TODO: See if this mutates. -(defun al-set (k v xs) - "Set K to V in XS." - (if (al-has-key? k xs) - (progn - ;; Note: this is intentional `alist-get' and not `al-get'. - (setf (alist-get k xs) v) - xs) - (list-cons `(,k . ,v) xs))) - -(defun al-set! (k v xs) - "Set K to V in XS mutatively. -Note that this doesn't append to the alist in the way that most alists handle - writing. If the k already exists in XS, it is overwritten." - (map-delete xs k) - (map-put! xs k v)) - -;; Read -(defun al-get (k xs) - "Return the value at K in XS; otherwise, return nil. -Returns the first occurrence of K in XS since alists support multiple entries." - (cdr (assoc k xs))) - -(defun al-get-entry (k xs) - "Return the first key-value pair at K in XS." - (assoc k xs)) - -;; Update -;; TODO: Add warning about only the first occurrence being updated in the -;; documentation. -(defun al-update (k f xs) - "Apply F to the value stored at K in XS. -If `K' is not in `XS', this function errors. Use `al-upsert' if you're -interested in inserting a value when a key doesn't already exist." - (if (not (al-has-key? k xs)) - (error "Refusing to update: key does not exist in alist") - (al-set k (funcall f (al-get k xs)) xs))) - -(defun al-update! (k f xs) - "Call F on the entry at K in XS. -Mutative variant of `al-update'." - (al-set! k (funcall f (al-get k xs))xs)) - -;; TODO: Support this. -(defun al-upsert (k v f xs) - "If K exists in `XS' call `F' on the value otherwise insert `V'." - (if (al-has-key? k xs) - (al-update k f xs) - (al-set k v xs))) - -;; Delete -;; TODO: Make sure `delete' and `remove' behave as advertised in the Elisp docs. -(defun al-delete (k xs) - "Deletes the entry of K from XS. -This only removes the first occurrence of K, since alists support multiple - key-value entries. See `al-delete-all' and `al-dedupe'." - (remove (assoc k xs) xs)) - -(defun al-delete! (k xs) - "Delete the entry of K from XS. -Mutative variant of `al-delete'." - (delete (assoc k xs) xs)) - -;; Additions to the CRUD API -;; TODO: Implement this function. -(defun al-dedupe-keys (xs) - "Remove the entries in XS where the keys are `equal'.") - -(defun al-dedupe-entries (xs) - "Remove the entries in XS where the key-value pair are `equal'." - (delete-dups xs)) - -(defun al-keys (xs) - "Return a list of the keys in XS." - (mapcar 'car xs)) - -(defun al-values (xs) - "Return a list of the values in XS." - (mapcar 'cdr xs)) - -(defun al-has-key? (k xs) - "Return t if XS has a key `equal' to K." - (maybe-some? (assoc k xs))) - -(defun al-has-value? (v xs) - "Return t if XS has a value of V." - (maybe-some? (rassoc v xs))) - -(defun al-count (xs) - "Return the number of entries in XS." - (length xs)) - -;; TODO: Should I support `al-find-key' and `al-find-value' variants? -(defun al-find (p xs) - "Find an element in XS. - -Apply a predicate fn, P, to each key and value in XS and return the key of the -first element that returns t." - (let ((result (list-find (lambda (x) (funcall p (car x) (cdr x))) xs))) - (if result - (car result) - nil))) - -(defun al-map-keys (f xs) - "Call F on the values in XS, returning a new alist." - (list-map (lambda (x) - `(,(funcall f (car x)) . ,(cdr x))) - xs)) - -(defun al-map-values (f xs) - "Call F on the values in XS, returning a new alist." - (list-map (lambda (x) - `(,(car x) . ,(funcall f (cdr x)))) - xs)) - -(defun al-reduce (acc f xs) - "Return a new alist by calling F on k v and ACC from XS. -F should return a tuple. See tuple.el for more information." - (->> (al-keys xs) - (list-reduce acc - (lambda (k acc) - (funcall f k (al-get k xs) acc))))) - -(defun al-merge (a b) - "Return a new alist with a merge of alists, A and B. -In this case, the last writer wins, which is B." - (al-reduce a #'al-set b)) - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Tests -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -(when al-enable-tests? - (prelude-assert - (equal '((2 . one) - (3 . two)) - (al-map-keys #'1+ - '((1 . one) - (2 . two))))) - (prelude-assert - (equal '((one . 2) - (two . 3)) - (al-map-values #'1+ - '((one . 1) - (two . 2)))))) - - -;; TODO: Support test cases for the entire API. - -(provide 'al) -;;; al.el ends here diff --git a/users/wpcarro/emacs/.emacs.d/wpc/bag.el b/users/wpcarro/emacs/.emacs.d/wpc/bag.el deleted file mode 100644 index 467e25fceb..0000000000 --- a/users/wpcarro/emacs/.emacs.d/wpc/bag.el +++ /dev/null @@ -1,70 +0,0 @@ -;;; bag.el --- Working with bags (aka multi-sets) -*- lexical-binding: t -*- - -;; Author: William Carroll <wpcarro@gmail.com> -;; Version: 0.0.1 -;; Package-Requires: ((emacs "24.3")) - -;;; Commentary: -;; What is a bag? A bag should be thought of as a frequency table. It's a way -;; to convert a list of something into a set that allows duplicates. Isn't -;; allowing duplicates the whole thing with Sets? Kind of. But the interface -;; of Sets is something that bags resemble, so multi-set isn't as bag of a name -;; as it may first seem. -;; -;; If you've used Python's collections.Counter, the concept of a bag should be -;; familiar already. -;; -;; Interface: -;; - add :: x -> Bag(x) -> Bag(x) -;; - remove :: x -> Bag(x) -> Bag(x) -;; - union :: Bag(x) -> Bag(x) -> Bag(x) -;; - difference :: Bag(x) -> Bag(x) -> Bag(x) - -;;; Code: - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Dependencies -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -(require 'al) -(require 'number) - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Library -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -(cl-defstruct bag xs) - -(defun bag-update (f xs) - "Call F on alist in XS." - (let ((ys (bag-xs xs))) - (setf (bag-xs xs) (funcall f ys)))) - -(defun bag-new () - "Create an empty bag." - (make-bag :xs (al-new))) - -(defun bag-contains? (x xs) - "Return t if XS has X." - (al-has-key? x (bag-xs xs))) - -;; TODO: Tabling this for now since working with structs seems to be -;; disappointingly difficult. Where is `struct-update'? -;; (defun bag-add (x xs) -;; "Add X to XS.") - -;; TODO: What do we name delete vs. remove? -;; (defun bag-remove (x xs) -;; "Remove X from XS. -;; This is a no-op is X doesn't exist in XS.") - -(defun bag-from-list (xs) - "Map a list of `XS' into a bag." - (->> xs - (list-reduce - (bag-new) - (lambda (x acc) - (bag-add x 1 #'number-inc acc))))) - -(provide 'bag) -;;; bag.el ends here diff --git a/users/wpcarro/emacs/.emacs.d/wpc/bookmark.el b/users/wpcarro/emacs/.emacs.d/wpc/bookmark.el deleted file mode 100644 index c5e3bf3ac9..0000000000 --- a/users/wpcarro/emacs/.emacs.d/wpc/bookmark.el +++ /dev/null @@ -1,89 +0,0 @@ -;;; bookmark.el --- Saved files and directories on my filesystem -*- lexical-binding: t -*- - -;; Author: William Carroll <wpcarro@gmail.com> -;; Version: 0.0.1 -;; Package-Requires: ((emacs "24.3")) - -;;; Commentary: -;; After enjoying and relying on Emacs's builtin `jump-to-register' command, I'd -;; like to recreate this functionality with a few extensions. -;; -;; Everything herein will mimmick my previous KBDs for `jump-to-register', which -;; were <leader>-j-<register-kbd>. If the `bookmark-path' is a file, Emacs will -;; open a buffer with that file. If the `bookmark-path' is a directory, Emacs -;; will open an ivy window searching that directory. - -;;; Code: - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Dependencies -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -(require 'f) -(require 'buffer) -(require 'dash) -(require 'string) -(require 'set) -(require 'constants) -(require 'general) -(require 'tvl) - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Constants -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -(cl-defstruct bookmark label path kbd) - -(defun bookmark-handle-directory-dwim (path) - "Open PATH as either a project directory or a regular directory." - (with-temp-buffer - (cd path) - (call-interactively #'project-find-file))) - -(defconst bookmark-handle-directory #'bookmark-handle-directory-dwim - "Function to call when a bookmark points to a directory.") - -(defconst bookmark-handle-file #'counsel-find-file-action - "Function to call when a bookmark points to a file.") - -(defconst bookmark-whitelist - (list - (make-bookmark :label "depot" - :path tvl-depot-path - :kbd "d")) - "List of registered bookmarks.") - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; API -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -(defun bookmark-open (b) - "Open bookmark, B, in a new buffer or an ivy minibuffer." - (let ((path (bookmark-path b))) - (cond - ((f-directory? path) - (funcall bookmark-handle-directory path)) - ((f-file? path) - (funcall bookmark-handle-file path))))) - -(defun bookmark-install-kbd (b) - "Define two functions to explore B and assign them to keybindings." - (eval `(defun ,(intern (format "bookmark-visit-%s" (bookmark-label b))) () - (interactive) - (find-file ,(bookmark-path b)))) - (eval `(defun ,(intern (format "bookmark-browse-%s" (bookmark-label b))) () - (interactive) - (bookmark-open ,b))) - (general-define-key - :prefix "<SPC>" - :states '(motion) - (format "J%s" (bookmark-kbd b)) `,(intern (format "bookmark-visit-%s" (bookmark-label b))) - (format "j%s" (bookmark-kbd b)) `,(intern (format "bookmark-browse-%s" (bookmark-label b))))) - -(defun bookmark-install-kbds () - "Install the keybindings defined herein." - (->> bookmark-whitelist - (-map #'bookmark-install-kbd))) - -(provide 'bookmark) -;;; bookmark.el ends here diff --git a/users/wpcarro/emacs/.emacs.d/wpc/buffer.el b/users/wpcarro/emacs/.emacs.d/wpc/buffer.el index fa98393df8..0f86f7f811 100644 --- a/users/wpcarro/emacs/.emacs.d/wpc/buffer.el +++ b/users/wpcarro/emacs/.emacs.d/wpc/buffer.el @@ -33,6 +33,7 @@ (require 'struct) (require 'ts) (require 'general) +(require 'list) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Library @@ -142,12 +143,12 @@ Return a reference to that buffer." (defun buffer-cycle-next () "Cycle forward through the `buffer-source-code-buffers'." (interactive) - (buffer-cycle #'cycle-next)) + (buffer-cycle #'cycle-next!)) (defun buffer-cycle-prev () "Cycle backward through the `buffer-source-code-buffers'." (interactive) - (buffer-cycle #'cycle-prev)) + (buffer-cycle #'cycle-prev!)) (defun buffer-ivy-source-code () "Use `ivy-read' to choose among all open source code buffers." diff --git a/users/wpcarro/emacs/.emacs.d/wpc/bytes.el b/users/wpcarro/emacs/.emacs.d/wpc/bytes.el deleted file mode 100644 index b76921d3c7..0000000000 --- a/users/wpcarro/emacs/.emacs.d/wpc/bytes.el +++ /dev/null @@ -1,112 +0,0 @@ -;;; bytes.el --- Working with byte values -*- lexical-binding: t -*- - -;; Author: William Carroll <wpcarro@gmail.com> -;; Version: 0.0.1 -;; Package-Requires: ((emacs "24.3")) - -;;; Commentary: -;; Functions to help with human-readable representations of byte values. -;; -;; Usage: -;; See the test cases for example usage. Or better yet, I should use a type of -;; structured documentation that would allow me to expose a view into the test -;; suite here. Is this currently possible in Elisp? -;; -;; API: -;; - serialize :: Integer -> String -;; -;; Wish list: -;; - Rounding: e.g. (bytes (* 1024 1.7)) => "2KB" - -;;; Code: - -;; TODO: Support -ibabyte variants like Gibibyte (GiB). - -;; Ranges: -;; B: [ 0, 1e3) -;; KB: [ 1e3, 1e6) -;; MB: [ 1e6, 1e6) -;; GB: [ 1e9, 1e12) -;; TB: [1e12, 1e15) -;; PB: [1e15, 1e18) -;; -;; Note: I'm currently not support exabytes because that causes the integer to -;; overflow. I imagine a larger integer type may exist, but for now, I'll -;; treat this as a YAGNI. - -(require 'prelude) -(require 'tuple) -(require 'math) -(require 'number) - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Constants -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -(defconst bytes-kb (math-exp 2 10) - "Number of bytes in a kilobyte.") - -(defconst bytes-mb (math-exp 2 20) - "Number of bytes in a megabytes.") - -(defconst bytes-gb (math-exp 2 30) - "Number of bytes in a gigabyte.") - -(defconst bytes-tb (math-exp 2 40) - "Number of bytes in a terabyte.") - -(defconst bytes-pb (math-exp 2 50) - "Number of bytes in a petabyte.") - -(defconst bytes-eb (math-exp 2 60) - "Number of bytes in an exabyte.") - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Functions -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -(defun bytes-classify (x) - "Return unit that closest fits byte count, X." - (prelude-assert (number-whole? x)) - (cond - ((and (>= x 0) (< x bytes-kb)) 'byte) - ((and (>= x bytes-kb) (< x bytes-mb)) 'kilobyte) - ((and (>= x bytes-mb) (< x bytes-gb)) 'megabyte) - ((and (>= x bytes-gb) (< x bytes-tb)) 'gigabyte) - ((and (>= x bytes-tb) (< x bytes-pb)) 'terabyte) - ((and (>= x bytes-pb) (< x bytes-eb)) 'petabyte))) - -(defun bytes-to-string (x) - "Convert integer X into a human-readable string." - (let ((base-and-unit - (pcase (bytes-classify x) - ('byte (tuple/from 1 "B")) - ('kilobyte (tuple/from bytes-kb "KB")) - ('megabyte (tuple/from bytes-mb "MB")) - ('gigabyte (tuple/from bytes-gb "GB")) - ('terabyte (tuple/from bytes-tb "TB")) - ('petabyte (tuple/from bytes-pb "PB"))))) - (string-format "%d%s" - (round x (tuple/first base-and-unit)) - (tuple/second base-and-unit)))) - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Tests -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -(progn - (prelude-assert - (equal "1000B" (bytes-to-string 1000))) - (prelude-assert - (equal "2KB" (bytes-to-string (* 2 bytes-kb)))) - (prelude-assert - (equal "17MB" (bytes-to-string (* 17 bytes-mb)))) - (prelude-assert - (equal "419GB" (bytes-to-string (* 419 bytes-gb)))) - (prelude-assert - (equal "999TB" (bytes-to-string (* 999 bytes-tb)))) - (prelude-assert - (equal "2PB" (bytes-to-string (* 2 bytes-pb))))) - -(provide 'bytes) -;;; bytes.el ends here diff --git a/users/wpcarro/emacs/.emacs.d/wpc/cache.el b/users/wpcarro/emacs/.emacs.d/wpc/cache.el deleted file mode 100644 index 70ebdb71ef..0000000000 --- a/users/wpcarro/emacs/.emacs.d/wpc/cache.el +++ /dev/null @@ -1,88 +0,0 @@ -;;; cache.el --- Caching things -*- lexical-binding: t -*- - -;; Author: William Carroll <wpcarro@gmail.com> -;; Version: 0.0.1 -;; Package-Requires: ((emacs "24.3")) - -;;; Commentary: -;; An immutable cache data structure. -;; -;; This is like a sideways stack, that you can pull values out from and re-push -;; to the top. It'd be like a stack supporting push, pop, pull. -;; -;; This isn't a key-value data-structure like you might expect from a -;; traditional cache. The name is subject to change, but the underlying idea of -;; a cache remains the same. -;; -;; Think about prescient.el, which uses essentially an LRU cache integrated into -;; counsel to help create a "clairovoyant", self-organizing list. -;; -;; Use-cases: -;; - Keeps an cache of workspaces sorted as MRU with an LRU eviction strategy. - -;;; Code: - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Dependencies -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -(require 'prelude) -(require 'struct) -(require '>) - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Library -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -(cl-defstruct cache xs) - -;; TODO: Prefer another KBD for yasnippet form completion than company-mode's -;; current KBD. - -(defun cache-from-list (xs) - "Turn list, XS, into a cache." - (make-cache :xs xs)) - -(defun cache-contains? (x xs) - "Return t if X in XS." - (->> xs - cache-xs - (list-contains? x))) - -(defun cache-touch (x xs) - "Ensure value X in cache, XS, is front of the list. -If X isn't in XS (using `equal'), insert it at the front." - (struct-update - cache - xs - (>-> (list-reject (lambda (y) (equal x y))) - (list-cons x)) - xs)) - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Tests -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -(progn - (let ((cache (cache-from-list '("chicken" "nugget")))) - ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - ;; contains?/2 - ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - (prelude-refute - (cache-contains? "turkey" cache)) - (prelude-assert - (cache-contains? "chicken" cache)) - ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - ;; touch/2 - ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - (prelude-assert - (equal - (cache-touch "nugget" cache) - (cache-from-list '("nugget" "chicken")))) - (prelude-assert - (equal - (cache-touch "spicy" cache) - (cache-from-list '("spicy" "chicken" "nugget")))))) - -(provide 'cache) -;;; cache.el ends here diff --git a/users/wpcarro/emacs/.emacs.d/wpc/clipboard.el b/users/wpcarro/emacs/.emacs.d/wpc/clipboard.el index 1c14eebae1..ec2a46f540 100644 --- a/users/wpcarro/emacs/.emacs.d/wpc/clipboard.el +++ b/users/wpcarro/emacs/.emacs.d/wpc/clipboard.el @@ -9,9 +9,6 @@ ;; ;; Integrate with bburns/clipmon so that System Clipboard can integrate with ;; Emacs's kill-ring. -;; -;; Wish list: -;; - Create an Emacs integration with github.com/cdown/clipmenud. ;;; Code: diff --git a/users/wpcarro/emacs/.emacs.d/wpc/colorscheme.el b/users/wpcarro/emacs/.emacs.d/wpc/colorscheme.el deleted file mode 100644 index cc2afd6c57..0000000000 --- a/users/wpcarro/emacs/.emacs.d/wpc/colorscheme.el +++ /dev/null @@ -1,85 +0,0 @@ -;;; colorscheme.el --- Syntax highlight and friends -*- lexical-binding: t -*- - -;; Author: William Carroll <wpcarro@gmail.com> -;; Version: 0.0.1 -;; Package-Requires: ((emacs "24.3")) - -;;; Commentary: -;; -;; TODO: Clarify this. -;; Since I have my own definition of "theme", which couples wallpaper, font, -;; with Emacs's traditional notion of the word "theme", I'm choosing to use -;; "colorscheme" to refer to *just* the notion of syntax highlight etc. - -;;; Code: - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Dependencies -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -(require 'cycle) -(require '>) -(require 'cl-lib) - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Library -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -(defcustom colorscheme-whitelist - (cycle-from-list - (->> (custom-available-themes) - (list-map #'symbol-name) - (list-filter (>-> (s-starts-with? "doom-"))) - (list-map #'intern))) - "The whitelist of colorschemes through which to cycle.") - -(defun colorscheme-current () - "Return the currently enabled colorscheme." - (cycle-current colorscheme-whitelist)) - -(defun colorscheme-disable-all () - "Disable all currently enabled colorschemes." - (interactive) - (->> custom-enabled-themes - (list-map #'disable-theme))) - -(defun colorscheme-set (theme) - "Call `load-theme' with `THEME', ensuring that the line numbers are bright. -There is no hook that I'm aware of to handle this more elegantly." - (load-theme theme t) - (prelude-set-line-number-color "#da5468")) - -(defun colorscheme-whitelist-set (colorscheme) - "Focus the COLORSCHEME in the `colorscheme-whitelist' cycle." - (cycle-focus (lambda (x) (equal x colorscheme)) colorscheme-whitelist) - (colorscheme-set (colorscheme-current))) - -(defun colorscheme-ivy-select () - "Load a colorscheme using ivy." - (interactive) - (let ((theme (ivy-read "Theme: " (cycle-to-list colorscheme-whitelist)))) - (colorscheme-disable-all) - (colorscheme-set (intern theme)))) - -(cl-defun colorscheme-cycle (&key forward?) - "Cycle next if `FORWARD?' is non-nil. -Cycle prev otherwise." - (disable-theme (cycle-current colorscheme-whitelist)) - (let ((theme (if forward? - (cycle-next colorscheme-whitelist) - (cycle-prev colorscheme-whitelist)))) - (colorscheme-set theme) - (message (s-concat "Active theme: " (symbol-to-string theme))))) - -(defun colorscheme-next () - "Disable the currently active theme and load the next theme." - (interactive) - (colorscheme-cycle :forward? t)) - -(defun colorscheme-prev () - "Disable the currently active theme and load the previous theme." - (interactive) - (colorscheme-cycle :forward? nil)) - -(provide 'colorscheme) -;;; colorscheme.el ends here diff --git a/users/wpcarro/emacs/.emacs.d/wpc/constants.el b/users/wpcarro/emacs/.emacs.d/wpc/constants.el index 69003f5955..48bcd9042f 100644 --- a/users/wpcarro/emacs/.emacs.d/wpc/constants.el +++ b/users/wpcarro/emacs/.emacs.d/wpc/constants.el @@ -20,7 +20,10 @@ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (defconst constants-ci? (maybe-some? (getenv "CI")) - "Encoded as t when Emacs is running in CI.") + "Defined as t when Emacs is running in CI.") + +(defconst constants-osx? (eq system-type 'darwin) + "Defined as t when OSX is running.") (provide 'constants) ;;; constants.el ends here diff --git a/users/wpcarro/emacs/.emacs.d/wpc/cycle.el b/users/wpcarro/emacs/.emacs.d/wpc/cycle.el deleted file mode 100644 index a1853ece14..0000000000 --- a/users/wpcarro/emacs/.emacs.d/wpc/cycle.el +++ /dev/null @@ -1,224 +0,0 @@ -;;; cycle.el --- Simple module for working with cycles -*- lexical-binding: t -*- - -;; Author: William Carroll <wpcarro@gmail.com> -;; Version: 0.0.1 -;; Package-Requires: ((emacs "24.3")) - -;;; Commentary: -;; Something like this may already exist, but I'm having trouble finding it, and -;; I think writing my own is a nice exercise for learning more Elisp. - -;;; Code: - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Dependencies -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -(require 'prelude) -(require 'math) -(require 'maybe) -(require 'struct) -(require 'cl-lib) - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Wish list -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -;; - TODO: Provide immutable variant. -;; - TODO: Replace mutable consumption with immutable variant. -;; - TODO: Replace indexing with (math-mod current cycle). - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Library -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -;; `current-index' tracks the current index -;; `xs' is the original list -(cl-defstruct cycle current-index previous-index xs) - -(defconst cycle-enable-tests? t - "When t, run the tests defined herein.") - -(defun cycle-from-list (xs) - "Create a cycle from a list of `XS'." - (if (= 0 (length xs)) - (make-cycle :current-index nil - :previous-index nil - :xs xs) - (make-cycle :current-index 0 - :previous-index nil - :xs xs))) - -(defun cycle-new (&rest xs) - "Create a cycle with XS as the values." - (cycle-from-list xs)) - -(defun cycle-to-list (xs) - "Return the list representation of a cycle, XS." - (cycle-xs xs)) - -(defun cycle--next-index<- (lo hi x) - "Return the next index in a cycle when moving downwards. -- `LO' is the lower bound. -- `HI' is the upper bound. -- `X' is the current index." - (if (< (- x 1) lo) - (- hi 1) - (- x 1))) - -(defun cycle--next-index-> (lo hi x) - "Return the next index in a cycle when moving upwards. -- `LO' is the lower bound. -- `HI' is the upper bound. -- `X' is the current index." - (if (>= (+ 1 x) hi) - lo - (+ 1 x))) - -(defun cycle-previous-focus (cycle) - "Return the previously focused entry in CYCLE." - (let ((i (cycle-previous-index cycle))) - (if (maybe-some? i) - (nth i (cycle-xs cycle)) - nil))) - -;; TODO: Consider adding "!" to the function name herein since many of them -;; mutate the collection, and the APIs are beginning to confuse me. -(defun cycle-focus-previous! (xs) - "Jump to the item in XS that was most recently focused; return the cycle. -This will error when previous-index is nil. This function mutates the -underlying struct." - (let ((i (cycle-previous-index xs))) - (if (maybe-some? i) - (progn - (cycle-jump i xs) - (cycle-current xs)) - (error "Cannot focus the previous element since cycle-previous-index is nil")))) - -(defun cycle-next (xs) - "Return the next value in `XS' and update `current-index'." - (let* ((current-index (cycle-current-index xs)) - (next-index (cycle--next-index-> 0 (cycle-count xs) current-index))) - (struct-set! cycle previous-index current-index xs) - (struct-set! cycle current-index next-index xs) - (nth next-index (cycle-xs xs)))) - -(defun cycle-prev (xs) - "Return the previous value in `XS' and update `current-index'." - (let* ((current-index (cycle-current-index xs)) - (next-index (cycle--next-index<- 0 (cycle-count xs) current-index))) - (struct-set! cycle previous-index current-index xs) - (struct-set! cycle current-index next-index xs) - (nth next-index (cycle-xs xs)))) - -(defun cycle-current (cycle) - "Return the current value in `CYCLE'." - (nth (cycle-current-index cycle) (cycle-xs cycle))) - -(defun cycle-count (cycle) - "Return the length of `xs' in `CYCLE'." - (length (cycle-xs cycle))) - -(defun cycle-jump (i xs) - "Jump to the I index of XS." - (let ((current-index (cycle-current-index xs)) - (next-index (math-mod i (cycle-count xs)))) - (struct-set! cycle previous-index current-index xs) - (struct-set! cycle current-index next-index xs)) - xs) - -(defun cycle-focus (p cycle) - "Focus the element in CYCLE for which predicate, P, is t." - (let ((i (->> cycle - cycle-xs - (-find-index p)))) - (if i - (cycle-jump i cycle) - (error "No element in cycle matches predicate")))) - -(defun cycle-focus-item (x xs) - "Focus item, X, in cycle XS. -ITEM is the first item in XS that t for `equal'." - (cycle-focus (lambda (y) (equal x y)) xs)) - -(defun cycle-contains? (x xs) - "Return t if cycle, XS, has member X." - (->> xs - cycle-xs - (list-contains? x))) - -(defun cycle-empty? (xs) - "Return t if cycle XS has no elements." - (= 0 (length (cycle-xs xs)))) - -(defun cycle-focused? (xs) - "Return t if cycle XS has a non-nil value for current-index." - (maybe-some? (cycle-current-index xs))) - -(defun cycle-append (x xs) - "Add X to the left of the focused element in XS. -If there is no currently focused item, add X to the beginning of XS." - (if (cycle-empty? xs) - (progn - (struct-set! cycle xs (list x) xs) - (struct-set! cycle current-index 0 xs) - (struct-set! cycle previous-index nil xs)) - (let ((curr-i (cycle-current-index xs)) - (prev-i (cycle-previous-index xs))) - (if curr-i - (progn - (struct-set! cycle xs (-insert-at curr-i x (cycle-xs xs)) xs) - (when (and prev-i (>= prev-i curr-i)) - (struct-set! cycle previous-index (1+ prev-i) xs)) - (when curr-i (struct-set! cycle current-index (1+ curr-i) xs))) - (progn - (struct-set! cycle xs (cons x (cycle-xs xs)) xs) - (when prev-i (struct-set! cycle previous-index (1+ prev-i) xs)))) - xs))) - -(defun cycle-remove (x xs) - "Attempt to remove X from XS. - -X is found using `equal'. - -If X is the currently focused value, after it's deleted, current-index will be - nil. If X is the previously value, after it's deleted, previous-index will be - nil." - (let ((curr-i (cycle-current-index xs)) - (prev-i (cycle-previous-index xs)) - (rm-i (-elem-index x (cycle-xs xs)))) - (struct-set! cycle xs (-remove-at rm-i (cycle-xs xs)) xs) - (when prev-i - (when (> prev-i rm-i) (struct-set! cycle previous-index (1- prev-i) xs)) - (when (= prev-i rm-i) (struct-set! cycle previous-index nil xs))) - (when curr-i - (when (> curr-i rm-i) (struct-set! cycle current-index (1- curr-i) xs)) - (when (= curr-i rm-i) (struct-set! cycle current-index nil xs))) - xs)) - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Tests -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -(when cycle-enable-tests? - (let ((xs (cycle-new 1 2 3))) - (prelude-assert (maybe-nil? (cycle-previous-focus xs))) - (prelude-assert (= 1 (cycle-current xs))) - (prelude-assert (= 2 (cycle-next xs))) - (prelude-assert (= 1 (cycle-previous-focus xs))) - (prelude-assert (= 1 (->> xs (cycle-jump 0) cycle-current))) - (prelude-assert (= 2 (->> xs (cycle-jump 1) cycle-current))) - (prelude-assert (= 3 (->> xs (cycle-jump 2) cycle-current))) - (prelude-assert (= 2 (cycle-previous-focus xs))) - (prelude-assert (= 2 (cycle-focus-previous! xs))) - (prelude-assert (equal '(1 4 2 3) (cycle-xs (cycle-append 4 xs)))) - (prelude-assert (equal '(1 2 3) (cycle-xs (cycle-remove 4 xs)))) - (progn - (cycle-focus-item 3 xs) - (cycle-focus-item 2 xs) - (cycle-remove 1 xs) - (prelude-assert (= 2 (cycle-current xs))) - (prelude-assert (= 3 (cycle-previous-focus xs)))))) - -(provide 'cycle) -;;; cycle.el ends here diff --git a/users/wpcarro/emacs/.emacs.d/wpc/device.el b/users/wpcarro/emacs/.emacs.d/wpc/device.el deleted file mode 100644 index 09819ad748..0000000000 --- a/users/wpcarro/emacs/.emacs.d/wpc/device.el +++ /dev/null @@ -1,62 +0,0 @@ -;;; device.el --- Physical device information -*- lexical-binding: t -*- - -;; Author: William Carroll <wpcarro@gmail.com> -;; Version: 0.0.1 -;; Package-Requires: ((emacs "25.1")) - -;;; Commentary: -;; Functions for querying device information. - -;;; Code: - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Dependencies -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -(require 'dash) -(require 'al) - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Library -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -;; TODO(wpcarro): Consider integrating this with Nix and depot instead of -;; denormalizing the state. -(defconst device-hostname->device - '(("zeno.lon.corp.google.com" . work-desktop-lon) - ("wpcarro.svl.corp.google.com" . work-desktop-svl) - ("seneca" . work-laptop) - ("marcus" . personal-laptop) - ("diogenes" . personal-vm)) - "Mapping hostname to a device symbol.") - -;; TODO: Should I generate these predicates? - -(defun device-classify () - "Return the device symbol for the current host or nil if not supported." - (al-get system-name device-hostname->device)) - -(defun device-work-laptop? () - "Return t if current device is work laptop." - (equal 'work-laptop - (device-classify))) - -(defun device-work-desktop? () - "Return t if current device is work desktop." - (-contains? '(work-desktop-lon - work-desktop-svl) - (device-classify))) - -(defun device-corporate? () - "Return t if the current device is owned by my company." - (-contains? '(work-desktop-lon - work-desktop-svl - work-laptop) - (device-classify))) - -(defun device-laptop? () - "Return t if the current device is a laptop." - (-contains? '(work-laptop personal-laptop) (device-classify))) - -(provide 'device) -;;; device.el ends here diff --git a/users/wpcarro/emacs/.emacs.d/wpc/dotted.el b/users/wpcarro/emacs/.emacs.d/wpc/dotted.el deleted file mode 100644 index b824ddbda7..0000000000 --- a/users/wpcarro/emacs/.emacs.d/wpc/dotted.el +++ /dev/null @@ -1,57 +0,0 @@ -;;; dotted.el --- Working with dotted pairs in Elisp -*- lexical-binding: t -*- - -;; Author: William Carroll <wpcarro@gmail.com> -;; Version: 0.0.1 -;; Package-Requires: ((emacs "24.3")) - -;;; Commentary: -;; Part of my primitives library extensions in Elisp. Contrast my primitives -;; with the wrapper extensions that I provide, which expose immutable variants -;; of data structures like an list, alist, tuple, as well as quasi-typeclasses -;; like sequence, etc. - -;;; Code: - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Dependencies -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -(require 'prelude) -(require 'macros) -(require 'cl-lib) - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Library -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -(cl-defun dotted-new (&optional a b) - "Create a new dotted pair of A and B." - (cons a b)) - -(defun dotted-instance? (x) - "Return t if X is a dotted pair." - (let ((b (cdr x))) - (and b (atom b)))) - -(defun dotted-first (x) - "Return the first element of X." - (car x)) - -(defun dotted-second (x) - "Return the second element of X." - (cdr x)) - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Tests -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -(progn - (prelude-assert - (equal '(fname . "Bob") (dotted-new 'fname "Bob"))) - (prelude-assert - (dotted-instance? '(one . two))) - (prelude-refute - (dotted-instance? '(1 2 3)))) - -(provide 'dotted) -;;; dotted.el ends here diff --git a/users/wpcarro/emacs/.emacs.d/wpc/fonts.el b/users/wpcarro/emacs/.emacs.d/wpc/fonts.el index 196b882862..0f70f69c2b 100644 --- a/users/wpcarro/emacs/.emacs.d/wpc/fonts.el +++ b/users/wpcarro/emacs/.emacs.d/wpc/fonts.el @@ -9,15 +9,10 @@ ;;; Code: -;; TODO: `defcustom' font-size. -;; TODO: `defcustom' fonts. - ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Dependencies ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -(require 'prelude) -(require 'cycle) (require 'maybe) (require 'cl-lib) @@ -25,93 +20,30 @@ ;; Constants ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; TODO: Troubleshoot why "8" appears so large on my desktop. - -;; TODO: Consider having a different font size when I'm using my 4K monitor. - -(defconst fonts-size "10" - "My preferred default font-size.") - -(defconst fonts-size-step 10 - "The amount (%) by which to increase or decrease a font.") - -(defconst fonts-hacker-news-recommendations - '("APL385 Unicode" - "Go Mono" - "Sudo" - "Monoid" - "Input Mono Medium" ;; NOTE: Also "Input Mono Thin" is nice. - ) - "List of fonts optimized for programming I found in a HN article.") - -(defconst fonts-whitelist - (cycle-from-list - (list-concat - fonts-hacker-news-recommendations - '("JetBrainsMono" - "Mononoki Medium" - "Monospace" - "Operator Mono Light" - "Courier" - "Andale Mono" - "Source Code Pro" - "Terminus"))) - "This is a list of my preferred fonts.") +(defgroup fonts nil + "Customize group for fonts configuration.") + +(defcustom fonts-size "10" + "My preferred default font-size." + :group 'fonts) + +(defcustom fonts-size-step 10 + "The amount (%) by which to increase or decrease a font." + :group 'fonts) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Functions ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; TODO: fonts and fonts-whitelist make it difficult to name functions like -;; fonts-set as a generic Emacs function vs choosing a font from the whitelist. - -(cl-defun fonts-cycle (&key forward?) - "Cycle forwards when `FORWARD?' non-nil." - (let ((font (if forward? - (cycle-next fonts-whitelist) - (cycle-prev fonts-whitelist)))) - (message (s-concat "Active font: " font)) - (fonts-set font))) - -(defun fonts-next () - "Quickly cycle through preferred fonts." - (interactive) - (fonts-cycle :forward? t)) - -(defun fonts-prev () - "Quickly cycle through preferred fonts." - (interactive) - (fonts-cycle :forward? nil)) - (defun fonts-set (font &optional size) "Change the font to `FONT' with option integer, SIZE, in pixels." (if (maybe-some? size) (set-frame-font (string-format "%s %s" font size) nil t) (set-frame-font font nil t))) -(defun fonts-whitelist-set (font) - "Focuses the FONT in the `fonts-whitelist' cycle. -The size of the font is determined by `fonts-size'." - (prelude-assert (cycle-contains? font fonts-whitelist)) - (cycle-focus (lambda (x) (equal x font)) fonts-whitelist) - (fonts-set (fonts-current) fonts-size)) - -(defun fonts-ivy-select () - "Select a font from an ivy prompt." - (interactive) - (fonts-whitelist-set - (ivy-read "Font: " (cycle-to-list fonts-whitelist)))) - -(defun fonts-print-current () - "Message the currently enabled font." - (interactive) - (message - (string-format "[fonts] Current font: \"%s\"" - (fonts-current)))) - (defun fonts-current () "Return the currently enabled font." - (cycle-current fonts-whitelist)) + (symbol-name (font-get (face-attribute 'default :font) :family))) (defun fonts-increase-size () "Increase font size." @@ -130,7 +62,7 @@ The size of the font is determined by `fonts-size'." (defun fonts-reset-size () "Restore font size to its default value." (interactive) - (fonts-whitelist-set (fonts-current))) + (fonts-set (fonts-current) fonts-size)) (defun fonts-enable-ligatures () "Call this function to enable ligatures." diff --git a/users/wpcarro/emacs/.emacs.d/wpc/fs.el b/users/wpcarro/emacs/.emacs.d/wpc/fs.el deleted file mode 100644 index c303b23539..0000000000 --- a/users/wpcarro/emacs/.emacs.d/wpc/fs.el +++ /dev/null @@ -1,69 +0,0 @@ -;;; fs.el --- Make working with the filesystem easier -*- lexical-binding: t -*- - -;; Author: William Carroll <wpcarro@gmail.com> -;; Version: 0.0.1 -;; Package-Requires: ((emacs "24.1")) - -;;; Commentary: -;; Ergonomic alternatives for working with the filesystem. - -;;; Code: - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Dependencies -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -(require 'dash) -(require 'f) -(require 's) - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Library -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -(defun fs-ensure-file (path) - "Ensure that a file and its directories in `PATH' exist. -Will error for inputs with a trailing slash." - (when (s-ends-with? "/" path) - (error (format "Input path has trailing slash: %s" path))) - (->> path - f-dirname - fs-ensure-dir) - (f-touch path)) - -(f-dirname "/tmp/a/b/file.txt") - -(defun fs-ensure-dir (path) - "Ensure that a directory and its ancestor directories in `PATH' exist." - (->> path - f-split - (apply #'f-mkdir))) - -(defun fs-ls (dir &optional full-path?) - "List the files in `DIR' one-level deep. -Should behave similarly in spirit to the Unix command, ls. -If `FULL-PATH?' is set, return the full-path of the files." - (-drop 2 (directory-files dir full-path?))) - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Tests -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -(ert-deftest fs-test-ensure-file () - (let ((file "/tmp/file/a/b/c/file.txt")) - ;; Ensure this file doesn't exist first to prevent false-positives. - (f-delete file t) - (fs-ensure-file file) - (should (and (f-exists? file) - (f-file? file))))) - -(ert-deftest fs-test-ensure-dir () - (let ((dir "/tmp/dir/a/b/c")) - ;; Ensure the directory doesn't exist. - (f-delete dir t) - (fs-ensure-dir dir) - (should (and (f-exists? dir) - (f-dir? dir))))) - -(provide 'fs) -;;; fs.el ends here diff --git a/users/wpcarro/emacs/.emacs.d/wpc/functions.el b/users/wpcarro/emacs/.emacs.d/wpc/functions.el deleted file mode 100644 index 936e25eb2d..0000000000 --- a/users/wpcarro/emacs/.emacs.d/wpc/functions.el +++ /dev/null @@ -1,46 +0,0 @@ -;;; functions.el --- Helper functions -*- lexical-binding: t -*- - -;; Author: William Carroll <wpcarro@gmail.com> -;; Version: 0.0.1 -;; Package-Requires: ((emacs "24")) - -;;; Commentary: -;; This file hopefully contains friendly APIs that making ELisp development more -;; enjoyable. - -;; TODO: Break these out into separate modules. - -;;; Code: -(defun functions-evil-window-vsplit-right () - "Split the window vertically and focus the right half." - (interactive) - (evil-window-vsplit) - (windmove-right)) - -(defun functions-evil-window-split-down () - "Split the window horizontal and focus the bottom half." - (interactive) - (evil-window-split) - (windmove-down)) - -(defun functions-create-snippet () - "Create a window split and then opens the Yasnippet editor." - (interactive) - (evil-window-vsplit) - (call-interactively #'yas-new-snippet)) - -(defun functions-evil-replace-under-point () - "Faster than typing %s//thing/g." - (interactive) - (let ((term (s-replace "/" "\\/" (symbol-to-string (symbol-at-point))))) - (save-excursion - (evil-ex (concat "%s/\\b" term "\\b/"))))) - -(defun functions-buffer-dirname () - "Return the directory name of the current buffer as a string." - (->> buffer-file-name - f-dirname - f-filename)) - -(provide 'functions) -;;; functions.el ends here diff --git a/users/wpcarro/emacs/.emacs.d/wpc/graph.el b/users/wpcarro/emacs/.emacs.d/wpc/graph.el deleted file mode 100644 index 1d2f67a4dd..0000000000 --- a/users/wpcarro/emacs/.emacs.d/wpc/graph.el +++ /dev/null @@ -1,94 +0,0 @@ -;;; graph.el --- Working with in-memory graphs -*- lexical-binding: t -*- - -;; Author: William Carroll <wpcarro@gmail.com> -;; Version: 0.0.1 -;; Package-Requires: ((emacs "24.3")) - -;;; Commentary: -;; -;; Remember that there are optimal three ways to model a graph: -;; 1. Edge List -;; 2. Vertex Table (a.k.a. Neighbors Table) -;; 3. Adjacency Matrix -;; -;; I may call these "Edges", "Neighbors", "Adjacencies" to avoid verbose naming. -;; For now, I'm avoiding dealing with Adjacency Matrices as I don't have an -;; immediate use-case for them. This is subject to change. -;; -;; There are also hybrid representations of graphs that combine the three -;; aforementioned models. I believe Erlang's digraph module models graphs in -;; Erlang Term Storage (i.e. ETS) this way. -;; TODO: Verify this claim. -;; -;; Graphs can be weighted or unweighted. They can also be directed or -;; undirected. -;; TODO: Create a table explaining all graph variants. -;; -;; TODO: Figure out the relationship of this module and tree.el, which should in -;; principle overlap. - -;;; Code: - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Dependencies -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -(require 'prelude) - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Library -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -;; For now, I'll support storing *either* neighbors or edges in the graph struct -;; as long as both aren't set, since that introduces consistency issues. I may -;; want to handle that use-case in the future, but not now. -(cl-defstruct graph neighbors edges) - -;; TODO: How do you find the starting point for a topo sort? -(defun graph-sort (xs) - "Return a topological sort of XS.") - -(defun graph-from-edges (xs) - "Create a graph struct from the Edge List, XS. -The user must pass in a valid Edge List since asserting on the shape of XS might - be expensive." - (make-graph :edges xs)) - -(defun graph-from-neighbors (xs) - "Create a graph struct from a Neighbors Table, XS. -The user must pass in a valid Neighbors Table since asserting on the shape of - XS might be expensive." - (make-graph :neighbors xs)) - -(defun graph-instance? (xs) - "Return t if XS is a graph struct." - (graph-p xs)) - -;; TODO: Model each of the mapping functions into an isomorphism. -(defun graph-edges->neighbors (xs) - "Map Edge List, XS, into a Neighbors Table." - (prelude-assert (graph-instance? xs))) - -(defun graph-neighbors->edges (xs) - "Map Neighbors Table, XS, into an Edge List." - (prelude-assert (graph-instance? xs))) - -;; Below are three different models of the same unweighted, directed graph. - -(defvar graph-edges - '((a . b) (a . c) (a . e) - (b . c) (b . d) - (c . e) - (d . f) - (e . d) (e . f))) - -(defvar graph-neighbors - ((a b c e) - (b c d) - (c e) - (d f) - (e d g) - (f))) - -(provide 'graph) -;;; graph.el ends here diff --git a/users/wpcarro/emacs/.emacs.d/wpc/irc.el b/users/wpcarro/emacs/.emacs.d/wpc/irc.el deleted file mode 100644 index 9103bd38fe..0000000000 --- a/users/wpcarro/emacs/.emacs.d/wpc/irc.el +++ /dev/null @@ -1,170 +0,0 @@ -;;; irc.el --- Configuration for IRC chat -*- lexical-binding: t -*- - -;; Author: William Carroll <wpcarro@gmail.com> -;; Version: 0.0.1 -;; Package-Requires: ((emacs "25.1")) - -;;; Commentary: -;; Need to decide which client I will use for IRC. - -;;; Code: - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Dependencies -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -(require 'erc) -(require 'cycle) -(require 'string) -(require 'prelude) -(require 'al) -(require 'set) -(require 'maybe) -(require 'macros) -(require '>) -(require 'password-store) -(require 'general) - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Configuration -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -(defcustom irc-install-kbds? t - "When t, install the keybindings defined herein.") - -(setq erc-rename-buffers t) - -;; Setting `erc-join-buffer' to 'bury prevents erc from stealing focus of the -;; current buffer when it connects to IRC servers. -(setq erc-join-buffer 'bury) - -;; TODO: Find a way to avoid putting "freenode" and "#freenode" as channels -;; here. I'm doing it because when erc first connects, it's `(buffer-name)' is -;; "freenode", so when `irc-next-channel' is called, it 404s on the -;; `cycle-contains?' call in `irc-channel->cycle" unless "freenode" is there. To -;; make matters even uglier, when `erc-join-channel' is called with "freenode" -;; as the value, it connects to the "#freenode" channel, so unless "#freenode" -;; exists in this cycle also, `irc-next-channel' breaks again. -(defconst irc-server->channels - `(("irc.freenode.net" . ,(cycle-new "freenode" "#freenode" "#nixos" "#emacs" "#pass")) - ("irc.corp.google.com" . ,(cycle-new "#drive-prod"))) - "Mapping of IRC servers to a cycle of my preferred channels.") - -;; TODO: Here is another horrible hack that should be revisted. -(setq erc-autojoin-channels-alist - (->> irc-server->channels - (al-map-values #'cycle-to-list) - (al-map-keys (>-> (s-chop-prefix "irc.") - (s-chop-suffix ".net"))))) - -;; TODO: Assert that no two servers have a channel with the same name. We need -;; this because that's the assumption that underpins the `irc-channel->server' -;; function. This will probably be an O(n^2) operation. -(prelude-assert - (set-distinct? (set-from-list - (cycle-to-list - (al-get "irc.freenode.net" - irc-server->channels))) - (set-from-list - (cycle-to-list - (al-get "irc.corp.google.com" - irc-server->channels))))) - -(defun irc-channel->server (server->channels channel) - "Using SERVER->CHANNELS, resolve an IRC server from a given CHANNEL." - (let ((result (al-find (lambda (k v) (cycle-contains? channel v)) - server->channels))) - (prelude-assert (maybe-some? result)) - result)) - -(defun irc-channel->cycle (server->channels channel) - "Using SERVER->CHANNELS, resolve an IRC's channels cycle from CHANNEL." - (al-get (irc-channel->server server->channels channel) - server->channels)) - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Library -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -(defun irc-message (x) - "Print message X in a structured way." - (message (string-format "[irc.el] %s" x))) - -;; TODO: Integrate Google setup with Freenode setup. - -;; TODO: Support function or KBD for switching to an ERC buffer. - -(defun irc-kill-all-erc-processes () - "Kill all ERC buffers and processes." - (interactive) - (->> (erc-buffer-list) - (-map #'kill-buffer))) - -(defun irc-switch-to-erc-buffer () - "Switch to an ERC buffer." - (interactive) - (let ((buffers (erc-buffer-list))) - (if (list-empty? buffers) - (error "[irc.el] No ERC buffers available") - (switch-to-buffer (list-head (erc-buffer-list)))))) - -(defun irc-connect-to-freenode () - "Connect to Freenode IRC." - (interactive) - (erc-ssl :server "irc.freenode.net" - :port 6697 - :nick "wpcarro" - :password (password-store-get "programming/irc/freenode") - :full-name "William Carroll")) - -;; TODO: Handle failed connections. -(defun irc-connect-to-google () - "Connect to Google's Corp IRC using ERC." - (interactive) - (erc-ssl :server "irc.corp.google.com" - :port 6697 - :nick "wpcarro" - :full-name "William Carroll")) - -;; TODO: Prefer defining these with a less homespun solution. There is a -;; function call `erc-buffer-filter' that would be more appropriate for the -;; implementation of `irc-next-channel' and `irc-prev-channel'. -(defun irc-next-channel () - "Join the next channel for the active server." - (interactive) - (with-current-buffer (current-buffer) - (let ((cycle (irc-channel->cycle irc-server->channels (buffer-name)))) - (erc-join-channel - (cycle-next cycle)) - (irc-message - (string-format "Current IRC channel: %s" (cycle-current cycle)))))) - -(defun irc-prev-channel () - "Join the previous channel for the active server." - (interactive) - (with-current-buffer (current-buffer) - (let ((cycle (irc-channel->cycle irc-server->channels (buffer-name)))) - (erc-join-channel - (cycle-prev cycle)) - (irc-message - (string-format "Current IRC channel: %s" (cycle-current cycle)))))) - -(add-hook 'erc-mode-hook (macros-disable auto-fill-mode)) -(add-hook 'erc-mode-hook (macros-disable company-mode)) - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Keybindings -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -(when irc-install-kbds? - (general-define-key - :keymaps 'erc-mode-map - "<C-tab>" #'irc-next-channel - "<C-S-iso-lefttab>" #'irc-prev-channel)) - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Tests -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -(provide 'irc) -;;; irc.el ends here diff --git a/users/wpcarro/emacs/.emacs.d/wpc/ivy-clipmenu.el b/users/wpcarro/emacs/.emacs.d/wpc/ivy-clipmenu.el deleted file mode 100644 index 70e68d257c..0000000000 --- a/users/wpcarro/emacs/.emacs.d/wpc/ivy-clipmenu.el +++ /dev/null @@ -1,137 +0,0 @@ -;;; ivy-clipmenu.el --- Emacs client for clipmenu -*- lexical-binding: t -*- - -;; Author: William Carroll <wpcarro@gmail.com> -;; Version: 0.0.1 -;; 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 diff --git a/users/wpcarro/emacs/.emacs.d/wpc/keybindings.el b/users/wpcarro/emacs/.emacs.d/wpc/keybindings.el index c6082ec704..a55bf27330 100644 --- a/users/wpcarro/emacs/.emacs.d/wpc/keybindings.el +++ b/users/wpcarro/emacs/.emacs.d/wpc/keybindings.el @@ -21,23 +21,20 @@ ;; Dependencies ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -(require 'functions) -(require 'clipboard) (require 'screen-brightness) (require 'pulse-audio) (require 'scrot) +(require 'ivy) (require 'ivy-clipmenu) (require 'ivy-helpers) (require 'general) (require 'exwm) (require 'vterm-mgt) (require 'buffer) -(require 'device) (require 'fonts) (require 'bookmark) (require 'tvl) (require 'window-manager) -(require 'wpc-misc) ;; Note: The following lines must be sorted this way. (setq evil-want-integration t) @@ -49,6 +46,43 @@ (require 'evil-surround) (require 'key-chord) (require 'edebug) +(require 'avy) +(require 'passage) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Helper Functions +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +(defun keybindings--window-vsplit-right () + "Split the window vertically and focus the right half." + (interactive) + (evil-window-vsplit) + (windmove-right)) + +(defun keybindings--window-split-down () + "Split the window horizontal and focus the bottom half." + (interactive) + (evil-window-split) + (windmove-down)) + +(defun keybindings--create-snippet () + "Create a window split and then opens the Yasnippet editor." + (interactive) + (evil-window-vsplit) + (call-interactively #'yas-new-snippet)) + +(defun keybindings--replace-under-point () + "Faster than typing %s//thing/g." + (interactive) + (let ((term (s-replace "/" "\\/" (symbol-to-string (symbol-at-point))))) + (save-excursion + (evil-ex (concat "%s/\\b" term "\\b/"))))) + +(defun keybindings--evil-ex-define-cmd-local (cmd f) + "Define CMD to F locally to a buffer." + (unless (local-variable-p 'evil-ex-commands) + (setq-local evil-ex-commands (copy-alist evil-ex-commands))) + (evil-ex-define-cmd cmd f)) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; General Keybindings @@ -77,10 +111,10 @@ "L" #'evil-end-of-line "_" #'ranger "-" #'dired-jump - "sl" #'functions-evil-window-vsplit-right + "sl" #'keybindings--window-vsplit-right "sh" #'evil-window-vsplit "sk" #'evil-window-split - "sj" #'functions-evil-window-split-down) + "sj" #'keybindings--window-split-down) (general-nmap :keymaps 'override @@ -121,6 +155,20 @@ (after advice-for-evil-search-previous activate) (evil-scroll-line-to-center (line-number-at-pos))))) +(general-define-key + :keymaps '(isearch-mode-map) + "C-p" #'isearch-ring-retreat + "C-n" #'isearch-ring-advance + "<up>" #'isearch-ring-retreat + "<down>" #'isearch-ring-advance) + +(general-define-key + :keymaps '(minibuffer-local-isearch-map) + "C-p" #'previous-line-or-history-element + "C-n" #'next-line-or-history-element + "<up>" #'previous-line-or-history-element + "<down>" #'next-line-or-history-element) + (key-chord-mode 1) (key-chord-define evil-insert-state-map "jk" 'evil-normal-state) @@ -174,8 +222,14 @@ (keybindings-exwm "<M-tab>" #'window-manager-next-workspace) (keybindings-exwm "<M-S-iso-lefttab>" #'window-manager-prev-workspace) (keybindings-exwm "C-S-f" #'window-manager-toggle-previous) -(keybindings-exwm "C-M-\\" #'ivy-pass) -(keybindings-exwm "s-e" #'wpc-misc-copy-emoji) +(keybindings-exwm "C-M-\\" #'passage-select) + +(defun keybindings-copy-emoji () + "Select an emoji from the completing-read menu." + (interactive) + (clipboard-copy (emojify-completing-read "Copy: "))) + +(keybindings-exwm "s-e" #'keybindings-copy-emoji) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Workspaces @@ -227,11 +281,11 @@ "gss" #'magit-status "gsd" #'tvl-depot-status "E" #'refine - "es" #'functions-create-snippet + "es" #'keybindings--create-snippet "l" #'linum-mode "B" #'magit-blame "w" #'save-buffer - "r" #'functions-evil-replace-under-point + "r" #'keybindings--replace-under-point "R" #'deadgrep) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; @@ -260,7 +314,9 @@ "<s-backspace>" #'vterm-mgt-rename-buffer ;; Without this, typing "+" is effectively no-op. Try for yourself: ;; (vterm-send-key "<kp-add>") - "<kp-add>" "+") + "<kp-add>" "+" + "M--" #'evil-window-split + "M-\\" #'evil-window-vsplit) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; notmuch @@ -277,19 +333,6 @@ "<C-tab>" #'notmuch-show-next-thread-show "e" #'notmuch-show-archive-message-then-next-or-next-thread) -;; TODO(wpcarro): Consider moving this to a separate module -(defun keybindings--evil-ex-define-cmd-local (cmd f) - "Define CMD to F locally to a buffer." - (unless (local-variable-p 'evil-ex-commands) - (setq-local evil-ex-commands (copy-alist evil-ex-commands))) - (evil-ex-define-cmd cmd f)) - -;; TODO(wpcarro): Support a macro that can easily define evil-ex commands for a -;; particular mode. -;; Consumption: -;; (evil-ex-for-mode 'notmuch-message-mode -;; "x" #'notmuch-mua-send-and-exit) - (add-hook 'notmuch-message-mode-hook (lambda () (keybindings--evil-ex-define-cmd-local "x" #'notmuch-mua-send-and-exit))) @@ -396,8 +439,57 @@ ;; bookmarks ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Install KBDs like <SPC>jb to search through my monorepo. -(bookmark-install-kbds) +(bookmark-install-kbd + (make-bookmark :label "wpcarro" + :path (f-join tvl-depot-path "users/wpcarro") + :kbd "w")) + +(bookmark-install-kbd + (make-bookmark :label "depot" + :path tvl-depot-path + :kbd "d")) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; refine +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +(general-define-key + :keymaps '(refine-mode-map) + :states '(normal) + "K" #'refine-delete + "q" #'kill-this-buffer) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; avy +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +(global-set-key (kbd "C-;") #'avy-goto-char) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ivy +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;; restore the ability to paste in ivy +(general-define-key + :keymaps '(ivy-minibuffer-map) + "C-k" #'kill-line + "C-u" (lambda () (interactive) (kill-line 0)) + "C-v" #'clipboard-yank + "C-S-v" #'clipboard-yank) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Rust +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +(general-define-key + :keymaps '(rust-mode-map) + :states '(normal) + "gd" #'lsp-find-definition + "gr" #'lsp-find-references) + +(general-define-key + :keymaps '(rust-mode-map) + "TAB" #'company-indent-or-complete-common) (provide 'keybindings) ;;; keybindings.el ends here diff --git a/users/wpcarro/emacs/.emacs.d/wpc/keyboard.el b/users/wpcarro/emacs/.emacs.d/wpc/keyboard.el index 03fb9e3f35..0ee00e1b84 100644 --- a/users/wpcarro/emacs/.emacs.d/wpc/keyboard.el +++ b/users/wpcarro/emacs/.emacs.d/wpc/keyboard.el @@ -15,9 +15,8 @@ ;; Dependencies ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -(require 'string) -(require 'number) (require 'cl-lib) +(require 'prelude) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Constants @@ -46,7 +45,7 @@ (defun keyboard-message (x) "Message X in a structured way." - (message (string-format "[keyboard.el] %s" x))) + (message (format "[keyboard.el] %s" x))) (cl-defun keyboard-set-key-repeat (&key (rate keyboard-repeat-rate) @@ -54,7 +53,7 @@ "Use xset to set the key-repeat RATE and DELAY." (prelude-start-process :name "keyboard-set-key-repeat" - :command (string-format "xset r rate %s %s" delay rate))) + :command (format "xset r rate %s %s" delay rate))) ;; NOTE: Settings like this are machine-dependent. For instance I only need to ;; do this on my laptop and other devices where I don't have access to my split @@ -76,42 +75,42 @@ (defun keyboard-inc-repeat-rate () "Increment `keyboard-repeat-rate'." (interactive) - (setq keyboard-repeat-rate (number-inc keyboard-repeat-rate)) + (setq keyboard-repeat-rate (1+ keyboard-repeat-rate)) (keyboard-set-key-repeat :rate keyboard-repeat-rate) (keyboard-message - (string-format "Rate: %s" keyboard-repeat-rate))) + (format "Rate: %s" keyboard-repeat-rate))) (defun keyboard-dec-repeat-rate () "Decrement `keyboard-repeat-rate'." (interactive) - (setq keyboard-repeat-rate (number-dec keyboard-repeat-rate)) + (setq keyboard-repeat-rate (1- keyboard-repeat-rate)) (keyboard-set-key-repeat :rate keyboard-repeat-rate) (keyboard-message - (string-format "Rate: %s" keyboard-repeat-rate))) + (format "Rate: %s" keyboard-repeat-rate))) (defun keyboard-inc-repeat-delay () "Increment `keyboard-repeat-delay'." (interactive) - (setq keyboard-repeat-delay (number-inc keyboard-repeat-delay)) + (setq keyboard-repeat-delay (1+ keyboard-repeat-delay)) (keyboard-set-key-repeat :delay keyboard-repeat-delay) (keyboard-message - (string-format "Delay: %s" keyboard-repeat-delay))) + (format "Delay: %s" keyboard-repeat-delay))) (defun keyboard-dec-repeat-delay () "Decrement `keyboard-repeat-delay'." (interactive) - (setq keyboard-repeat-delay (number-dec keyboard-repeat-delay)) + (setq keyboard-repeat-delay (1- keyboard-repeat-delay)) (keyboard-set-key-repeat :delay keyboard-repeat-delay) (keyboard-message - (string-format "Delay: %s" keyboard-repeat-delay))) + (format "Delay: %s" keyboard-repeat-delay))) (defun keyboard-print-key-repeat () "Print the currently set values for key repeat." (interactive) (keyboard-message - (string-format "Rate: %s. Delay: %s" - keyboard-repeat-rate - keyboard-repeat-delay))) + (format "Rate: %s. Delay: %s" + keyboard-repeat-rate + keyboard-repeat-delay))) (defun keyboard-set-preferences () "Reset the keyboard preferences to their default values. diff --git a/users/wpcarro/emacs/.emacs.d/wpc/laptop-battery.el b/users/wpcarro/emacs/.emacs.d/wpc/laptop-battery.el deleted file mode 100644 index 80dc96ebeb..0000000000 --- a/users/wpcarro/emacs/.emacs.d/wpc/laptop-battery.el +++ /dev/null @@ -1,63 +0,0 @@ -;;; laptop-battery.el --- Display laptop battery information -*- lexical-binding: t -*- - -;; Author: William Carroll <wpcarro@gmail.com> -;; Version: 0.0.1 -;; Package-Requires: ((emacs "25.1")) - -;;; Commentary: -;; Some wrappers to obtain battery information. -;; -;; To troubleshoot battery consumpton look into the CLI `powertop`. - -;;; Code: - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Roadmap -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -;; TODO: Support functions that work with reporting battery stats. -;; TODO: low-battery-reporting-threshold -;; TODO: charged-battery-reporting-threshold -;; TODO: Format modeline battery information. -;; TODO: Provide better time information in the modeline. - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Dependencies -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -(require 'battery) -(require 'al) -(require 'maybe) - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Library -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -(defun laptop-battery-available? () - "Return t if battery information is available." - (maybe-some? battery-status-function)) - -(defun laptop-battery-percentage () - "Return the current percentage of the battery." - (->> battery-status-function - funcall - (al-get 112))) - -(defun laptop-battery-print-percentage () - "Return the current percentage of the battery." - (interactive) - (->> (laptop-battery-percentage) - message)) - -(defun laptop-battery-display () - "Display laptop battery percentage in the modeline." - (interactive) - (display-battery-mode 1)) - -(defun laptop-battery-hide () - "Hide laptop battery percentage in the modeline." - (interactive) - (display-battery-mode -1)) - -(provide 'laptop-battery) -;;; laptop-battery.el ends here diff --git a/users/wpcarro/emacs/.emacs.d/wpc/list.el b/users/wpcarro/emacs/.emacs.d/wpc/list.el deleted file mode 100644 index 2f1509eeb4..0000000000 --- a/users/wpcarro/emacs/.emacs.d/wpc/list.el +++ /dev/null @@ -1,221 +0,0 @@ -;;; list.el --- Functions for working with lists -*- lexical-binding: t -*- - -;; Author: William Carroll <wpcarro@gmail.com> -;; Version: 0.0.1 -;; Package-Requires: ((emacs "24")) - -;;; Commentary: -;; Since I prefer having the `list-' namespace, I wrote this module to wrap many -;; of the functions that are defined in the the global namespace in ELisp. I -;; sometimes forget the names of these functions, so it's nice for them to be -;; organized like this. -;; -;; Motivation: -;; Here are some examples of function names that I cannot tolerate: -;; - `car': Return the first element (i.e. "head") of a linked list -;; - `cdr': Return the tail of a linked list - -;; As are most APIs for standard libraries that I write, this is heavily -;; influenced by Elixir's standard library. -;; -;; Elixir's List library: -;; - ++/2 -;; - --/2 -;; - hd/1 -;; - tl/1 -;; - in/2 -;; - length/1 -;; -;; Similar libraries: -;; - dash.el: Functional library that mimmicks Clojure. It is consumed herein. -;; - list-utils.el: Utility library that covers things that dash.el may not -;; cover. -;; stream.el: Elisp implementation of streams, "implemented as delayed -;; evaluation of cons cells." - -;; TODO: Consider naming this file linked-list.el. - -;; TODO: Support module-like macro that auto-namespaces functions. - -;; TODO: Consider wrapping most data structures like linked-lists, -;; associative-lists, etc in a `cl-defstruct', so that the dispatching by type -;; can be nominal instead of duck-typing. I'm not sure if this is a good idea -;; or not. If I do this, I should provide isomorphisms to map between idiomatic -;; ways of working with Elisp data structures and my wrapped variants. - -;; TODO: Are function aliases/synonyms even a good idea? Or do they just -;; bloat the API unnecessarily? - -;;; Code: - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Dependencies -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -;; TODO: Move `prelude-assert' elsewhere so that I can require it without -;; introducing the circular dependency of list.el -> prelude.el -> list.el. -;;(require 'prelude) -(require 'dash) - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Constants -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -(defconst list-tests? t - "When t, run the test suite.") - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Library -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -(defun list-new () - "Return a new, empty list." - '()) - -(defun list-concat (&rest lists) - "Joins `LISTS' into on list." - (apply #'-concat lists)) - -(defun list-join (joint xs) - "Join a list of strings, XS, with JOINT." - (if (list-empty? xs) - "" - (list-reduce (list-first xs) - (lambda (x acc) - (string-concat acc joint x)) - (list-tail xs)))) - -(defun list-length (xs) - "Return the number of elements in `XS'." - (length xs)) - -(defun list-get (i xs) - "Return the value in `XS' at `I', or nil." - (nth i xs)) - -(defun list-head (xs) - "Return the head of `XS'." - (car xs)) - -;; TODO: Learn how to write proper function aliases. -(defun list-first (xs) - "Alias for `list-head' for `XS'." - (list-head xs)) - -(defun list-tail (xs) - "Return the tail of `XS'." - (cdr xs)) - -(defun list-reverse (xs) - "Reverses `XS'." - (reverse xs)) - -(defun list-cons (x xs) - "Add `X' to the head of `XS'." - (cons x xs)) - -;; map, filter, reduce - -;; TODO: Create function adapters like swap. -;; (defun adapter/swap (f) -;; "Return a new function that wraps `F' and swaps the arguments." -;; (lambda (a b) -;; (funcall f b a))) - -;; TODO: Make this function work. -(defun list-reduce (acc f xs) - "Return over `XS' calling `F' on an element in `XS'and `ACC'." - (-reduce-from (lambda (acc x) (funcall f x acc)) acc xs)) - -(defun list-map (f xs) - "Call `F' on each element of `XS'." - (-map f xs)) - -(defun list-map-indexed (f xs) - "Call `F' on each element of `XS' along with its index." - (-map-indexed (lambda (i x) (funcall f x i)) xs)) - -(defun list-filter (p xs) - "Return a subset of XS where predicate P returned t." - (list-reverse - (list-reduce - '() - (lambda (x acc) - (if (funcall p x) - (list-cons x acc) - acc)) - xs))) - -(defun list-reject (p xs) - "Return a subset of XS where predicate of P return nil." - (list-filter (lambda (x) (not (funcall p x))) xs)) - -(defun list-find (p xs) - "Return the first x in XS that passes P or nil." - (-find p xs)) - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Predicates -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -(defun list-instance? (xs) - "Return t if `XS' is a list. -Be leery of using this with things like alists. Many data structures in Elisp - are implemented using linked lists." - (listp xs)) - -(defun list-empty? (xs) - "Return t if XS are empty." - (= 0 (list-length xs))) - -(defun list-all? (p xs) - "Return t if all `XS' pass the predicate, `P'." - (-all? p xs)) - -(defun list-any? (p xs) - "Return t if any `XS' pass the predicate, `P'." - (-any? p xs)) - -(defun list-contains? (x xs) - "Return t if X is in XS using `equal'." - (-contains? xs x)) - -(defun list-xs-distinct-by? (f xs) - "Return t if all elements in XS are distinct after applying F to each." - (= (length xs) - (->> xs (-map f) set-from-list set-count))) - -;; TODO: Support dedupe. -;; TODO: Should we call this unique? Or distinct? - -;; TODO: Add tests. -(defun list-dedupe-adjacent (xs) - "Return XS without adjacent duplicates." - (prelude-assert (not (list-empty? xs))) - (list-reduce (list (list-first xs)) - (lambda (x acc) - (if (equal x (list-first acc)) - acc - (list-cons x acc))) - xs)) - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Tests -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -;; (when list-tests? -;; (prelude-assert -;; (= 0 -;; (list-length '()))) -;; (prelude-assert -;; (= 5 -;; (list-length '(1 2 3 4 5)))) -;; (prelude-assert -;; (= 16 -;; (list-reduce 1 (lambda (x acc) (+ x acc)) '(1 2 3 4 5)))) -;; (prelude-assert -;; (equal '(2 4 6 8 10) -;; (list-map (lambda (x) (* x 2)) '(1 2 3 4 5))))) - -(provide 'list) -;;; list.el ends here diff --git a/users/wpcarro/emacs/.emacs.d/wpc/macros.el b/users/wpcarro/emacs/.emacs.d/wpc/macros.el deleted file mode 100644 index 32c9b59dcd..0000000000 --- a/users/wpcarro/emacs/.emacs.d/wpc/macros.el +++ /dev/null @@ -1,63 +0,0 @@ -;;; macros.el --- Helpful variables for making my ELisp life more enjoyable -*- lexical-binding: t -*- - -;; Author: William Carroll <wpcarro@gmail.com> -;; Version: 0.0.1 -;; Package-Requires: ((emacs "24")) - -;;; Commentary: -;; This file contains helpful variables that I use in my ELisp development. - -;; TODO: Consider a macro solution for mimmicking OCaml's auto resolution of -;; dependencies using `load-path' and friends. - -;;; Code: - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Dependencies -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -(require 'f) -(require 'string) -(require 'symbol) - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Library -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -(defmacro macros-enable (mode) - "Helper for enabling `MODE'. -Useful in `add-hook' calls. Some modes, like `linum-mode' need to be called as -`(linum-mode 1)', so `(add-hook mode #'linum-mode)' won't work." - `#'(lambda nil (,mode 1))) - -(defmacro macros-disable (mode) - "Helper for disabling `MODE'. -Useful in `add-hook' calls." - `#'(lambda nil (,mode -1))) - -(defmacro macros-add-hook-before-save (mode f) - "Register a hook, `F', for a mode, `MODE' more conveniently. -Usage: (macros-add-hook-before-save 'reason-mode-hook #'refmt-before-save)" - `(add-hook ,mode - (lambda () - (add-hook 'before-save-hook ,f)))) - -;; TODO: Privatize? -(defun macros--namespace () - "Return the namespace for a function based on the filename." - (->> (buffer-file-name) - f-filename - f-base)) - -(defmacro macros-comment (&rest _) - "Empty comment s-expresion where `BODY' is ignored." - `nil) - -(defmacro macros-support-file-extension (ext mode) - "Register MODE to automatically load with files ending with EXT extension. -Usage: (macros-support-file-extension \"pb\" protobuf-mode)" - (let ((extension (string-format "\\.%s\\'" ext))) - `(add-to-list 'auto-mode-alist '(,extension . ,mode)))) - -(provide 'macros) -;;; macros.el ends here diff --git a/users/wpcarro/emacs/.emacs.d/wpc/math.el b/users/wpcarro/emacs/.emacs.d/wpc/math.el deleted file mode 100644 index 4013ce3be2..0000000000 --- a/users/wpcarro/emacs/.emacs.d/wpc/math.el +++ /dev/null @@ -1,62 +0,0 @@ -;;; math.el --- Math stuffs -*- lexical-binding: t -*- - -;; Author: William Carroll <wpcarro@gmail.com> -;; Version: 0.0.1 -;; Package-Requires: ((emacs "24.3")) - -;;; Commentary: -;; Containing some useful mathematical functions. - -;;; Code: - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Dependencies -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -(require 'maybe) -(require 'cl-lib) - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Constants -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -(defconst math-pi pi - "The number pi.") - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Functions -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -;; TODO: Support all three arguments. -;; Int -> Int -> Int -> Boolean -(cl-defun math-triangle-of-power (&key base power result) - (cond - ((maybe-somes? base power result) - (error "All three arguments should not be set")) - ((maybe-somes? power result) - (message "power and result")) - ((maybe-somes? base result) - (log result base)) - ((maybe-somes? base power) - (expt base power)) - (t - (error "Two of the three arguments must be set")))) - -(defun math-mod (x y) - "Return X mod Y." - (mod x y)) - -(defun math-exp (x y) - "Return X raised to the Y." - (expt x y)) - -(defun math-round (x) - "Round X to nearest ones digit." - (round x)) - -(defun math-floor (x) - "Floor value X." - (floor x)) - -(provide 'math) -;;; math.el ends here diff --git a/users/wpcarro/emacs/.emacs.d/wpc/maybe.el b/users/wpcarro/emacs/.emacs.d/wpc/maybe.el deleted file mode 100644 index ef92e5a4c1..0000000000 --- a/users/wpcarro/emacs/.emacs.d/wpc/maybe.el +++ /dev/null @@ -1,78 +0,0 @@ -;;; maybe.el --- Library for dealing with nil values -*- lexical-binding: t -*- - -;; Author: William Carroll <wpcarro@gmail.com> -;; Version: 0.0.1 -;; Package-Requires: ((emacs "24")) - -;;; Commentary: -;; Inspired by Elm's Maybe library. -;; -;; For now, a Nothing value will be defined exclusively as a nil value. I'm -;; uninterested in supported falsiness in this module even at risk of going -;; against the LISP grain. -;; -;; I'm avoiding introducing a struct to handle the creation of Just and Nothing -;; variants of Maybe. Perhaps this is a mistake in which case this file would -;; be more aptly named nil.el. I may change that. Because of this limitation, -;; functions in Elm's Maybe library like andThen, which is the monadic bind for -;; the Maybe type, doesn't have a home here since we cannot compose multiple -;; Nothing or Just values without a struct or some other construct. -;; -;; Possible names for the variants of a Maybe. -;; None | Some -;; Nothing | Something -;; None | Just -;; Nil | Set -;; -;; NOTE: In Elisp, values like '() (i.e. the empty list) are aliases for nil. -;; What else in Elisp is an alias in this way? -;; Examples: -;; TODO: Provide examples of other nil types in Elisp. - -;;; Code: - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Dependencies -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -(require 'list) - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Constants -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -(defvar maybe--run-tests? t - "When t, run the test suite defined herein.") - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Library -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -(defun maybe-nil? (x) - "Return t if X is nil." - (eq nil x)) - -(defun maybe-some? (x) - "Return t when X is non-nil." - (not (maybe-nil? x))) - -(defun maybe-nils? (&rest xs) - "Return t if all XS are nil." - (list-all? #'maybe-nil? xs)) - -(defun maybe-somes? (&rest xs) - "Return t if all XS are non-nil." - (list-all? #'maybe-some? xs)) - -(defun maybe-default (default x) - "Return DEFAULT when X is nil." - (if (maybe-nil? x) default x)) - -(defun maybe-map (f x) - "Apply F to X if X is not nil." - (if (maybe-some? x) - (funcall f x) - x)) - -(provide 'maybe) -;;; maybe.el ends here diff --git a/users/wpcarro/emacs/.emacs.d/wpc/number.el b/users/wpcarro/emacs/.emacs.d/wpc/number.el deleted file mode 100644 index c8ed665b30..0000000000 --- a/users/wpcarro/emacs/.emacs.d/wpc/number.el +++ /dev/null @@ -1,142 +0,0 @@ -;;; number.el --- Functions for working with numbers -*- lexical-binding: t -*- - -;; Author: William Carroll <wpcarro@gmail.com> -;; Version: 0.0.1 -;; Package-Requires: ((emacs "24")) -;; Homepage: https://user.git.corp.google.com/wpcarro/briefcase - -;;; Commentary: -;; -;; Classifications of numbers: -;; - Natural: (a.k.a positive integers, counting numbers); {1, 2, 3, ... } -;; -;; - Whole: Natural Numbers, plus zero; {0, 1, 2, 3, ...} -;; -;; - Integers: Whole numbers plus all the negatives of the natural numbers; -;; {... , -2, -1, 0, 1, 2, ...} -;; -;; - Rational numbers: (a.k.a. fractions) where the top and bottom numbers are -;; integers; e.g., 1/2, 3/4, 7/2, ⁻4/3, 4/1. Note: The denominator cannot be -;; 0, but the numerator can be. -;; -;; - Real numbers: All numbers that can be written as a decimal. This includes -;; fractions written in decimal form e.g., 0.5, 0.75 2.35, ⁻0.073, 0.3333, or -;; 2.142857. It also includes all the irrational numbers such as π, √2 etc. -;; Every real number corresponds to a point on the number line. -;; -;; The functions defined herein attempt to capture the mathematical definitions -;; of numbers and their classifications as defined above. - -;;; Code: - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Dependencies -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -(require 'prelude) -(require 'dash) - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Library -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -(defconst number-test? t - "When t, run the test suite defined herein.") - -;; TODO: What about int.el? - -;; TODO: How do we handle a number typeclass? - -(defun number-positive? (x) - "Return t if `X' is a positive number." - (> x 0)) - -(defun number-negative? (x) - "Return t if `X' is a positive number." - (< x 0)) - -;; TODO: Don't rely on this. Need to have 10.0 and 10 behave similarly. -(defun number-float? (x) - "Return t if `X' is a floating point number." - (floatp x)) - -(defun number-natural? (x) - "Return t if `X' is a natural number." - (and (number-positive? x) - (not (number-float? x)))) - -(defun number-whole? (x) - "Return t if `X' is a whole number." - (or (= 0 x) - (number-natural? x))) - -(defun number-integer? (x) - "Return t if `X' is an integer." - (or (number-whole? x) - (number-natural? (- x)))) - -;; TODO: How defensive should these guards be? Should we assert that the inputs -;; are integers before checking evenness or oddness? - -;; TODO: Look up Runar (from Unison) definition of handling zero as even or odd. - -;; TODO: How should rational numbers be handled? Lisp is supposedly famous for -;; its handling of rational numbers. -;; TODO: `calc-mode' supports rational numbers as "1:2" meaning "1/2" -;; (defun number-rational? (x)) - -;; TODO: Can or should I support real numbers? -;; (defun number-real? (x)) - -(defun number-even? (x) - "Return t if `X' is an even number." - (or (= 0 x) - (= 0 (mod x 2)))) - -(defun number-odd? (x) - "Return t if `X' is an odd number." - (not (number-even? x))) - -(defun number-dec (x) - "Subtract one from `X'. -While this function is undeniably trivial, I have unintentionally done (- 1 x) - when in fact I meant to do (- x 1) that I figure it's better for this function - to exist, and for me to train myself to reach for it and its inc counterpart." - (- x 1)) - -(defun number-inc (x) - "Add one to `X'." - (+ x 1)) - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Tests -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -(when number-test? - (prelude-assert - (number-positive? 10)) - (prelude-assert - (number-natural? 10)) - (prelude-assert - (number-whole? 10)) - (prelude-assert - (number-whole? 0)) - (prelude-assert - (number-integer? 10)) - ;; (prelude-assert - ;; (= 120 (number-factorial 5))) - (prelude-assert - (number-even? 6)) - (prelude-refute - (number-odd? 6)) - (prelude-refute - (number-positive? -10)) - (prelude-refute - (number-natural? 10.0)) - (prelude-refute - (number-natural? -10)) - (prelude-refute - (number-natural? -10.0))) - -(provide 'number) -;;; number.el ends here diff --git a/users/wpcarro/emacs/.emacs.d/wpc/random.el b/users/wpcarro/emacs/.emacs.d/wpc/random.el deleted file mode 100644 index dfe10b6d47..0000000000 --- a/users/wpcarro/emacs/.emacs.d/wpc/random.el +++ /dev/null @@ -1,80 +0,0 @@ -;;; random.el --- Functions for working with randomness -*- lexical-binding: t -*- - -;; Author: William Carroll <wpcarro@gmail.com> -;; Version: 0.0.1 -;; Package-Requires: ((emacs "24")) - -;;; Commentary: -;; Functions for working with randomness. Some of this code is not as -;; functional as I'd like from. - -;;; Code: - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Dependencies -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -(require 'prelude) -(require 'number) -(require 'math) -(require 'series) -(require 'list) -(require 'set) - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Library -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -(defun random-int (x) - "Return a random integer from 0 to `X'." - (random x)) - -;; TODO: Make this work with sequences instead of lists. -(defun random-choice (xs) - "Return a random element of `XS'." - (let ((ct (list-length xs))) - (list-get - (random-int ct) - xs))) - -(defun random-boolean? () - "Randonly return t or nil." - (random-choice (list t nil))) - -;; TODO: This may not work if any of these generate numbers like 0, 1, etc. -(defun random-uuid () - "Return a generated UUID string." - (let ((eight (number-dec (math-triangle-of-power :base 16 :power 8))) - (four (number-dec (math-triangle-of-power :base 16 :power 4))) - (twelve (number-dec (math-triangle-of-power :base 16 :power 12)))) - (format "%x-%x-%x-%x-%x" - (random-int eight) - (random-int four) - (random-int four) - (random-int four) - (random-int twelve)))) - -(defun random-token (length) - "Return a randomly generated hexadecimal string of LENGTH." - (->> (series/range 0 (number-dec length)) - (list-map (lambda (_) (format "%x" (random-int 15)))) - (list-join ""))) - -;; TODO: Support random-sample -;; (defun random-sample (n xs) -;; "Return a randomly sample of list XS of size N." -;; (prelude-assert (and (>= n 0) (< n (list-length xs)))) -;; (cl-labels ((do-sample -;; (n xs y ys) -;; (if (= n (set-count ys)) -;; (->> ys -;; set-to-list -;; (list-map (lambda (i) -;; (list-get i xs)))) -;; (if (set-contains? y ys) -;; (do-sample n xs (random-int (list-length xs)) ys) -;; (do-sample n xs y (set-add y ys)))))) -;; (do-sample n xs (random-int (list-length xs)) (set-new)))) - -(provide 'random) -;;; random.el ends here diff --git a/users/wpcarro/emacs/.emacs.d/wpc/scope.el b/users/wpcarro/emacs/.emacs.d/wpc/scope.el deleted file mode 100644 index 99cdbd2b5e..0000000000 --- a/users/wpcarro/emacs/.emacs.d/wpc/scope.el +++ /dev/null @@ -1,106 +0,0 @@ -;;; scope.el --- Work with a scope data structure -*- lexical-binding: t -*- - -;; Author: William Carroll <wpcarro@gmail.com> -;; Version: 0.0.1 -;; Package-Requires: ((emacs "25.1")) - -;;; Commentary: -;; Exposing an API for working with a scope data structure in a non-mutative -;; way. -;; -;; What's a scope? Think of a scope as a stack of key-value bindings. - -;;; Code: - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Dependencies -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -(require 'al) -(require 'stack) -(require 'struct) -(require '>) - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Create -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -(cl-defstruct scope scopes) - -(defun scope-new () - "Return an empty scope." - (make-scope :scopes (->> (stack-new) - (stack-push (al-new))))) - -(defun scope-flatten (xs) - "Return a flattened representation of the scope, XS. -The newest bindings eclipse the oldest." - (->> xs - scope-scopes - stack-to-list - (list-reduce (al-new) - (lambda (scope acc) - (al-merge acc scope))))) - -(defun scope-push-new (xs) - "Push a new, empty scope onto XS." - (struct-update scope - scopes - (>-> (stack-push (al-new))) - xs)) - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Read -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -(defun scope-get (k xs) - "Return K from XS if it's in scope." - (->> xs - scope-flatten - (al-get k))) - -(defun scope-current (xs) - "Return the newest scope from XS." - (let ((xs-copy (copy-scope xs))) - (->> xs-copy - scope-scopes - stack-peek))) - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Update -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -(defun scope-set (k v xs) - "Set value, V, at key, K, in XS for the current scope." - (struct-update scope - scopes - (>-> (stack-map-top (>-> (al-set k v)))) - xs)) - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Delete -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -(defun scope-pop (xs) - "Return a new scope without the top element from XS." - (->> xs - scope-scopes - stack-pop)) - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Predicates -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -(defun scope-defined? (k xs) - "Return t if K is in scope of XS." - (->> xs - scope-flatten - (al-has-key? k))) - -;; TODO: Find a faster way to write aliases like this. -(defun scope-instance? (xs) - "Return t if XS is a scope struct." - (scope-p xs)) - -(provide 'scope) -;;; scope.el ends here diff --git a/users/wpcarro/emacs/.emacs.d/wpc/sequence.el b/users/wpcarro/emacs/.emacs.d/wpc/sequence.el deleted file mode 100644 index 204a72c5b0..0000000000 --- a/users/wpcarro/emacs/.emacs.d/wpc/sequence.el +++ /dev/null @@ -1,108 +0,0 @@ -;;; sequence.el --- Working with the "sequence" types -*- lexical-binding: t -*- - -;; Author: William Carroll <wpcarro@gmail.com> -;; Version: 0.0.1 -;; Package-Requires: ((emacs "25.1")) - -;;; Commentary: -;; Elisp supports a typeclass none as "sequence" which covers the following -;; types: -;; - list: '(1 2 3 4 5) -;; - vector: ["John" 27 :blue] -;; - string: "To be or not to be..." - -;; TODO: Document the difference between a "reduce" and a "fold". I.e. - reduce -;; has an initial value whereas fold uses the first element in the sequence as -;; the initial value. -;; -;; Note: This should be an approximation of Elixir's Enum protocol albeit -;; without streams. -;; -;; Elisp has done a lot of this work already and these are mostly wrapper -;; functions. -;; See the following list for reference: -;; - sequencep -;; - elt -;; - copy-sequence -;; - reverse -;; - nreverse -;; - sort -;; - seq-elt -;; - seq-length -;; - seqp -;; - seq-drop -;; - seq-take -;; - seq-take-while -;; - seq-drop-while -;; - seq-do -;; - seq-map -;; - seq-mapn -;; - seq-filter -;; - seq-remove -;; - seq-reduce -;; - seq-some -;; - seq-find -;; - seq-every-p -;; - seq-empty-p -;; - seq-count -;; - seq-sort -;; - seq-contains -;; - seq-position -;; - seq-uniq -;; - seq-subseq -;; - seq-concatenate -;; - seq-mapcat -;; - seq-partition -;; - seq-intersection -;; - seq-difference -;; - seq-group-by -;; - seq-into -;; - seq-min -;; - seq-max -;; - seq-doseq -;; - seq-let - -;;; Code: - -;; Perhaps we can provide default implementations for `filter' and `map' derived -;; from the `reduce' implementation. -;; (defprotocol sequence -;; :functions (reduce)) -;; (definstance sequence list -;; :reduce #'list-reduce -;; :filter #'list-filter -;; :map #'list-map) -;; (definstance sequence vector -;; :reduce #'vector/reduce) -;; (definstance sequence string -;; :reduce #'string) - -(defun sequence-classify (xs) - "Return the type of `XS'." - (cond - ((listp xs) 'list) - ((vectorp xs) 'vector) - ((stringp xs) 'string))) - -(defun sequence-reduce (acc f xs) - "Reduce of `XS' calling `F' on x and `ACC'." - (seq-reduce - (lambda (acc x) - (funcall f x acc)) - xs - acc)) - -;; Elixir also turned everything into a list for efficiecy reasons. - -(defun sequence-filter (p xs) - "Filter `XS' with predicate, `P'. -Returns a list regardless of the type of `XS'." - (seq-filter p xs)) - -(defun sequence-map (f xs) - "Maps `XS' calling `F' on each element. -Returns a list regardless of the type of `XS'." - (seq-map f xs)) - -(provide 'sequence) -;;; sequence.el ends here diff --git a/users/wpcarro/emacs/.emacs.d/wpc/series.el b/users/wpcarro/emacs/.emacs.d/wpc/series.el deleted file mode 100644 index d890038839..0000000000 --- a/users/wpcarro/emacs/.emacs.d/wpc/series.el +++ /dev/null @@ -1,92 +0,0 @@ -;;; series.el --- Hosting common series of numbers -*- lexical-binding: t -*- - -;; Author: William Carroll <wpcarro@gmail.com> -;; Version: 0.0.1 -;; Package-Requires: ((emacs "24")) - -;;; Commentary: -;; Encoding number series as I learn about them. -;; -;; These are the following series I'm interested in supporting: -;; - Fibonacci -;; - Catalan numbers -;; - Figurate number series -;; - Triangular -;; - Square -;; - Pentagonal -;; - Hexagonal -;; - Lazy-caterer -;; - Magic square -;; - Look-and-say - -;;; Code: - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Dependencies -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -(require 'number) - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Library -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -(defun series-range (beg end) - "Create a list of numbers from `BEG' to `END'. -This is an inclusive number range." - (if (< end beg) - (list-reverse - (number-sequence end beg)) - (number-sequence beg end))) - -(defun series-fibonacci-number (i) - "Return the number in the fibonacci series at `I'." - (cond - ((= 0 i) 0) - ((= 1 i) 1) - (t (+ (series-fibonacci-number (- i 1)) - (series-fibonacci-number (- i 2)))))) - -(defun series-fibonacci (n) - "Return the first `N' numbers of the fibonaccci series starting at zero." - (if (= 0 n) - '() - (list-reverse - (list-cons (series-fibonacci-number (number-dec n)) - (list-reverse - (series-fibonacci (number-dec n))))))) - -;; TODO: Consider memoization. -(defun series-triangular-number (i) - "Return the number in the triangular series at `I'." - (if (= 0 i) - 0 - (+ i (series-triangular-number (number-dec i))))) - -;; TODO: Improve performance. -;; TODO: Consider creating a stream protocol with `stream/next' and implement -;; this using that. -(defun series-triangular (n) - "Return the first `N' numbers of a triangular series starting at 0." - (if (= 0 n) - '() - (list-reverse - (list-cons (series-triangular-number (number-dec n)) - (list-reverse - (series-triangular (number-dec n))))))) - -(defun series-catalan-number (i) - "Return the catalan number in the series at `I'." - (if (= 0 i) - 1 - (/ (number-factorial (* 2 i)) - (* (number-factorial (number-inc i)) - (number-factorial i))))) - -(defun series-catalan (n) - "Return the first `N' numbers in a catalan series." - (->> (series-range 0 (number-dec n)) - (list-map #'series-catalan-number))) - -(provide 'series) -;;; series.el ends here diff --git a/users/wpcarro/emacs/.emacs.d/wpc/set.el b/users/wpcarro/emacs/.emacs.d/wpc/set.el deleted file mode 100644 index 778b089e15..0000000000 --- a/users/wpcarro/emacs/.emacs.d/wpc/set.el +++ /dev/null @@ -1,174 +0,0 @@ -;;; set.el --- Working with mathematical sets -*- lexical-binding: t -*- - -;; Author: William Carroll <wpcarro@gmail.com> -;; Version: 0.0.1 -;; Package-Requires: ((emacs "24.3")) - -;;; Commentary: -;; The set data structure is a collection that deduplicates its elements. - -;;; Code: - -(require 'ht) ;; friendlier API for hash-tables -(require 'dotted) -(require 'struct) - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Wish List -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -;; - TODO: Support enum protocol for set. -;; - TODO: Prefer a different hash-table library that doesn't rely on mutative -;; code. - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Library -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -(cl-defstruct set xs) - -(defconst set-enable-testing? t - "Run tests when t.") - -(defun set-from-list (xs) - "Create a new set from the list XS." - (make-set :xs (->> xs - (list-map #'dotted-new) - ht-from-alist))) - -(defun set-new (&rest args) - "Create a new set from ARGS." - (set-from-list args)) - -(defun set-to-list (xs) - "Map set XS into a list." - (->> xs - set-xs - ht-keys)) - -(defun set-add (x xs) - "Add X to set XS." - (struct-update set - xs - (lambda (table) - (let ((table-copy (ht-copy table))) - (ht-set table-copy x nil) - table-copy)) - xs)) - -;; TODO: Ensure all `*/reduce' functions share the same API. -(defun set-reduce (acc f xs) - "Return a new set by calling F on each element of XS and ACC." - (->> xs - set-to-list - (list-reduce acc f))) - -(defun set-intersection (a b) - "Return the set intersection between A and B." - (set-reduce (set-new) - (lambda (x acc) - (if (set-contains? x b) - (set-add x acc) - acc)) - a)) - -(defun set-count (xs) - "Return the number of elements in XS." - (->> xs - set-xs - ht-size)) - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Predicates -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -(defun set-empty? (xs) - "Return t if XS has no elements in it." - (= 0 (set-count xs))) - -(defun set-contains? (x xs) - "Return t if set XS has X." - (ht-contains? (set-xs xs) x)) - -;; TODO: Prefer using `ht.el' functions for this. -(defun set-equal? (a b) - "Return t if A and B share the name members." - (ht-equal? (set-xs a) - (set-xs b))) - -(defun set-distinct? (a b) - "Return t if A and B have no shared members." - (set-empty? (set-intersection a b))) - -(defun set-superset? (a b) - "Return t if A has all of the members of B." - (->> b - set-to-list - (list-all? (lambda (x) (set-contains? x a))))) - -(defun set-subset? (a b) - "Return t if each member of set A is present in set B." - (set-superset? b a)) - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Tests -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -(when set-enable-testing? - ;; set-distinct? - (prelude-assert - (set-distinct? (set-new 'one 'two 'three) - (set-new 'a 'b 'c))) - (prelude-refute - (set-distinct? (set-new 1 2 3) - (set-new 3 4 5))) - (prelude-refute - (set-distinct? (set-new 1 2 3) - (set-new 1 2 3))) - ;; set-equal? - (prelude-refute - (set-equal? (set-new 'a 'b 'c) - (set-new 'x 'y 'z))) - (prelude-refute - (set-equal? (set-new 'a 'b 'c) - (set-new 'a 'b))) - (prelude-assert - (set-equal? (set-new 'a 'b 'c) - (set-new 'a 'b 'c))) - ;; set-intersection - (prelude-assert - (set-equal? (set-new 2 3) - (set-intersection (set-new 1 2 3) - (set-new 2 3 4)))) - ;; set-{from,to}-list - (prelude-assert (equal '(1 2 3) - (->> '(1 1 2 2 3 3) - set-from-list - set-to-list))) - (let ((primary-colors (set-new "red" "green" "blue"))) - ;; set-subset? - (prelude-refute - (set-subset? (set-new "black" "grey") - primary-colors)) - (prelude-assert - (set-subset? (set-new "red") - primary-colors)) - ;; set-superset? - (prelude-refute - (set-superset? primary-colors - (set-new "black" "grey"))) - (prelude-assert - (set-superset? primary-colors - (set-new "red" "green" "blue"))) - (prelude-assert - (set-superset? primary-colors - (set-new "red" "blue")))) - ;; set-empty? - (prelude-assert (set-empty? (set-new))) - (prelude-refute (set-empty? (set-new 1 2 3))) - ;; set-count - (prelude-assert (= 0 (set-count (set-new)))) - (prelude-assert (= 2 (set-count (set-new 1 1 2 2))))) - -(provide 'set) -;;; set.el ends here diff --git a/users/wpcarro/emacs/.emacs.d/wpc/ssh.el b/users/wpcarro/emacs/.emacs.d/wpc/ssh.el index eb7debc492..1179e90363 100644 --- a/users/wpcarro/emacs/.emacs.d/wpc/ssh.el +++ b/users/wpcarro/emacs/.emacs.d/wpc/ssh.el @@ -41,7 +41,9 @@ ;; enables ControlMaster. (setq tramp-use-ssh-controlmaster-options nil) -(defcustom ssh-hosts '("wpcarro@wpcarro.dev") +(defcustom ssh-hosts '("wpcarro@wpcarro.dev" + "foundation" + "edge") "List of hosts to which I commonly connect.") (defun ssh-sudo-buffer () @@ -49,7 +51,10 @@ (interactive) (with-current-buffer (current-buffer) (if (s-starts-with? "/ssh:" buffer-file-name) - (message "[ssh.el] calling ssh-sudo-buffer for remote files isn't currently supported") + (pcase (s-split ":" buffer-file-name) + (`(,one ,two ,three) (find-file (format "/ssh:%s|sudo:%s:%s" two two three)))) + (find-file + (s-join ":" (-insert-at 2 "|sudo" (s-split ":" buffer-file-name)))) (find-file (format "/sudo::%s" buffer-file-name))))) (defun ssh-cd-home () diff --git a/users/wpcarro/emacs/.emacs.d/wpc/stack.el b/users/wpcarro/emacs/.emacs.d/wpc/stack.el deleted file mode 100644 index 3d1e3e4a16..0000000000 --- a/users/wpcarro/emacs/.emacs.d/wpc/stack.el +++ /dev/null @@ -1,101 +0,0 @@ -;;; stack.el --- Working with stacks in Elisp -*- lexical-binding: t -*- - -;; Author: William Carroll <wpcarro@gmail.com> -;; Version: 0.0.1 -;; Package-Requires: ((emacs "25.1")) - -;;; Commentary: -;; A stack is a LIFO queue. -;; The design goal here is to expose an intuitive API for working with stacks in -;; non-mutative way. -;; -;; TODO: Consider naming a Functor instance "Mappable." -;; TODO: Consider naming a Foldable instance "Reduceable." -;; -;; TODO: Consider implementing an instance for Mappable. -;; TODO: Consider implementing an instance for Reduceable. - -;;; Code: - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Dependencies -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -(require 'list) -(require '>) - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Create -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -(cl-defstruct stack xs) - -(defun stack-new () - "Create an empty stack." - (make-stack :xs '())) - -(defun stack-from-list (xs) - "Create a new stack from the list, `XS'." - (list-reduce (stack-new) #'stack-push xs)) - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Read -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -(defun stack-peek (xs) - "Look at the top element of `XS' without popping it off." - (->> xs - stack-xs - list-head)) - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Update -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -(defun stack-push (x xs) - "Push `X' on `XS'." - (struct-update stack - xs - (>-> (list-cons x)) - xs)) - -;; TODO: How to return something like {(list-head xs), (list-tail xs)} in Elixir -;; TODO: How to handle popping from empty stacks? -(defun stack-pop (xs) - "Return the stack, `XS', without the top element. -Since I cannot figure out a nice way of return tuples in Elisp, if you want to -look at the first element, use `stack-peek' before running `stack-pop'." - (struct-update stack - xs - (>-> list-tail) - xs)) - -(defun stack-map-top (f xs) - "Apply F to the top element of XS." - (->> xs - stack-pop - (stack-push (funcall f (stack-peek xs))))) - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Miscellaneous -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -(defun stack-to-list (xs) - "Return XS as a list. -The round-trip property of `stack-from-list' and `stack-to-list' should hold." - (->> xs - stack-xs - list-reverse)) - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Predicates -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -;; TODO: Create a macro that wraps `cl-defstruct' that automatically creates -;; things like `new', `instance?'. -(defun stack-instance? (xs) - "Return t if XS is a stack." - (stack-p xs)) - -(provide 'stack) -;;; stack.el ends here diff --git a/users/wpcarro/emacs/.emacs.d/wpc/string.el b/users/wpcarro/emacs/.emacs.d/wpc/string.el deleted file mode 100644 index 7e3f10c75a..0000000000 --- a/users/wpcarro/emacs/.emacs.d/wpc/string.el +++ /dev/null @@ -1,110 +0,0 @@ -;;; string.el --- Library for working with strings -*- lexical-binding: t -*- - -;; Author: William Carroll <wpcarro@gmail.com> -;; Version: 0.0.1 -;; Package-Requires: ((emacs "24")) - -;;; Commentary: -;; Library for working with string. - -;;; Code: - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Dependencies -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -(require 's) -(require 'dash) -;; TODO: Resolve the circular dependency that this introduces. -;; (require 'prelude) - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Library -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -(defun string-contains? (c x) - "Return t if X is in C." - (s-contains? c x)) - -(defun string-hookify (x) - "Append \"-hook\" to X." - (s-append "-hook" x)) - -(defun string-split (y x) - "Map string X into a list of strings that were separated by Y." - (s-split y x)) - -(defun string-ensure-hookified (x) - "Ensure that X has \"-hook\" appended to it." - (if (s-ends-with? "-hook" x) - x - (string-hookify x))) - -(defun string-format (x &rest args) - "Format template string X with ARGS." - (apply #'format (cons x args))) - -(defun string-concat (&rest strings) - "Joins `STRINGS' into onto string." - (apply #'s-concat strings)) - -(defun string-->symbol (string) - "Maps `STRING' to a symbol." - (intern string)) - -(defun string-<-symbol (symbol) - "Maps `SYMBOL' into a string." - (symbol-name symbol)) - -(defun string-prepend (prefix x) - "Prepend `PREFIX' onto `X'." - (s-concat prefix x)) - -(defun string-append (postfix x) - "Appen `POSTFIX' onto `X'." - (s-concat x postfix)) - -(defun string-surround (s x) - "Surrounds `X' one each side with `S'." - (->> x - (string-prepend s) - (string-append s))) - -;; TODO: Define a macro for defining a function and a test. - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Casing -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -(defun string-caps->kebab (x) - "Change the casing of `X' from CAP_CASE to kebab-case." - (->> x - s-downcase - (s-replace "_" "-"))) - -(defun string-kebab->caps (x) - "Change the casing of X from CAP_CASE to kebab-case." - (->> x - s-upcase - (s-replace "-" "_"))) - -(defun string-lower->caps (x) - "Change the casing of X from lowercase to CAPS_CASE." - (->> x - s-upcase - (s-replace " " "_"))) - -(defun string-lower->kebab (x) - "Change the casing of `X' from lowercase to kebab-case." - (s-replace " " "-" x)) - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Predicates -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -(defun string-instance? (x) - "Return t if X is a string." - (stringp x)) - -(provide 'string) -;;; string.el ends here diff --git a/users/wpcarro/emacs/.emacs.d/wpc/struct.el b/users/wpcarro/emacs/.emacs.d/wpc/struct.el deleted file mode 100644 index eeea04bf26..0000000000 --- a/users/wpcarro/emacs/.emacs.d/wpc/struct.el +++ /dev/null @@ -1,85 +0,0 @@ -;;; struct.el --- Helpers for working with structs -*- lexical-binding: t -*- - -;; Author: William Carroll <wpcarro@gmail.com> -;; Version: 0.0.1 -;; Package-Requires: ((emacs "24.3")) - -;;; Commentary: -;; Provides new macros for working with structs. Also provides adapter -;; interfaces to existing struct macros, that should have more intuitive -;; interfaces. -;; -;; Sometimes `setf' just isn't enough. - -;;; Code: - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Dependencies -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -(require 'string) -(require 'dash) - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Library -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -(defvar struct--enable-tests? t - "When t, run the test suite defined herein.") - -(defmacro struct-update (type field f xs) - "Apply F to FIELD in XS, which is a struct of TYPE. -This is immutable." - (let ((copier (->> type - symbol-name - (string-prepend "copy-") - intern)) - (accessor (->> field - symbol-name - (string-prepend (string-concat (symbol-name type) "-")) - intern))) - `(let ((copy (,copier ,xs))) - (setf (,accessor copy) (funcall ,f (,accessor copy))) - copy))) - -(defmacro struct-set (type field x xs) - "Immutably set FIELD in XS (struct TYPE) to X." - (let ((copier (->> type - symbol-name - (string-prepend "copy-") - intern)) - (accessor (->> field - symbol-name - (string-prepend (string-concat (symbol-name type) "-")) - intern))) - `(let ((copy (,copier ,xs))) - (setf (,accessor copy) ,x) - copy))) - -(defmacro struct-set! (type field x xs) - "Set FIELD in XS (struct TYPE) to X mutably. -This is an adapter interface to `setf'." - (let ((accessor (->> field - symbol-name - (string-prepend (string-concat (symbol-name type) "-")) - intern))) - `(progn - (setf (,accessor ,xs) ,x) - ,xs))) - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Tests -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -(when struct--enable-tests? - (cl-defstruct dummy name age) - (defvar struct--test-dummy (make-dummy :name "Roofus" :age 19)) - (struct-set! dummy name "Doofus" struct--test-dummy) - (prelude-assert (string= "Doofus" (dummy-name struct--test-dummy))) - (let ((result (struct-set dummy name "Shoofus" struct--test-dummy))) - ;; Test the immutability of `struct-set' - (prelude-assert (string= "Doofus" (dummy-name struct--test-dummy))) - (prelude-assert (string= "Shoofus" (dummy-name result))))) - -(provide 'struct) -;;; struct.el ends here diff --git a/users/wpcarro/emacs/.emacs.d/wpc/symbol.el b/users/wpcarro/emacs/.emacs.d/wpc/symbol.el deleted file mode 100644 index 79d665fa20..0000000000 --- a/users/wpcarro/emacs/.emacs.d/wpc/symbol.el +++ /dev/null @@ -1,48 +0,0 @@ -;;; symbol.el --- Library for working with symbols -*- lexical-binding: t -*- - -;; Author: William Carroll <wpcarro@gmail.com> -;; Version: 0.0.1 -;; Package-Requires: ((emacs "24")) - -;;; Commentary: -;; Library for working with symbols. - -;;; Code: - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Dependencies -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -(require 'string) - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Library -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -;; Symbols -(defun symbol-as-string (callback x) - "Treat the symbol, X, as a string while applying CALLBACK to it. -Coerce back to a symbol on the way out." - (->> x - #'symbol-name - callback - #'intern)) - -(defun symbol-to-string (x) - "Map `X' into a string." - (string-<-symbol x)) - -(defun symbol-hookify (x) - "Append \"-hook\" to X when X is a symbol." - (symbol-as-string #'string-hookify x)) - -(defun symbol-ensure-hookified (x) - "Ensure that X has \"-hook\" appended to it when X is a symbol." - (symbol-as-string #'string-ensure-hookified x)) - -(defun symbol-instance? (x) - "Return t if X is a symbol." - (symbolp x)) - -(provide 'symbol) -;;; symbol.el ends here diff --git a/users/wpcarro/emacs/.emacs.d/wpc/timestring.el b/users/wpcarro/emacs/.emacs.d/wpc/timestring.el deleted file mode 100644 index 245ace49e7..0000000000 --- a/users/wpcarro/emacs/.emacs.d/wpc/timestring.el +++ /dev/null @@ -1,77 +0,0 @@ -;;; timestring.el --- Quickly access timestamps in different formats -*- lexical-binding: t -*- - -;; Author: William Carroll <wpcarro@gmail.com> -;; Version: 0.0.1 -;; Package-Requires: ((emacs "25.1")) - -;;; Commentary: - -;; I was making some API calls where a URL needed a `since` parameter that of an -;; RFC 3339 encoded string. -;; -;; Because I didn't know what a RFC 3339 encoded -;; string was at the time, and because I didn't know what its format was -;; according to strftime, and because I'm most likely to forget both of these -;; things by the next time that I need something similar, I decided to write -;; this package so that I can accumulate a list of common time encodings. -;; -;; Thank you, Emacs. -;; -;; p.s. - I may turn this into a proper module and publish it. But not today. - -;;; Code: - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Dependencies -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -(require 'ts) - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Library -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -(defgroup timestring nil - "Customize group for timestring configuration.") - -(defcustom timestring-supported-encodings - '(("RFC 3339" . "%Y-%m-%dT%H:%M:%SZ") - ;; Does anyone recognize this format? - ("IDK" . "%Y-%m-%d %H:%M:%S %z")) - "Mapping of encoding names to their format strings." - :group 'timestring) - -(defcustom timestring-supported-times - '(("yesterday" . timestring--yesterday) - ("now" . ts-now) - ("tomorrow" . timestring--tomorrow)) - "Mapping of a labels to the functions that create those time objects." - :group 'timestring) - -(defun timestring--yesterday () - "Return a time object for yesterday." - (ts-adjust 'day -1 (ts-now))) - -(defun timestring--tomorrow () - "Return a time object for yesterday." - (ts-adjust 'day +1 (ts-now))) - -(defun timestring--completing-read (label xs) - "Call `completing-read' with LABEL over the collection XS." - (alist-get (completing-read label xs) xs nil nil #'equal)) - -(defun timestring-copy-encoded-time () - "Select a common time and an encoding. - -The selected time will be encoded using the selected encoding and copied onto -your clipboard." - (interactive) - (let ((time (funcall (timestring--completing-read - "Time: " timestring-supported-times))) - (fmt (timestring--completing-read - "Encoding: " timestring-supported-encodings))) - (kill-new (ts-format fmt time)) - (message "Copied!"))) - -(provide 'timestring) -;;; timestring.el ends here diff --git a/users/wpcarro/emacs/.emacs.d/wpc/tree.el b/users/wpcarro/emacs/.emacs.d/wpc/tree.el deleted file mode 100644 index 332e6c8d25..0000000000 --- a/users/wpcarro/emacs/.emacs.d/wpc/tree.el +++ /dev/null @@ -1,199 +0,0 @@ -;;; tree.el --- Working with Trees -*- lexical-binding: t -*- - -;; Author: William Carroll <wpcarro@gmail.com> -;; Version: 0.0.1 -;; Package-Requires: ((emacs "25.1")) - -;;; Commentary: -;; Some friendly functions that hopefully will make working with trees cheaper -;; and therefore more appealing! -;; -;; Tree terminology: -;; - leaf: node with zero children. -;; - root: node with zero parents. -;; - depth: measures a node's distance from the root node. This implies the -;; root node has a depth of zero. -;; - height: measures the longest traversal from a node to a leaf. This implies -;; that a leaf node has a height of zero. -;; - balanced? -;; -;; Tree variants: -;; - binary: the maximum number of children is two. -;; - binary search: the maximum number of children is two and left sub-trees are -;; lower in value than right sub-trees. -;; - rose: the number of children is variable. - -;;; Code: - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Dependencies -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -(require 'prelude) -(require 'list) -(require 'set) -(require 'tuple) -(require 'series) -(require 'random) -(require 'maybe) -(require 'cl-lib) - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Library -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -(cl-defstruct tree xs) - -(cl-defstruct node value children) - -(cl-defun tree-node (value &optional children) - "Create a node struct of VALUE with CHILDREN." - (make-node :value value - :children children)) - -(defun tree-reduce-breadth (acc f xs) - "Reduce over XS breadth-first applying F to each x and ACC (in that order). -Breadth-first traversals guarantee to find the shortest path in a graph. - They're typically more difficult to implement than DFTs and may also incur - higher memory costs on average than their depth-first counterparts.") - -;; TODO: Support :order as 'pre | 'in | 'post. -;; TODO: Troubleshoot why I need defensive (nil? node) check. -(defun tree-reduce-depth (acc f node) - "Reduce over NODE depth-first applying F to each NODE and ACC. -F is called with each NODE, ACC, and the current depth. -Depth-first traversals have the advantage of typically consuming less memory - than their breadth-first equivalents would have. They're also typically - easier to implement using recursion. This comes at the cost of not - guaranteeing to be able to find the shortest path in a graph." - (cl-labels ((do-reduce-depth - (acc f node depth) - (let ((acc-new (funcall f node acc depth))) - (if (or (maybe-nil? node) - (tree-leaf? node)) - acc-new - (list-reduce - acc-new - (lambda (node acc) - (tree-do-reduce-depth - acc - f - node - (number-inc depth))) - (node-children node)))))) - (do-reduce-depth acc f node 0))) - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Helpers -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -(defun tree-height (xs) - "Return the height of tree XS.") - -;; TODO: Troubleshoot why need for (nil? node). Similar misgiving -;; above. -(defun tree-leaf-depths (xs) - "Return a list of all of the depths of the leaf nodes in XS." - (list-reverse - (tree-reduce-depth - '() - (lambda (node acc depth) - (if (or (maybe-nil? node) - (tree-leaf? node)) - (list-cons depth acc) - acc)) - xs))) - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Generators -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -;; TODO: Consider parameterizing height, forced min-max branching, random -;; distributions, etc. - -;; TODO: Bail out before stack overflowing by consider branching, current-depth. - -(cl-defun tree-random (&optional (value-fn (lambda (_) nil)) - (branching-factor 2)) - "Randomly generate a tree with BRANCHING-FACTOR. - -This uses VALUE-FN to compute the node values. VALUE-FN is called with the -current-depth of the node. Useful for generating test data. Warning this -function can overflow the stack." - (cl-labels ((do-random - (d vf bf) - (make-node - :value (funcall vf d) - :children (->> (series/range 0 (number-dec bf)) - (list-map - (lambda (_) - (when (random-boolean?) - (do-random d vf bf)))))))) - (do-random 0 value-fn branching-factor))) - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Predicates -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -(defun tree-instance? (tree) - "Return t if TREE is a tree struct." - (node-p tree)) - -(defun tree-leaf? (node) - "Return t if NODE has no children." - (maybe-nil? (node-children node))) - -(defun tree-balanced? (n xs) - "Return t if the tree, XS, is balanced. -A tree is balanced if none of the differences between any two depths of two leaf - nodes in XS is greater than N." - (> n (->> xs - tree-leaf-depths - set-from-list - set-count - number-dec))) - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Tests -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -(defconst tree-enable-testing? t - "When t, test suite runs.") - -;; TODO: Create set of macros for a proper test suite including: -;; - describe (arbitrarily nestable) -;; - it (arbitrarily nestable) -;; - line numbers for errors -;; - accumulated output for synopsis -;; - do we want describe *and* it? Why not a generic label that works for both? -(when tree-enable-testing? - (let ((tree-a (tree-node 1 - (list (tree-node 2 - (list (tree-node 5) - (tree-node 6))) - (tree-node 3 - (list (tree-node 7) - (tree-node 8))) - (tree-node 4 - (list (tree-node 9) - (tree-node 10)))))) - (tree-b (tree-node 1 - (list (tree-node 2 - (list (tree-node 5) - (tree-node 6))) - (tree-node 3) - (tree-node 4 - (list (tree-node 9) - (tree-node 10))))))) - ;; instance? - (prelude-assert (tree-instance? tree-a)) - (prelude-assert (tree-instance? tree-b)) - (prelude-refute (tree-instance? '(1 2 3))) - (prelude-refute (tree-instance? "oak")) - ;; balanced? - (prelude-assert (tree-balanced? 1 tree-a)) - (prelude-refute (tree-balanced? 1 tree-b)) - (message "Tests pass!"))) - -(provide 'tree) -;;; tree.el ends here diff --git a/users/wpcarro/emacs/.emacs.d/wpc/tuple.el b/users/wpcarro/emacs/.emacs.d/wpc/tuple.el deleted file mode 100644 index 848c6fa48b..0000000000 --- a/users/wpcarro/emacs/.emacs.d/wpc/tuple.el +++ /dev/null @@ -1,93 +0,0 @@ -;;; tuple.el --- Tuple API for Elisp -*- lexical-binding: t -*- - -;; Author: William Carroll <wpcarro@gmail.com> -;; Version: 0.0.1 -;; Package-Requires: ((emacs "25.1")) - -;;; Commentary: -;; Work with cons cells with two elements with a familiar API for those who have -;; worked with tuples before. - -;;; Code: - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Library -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -(cl-defstruct tuple first second) - -;; Create -(defun tuple-new () - "Return an empty tuple." - (make-tuple :first nil - :second nil)) - -(defun tuple-from (a b) - "Return a new tuple from A and B." - (make-tuple :first a - :second b)) - -(defun tuple-from-dotted (dp) - "Convert dotted pair, DP, into a tuple." - (tuple-from (car dp) (cdr dp))) - -;; Read -(defun tuple-first (pair) - "Return the first element of PAIR." - (tuple-first pair)) - -(defun tuple-second (pair) - "Return the second element of PAIR." - (tuple-second pair)) - -;; Update -(defun tuple-map-each (f g pair) - "Apply F to first, G to second in PAIR." - (->> pair - (tuple-map-first f) - (tuple-map-second g))) - -(defun tuple-map (f pair) - "Apply F to PAIR." - (let ((pair-copy (copy-tuple pair))) - (funcall f pair-copy))) - -(defun tuple-map-first (f pair) - "Apply function F to the first element of PAIR." - (let ((pair-copy (copy-tuple pair))) - (setf (tuple-first pair-copy) (funcall f (tuple-first pair-copy))) - pair-copy)) - -(defun tuple-map-second (f pair) - "Apply function F to the second element of PAIR." - (let ((pair-copy (copy-tuple pair))) - (setf (tuple-second pair-copy) (funcall f (tuple-second pair-copy))) - pair-copy)) - -(defun tuple-set-first (a pair) - "Return a new tuple with the first element set as A in PAIR." - (tuple-map-first (lambda (_) a) pair)) - -(defun tuple-set-second (b pair) - "Return a new tuple with the second element set as B in PAIR." - (tuple-map-second (lambda (_) b) pair)) - -;; Delete -(defun tuple-delete-first (pair) - "Return PAIR with the first element set to nil." - (tuple-set-first nil pair)) - -(defun tuple-delete-second (pair) - "Return PAIR with the second element set to nil." - (tuple-set-second nil pair)) - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Predicates -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -(defun tuple-instance? (x) - "Return t if X is a tuple." - (tuple-p x)) - -(provide 'tuple) -;;; tuple.el ends here diff --git a/users/wpcarro/emacs/.emacs.d/wpc/vector.el b/users/wpcarro/emacs/.emacs.d/wpc/vector.el deleted file mode 100644 index 6b89708cef..0000000000 --- a/users/wpcarro/emacs/.emacs.d/wpc/vector.el +++ /dev/null @@ -1,84 +0,0 @@ -;;; vector.el --- Working with Elisp's Vector data type -*- lexical-binding: t -*- - -;; Author: William Carroll <wpcarro@gmail.com> -;; Version: 0.0.1 -;; Package-Requires: ((emacs "25.1")) - -;;; Commentary: -;; It might be best to think of Elisp vectors as tuples in languages like -;; Haskell or Erlang. -;; -;; Not surprisingly, this API is modelled after Elixir's Tuple API. -;; -;; Some Elisp trivia: -;; - "Array": Usually means vector or string. -;; - "Sequence": Usually means list or "array" (see above). -;; -;; It might be a good idea to think of Array and Sequence as typeclasses in -;; Elisp. This is perhaps more similar to Elixir's notion of the Enum protocol. -;; -;; Intentionally not supporting a to-list function, because tuples can contain -;; heterogenous types whereas lists should contain homogenous types. - -;;; Code: - -;; TODO: Consider supporting an alias named tuple for vector. - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Library -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -(defconst vector-enable-tests? t - "When t, run the tests defined herein.") - -;; TODO: Consider labelling variadic functions like `vector-concat*' -;; vs. `vector-concat'. -(defun vector-concat (&rest args) - "Return a new vector composed of all vectors in `ARGS'." - (apply #'vconcat args)) - -;; TODO: Here's a sketch of a protocol macro being consumed. -;; (definstance monoid vector -;; :empty (lambda () [])) - -(defun vector-prepend (x xs) - "Add `X' to the beginning of `XS'." - (vector-concat `[,x] xs)) - -(defun vector-append (x xs) - "Add `X' to the end of `XS'." - (vector-concat xs `[,x])) - -(defun vector-get (i xs) - "Return the value in `XS' at index, `I'." - (aref xs i)) - -(defun vector-set (i v xs) - "Set index `I' to value `V' in `XS'. -Returns a copy of `XS' with the updates." - (let ((copy (vconcat [] xs))) - (aset copy i v) - copy)) - -(defun vector-set! (i v xs) - "Set index `I' to value `V' in `XS'. -This function mutates XS." - (aset xs i v)) - -(when vector-enable-tests? - (let ((xs [1 2 3]) - (ys [1 2 3])) - (prelude-assert (= 1 (vector-get 0 ys))) - (vector-set 0 4 ys) - (prelude-assert (= 1 (vector-get 0 ys))) - (prelude-assert (= 1 (vector-get 0 xs))) - (vector-set! 0 4 xs) - (prelude-assert (= 4 (vector-get 0 xs))))) - -;; TODO: Decide between "remove" and "delete" as the appropriate verbs. -;; TODO: Implement this. -;; (defun vector/delete (i xs) -;; "Remove the element at `I' in `XS'.") - -(provide 'vector) -;;; vector.el ends here diff --git a/users/wpcarro/emacs/.emacs.d/wpc/vterm-mgt.el b/users/wpcarro/emacs/.emacs.d/wpc/vterm-mgt.el deleted file mode 100644 index ec9a04d1c8..0000000000 --- a/users/wpcarro/emacs/.emacs.d/wpc/vterm-mgt.el +++ /dev/null @@ -1,142 +0,0 @@ -;;; vterm-mgt.el --- Help me manage my vterm instances -*- lexical-binding: t -*- - -;; Author: William Carroll <wpcarro@gmail.com> -;; Version: 0.0.1 -;; Package-Requires: ((emacs "25.1")) - -;;; Commentary: -;; Supporting functions to instantiate vterm buffers, kill existing vterm -;; buffers, rename vterm buffers, cycle forwards and backwards through vterm -;; buffers. -;; -;; Many of the functions defined herein are intended to be bound to -;; `vterm-mode-map'. Some assertions are made to guard against calling -;; functions that are intended to be called from outside of a vterm buffer. -;; These assertions shouldn't error when the functions are bound to -;; `vterm-mode-map'. If for some reason, you'd like to bind these functions to -;; a separate keymap, caveat emptor. - -;;; Code: - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Dependencies -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -(require 'dash) -(require 'cycle) -(require 'vterm) - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Configuration -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -(defgroup vterm-mgt nil - "Customization options for `vterm-mgt'.") - -(defcustom vterm-mgt-scroll-on-focus nil - "When t, call `end-of-buffer' after focusing a vterm instance." - :type '(boolean) - :group 'vterm-mgt) - -(defconst vterm-mgt--instances (cycle-new) - "A cycle tracking all of my vterm instances.") - -(defun vterm-mgt--instance? (b) - "Return t if the buffer B is a vterm instance." - (equal 'vterm-mode (buffer-local-value 'major-mode b))) - -(defmacro vterm-mgt--assert-vterm-buffer () - "Error when the `current-buffer' is not a vterm buffer." - '(prelude-assert (vterm-mgt--instance? (current-buffer)))) - -(defun vterm-mgt-next () - "Replace the current buffer with the next item in `vterm-mgt--instances'. -This function should be called from a buffer running vterm." - (interactive) - (vterm-mgt--assert-vterm-buffer) - (vterm-mgt-reconcile-state) - (cycle-focus-item (current-buffer) vterm-mgt--instances) - (switch-to-buffer (cycle-next vterm-mgt--instances)) - (when vterm-mgt-scroll-on-focus (end-of-buffer))) - -(defun vterm-mgt-prev () - "Replace the current buffer with the previous item in `vterm-mgt--instances'. -This function should be called from a buffer running vterm." - (interactive) - (vterm-mgt--assert-vterm-buffer) - (vterm-mgt-reconcile-state) - (cycle-focus-item (current-buffer) vterm-mgt--instances) - (switch-to-buffer (cycle-prev vterm-mgt--instances)) - (when vterm-mgt-scroll-on-focus (end-of-buffer))) - -(defun vterm-mgt-instantiate () - "Create a new vterm instance. - -Prefer calling this function instead of `vterm'. This function ensures that the - newly created instance is added to `vterm-mgt--instances'. - -If however you must call `vterm', if you'd like to cycle through vterm - instances, make sure you call `vterm-mgt-reconcile-state' to allow vterm-mgt - to collect any untracked vterm instances." - (interactive) - (vterm-mgt-reconcile-state) - (let ((buffer (vterm t))) - (cycle-append buffer vterm-mgt--instances) - (cycle-focus-item buffer vterm-mgt--instances))) - -(defun vterm-mgt-kill () - "Kill the current buffer and remove it from `vterm-mgt--instances'. -This function should be called from a buffer running vterm." - (interactive) - (vterm-mgt--assert-vterm-buffer) - (let* ((buffer (current-buffer))) - (when (kill-buffer buffer) - (vterm-mgt-reconcile-state)))) - -(defun vterm-mgt-find-or-create () - "Call `switch-to-buffer' on a focused vterm instance if there is one. - -When `cycle-focused?' returns nil, focus the first item in the cycle. When -there are no items in the cycle, call `vterm-mgt-instantiate' to create a vterm -instance." - (interactive) - (vterm-mgt-reconcile-state) - (if (cycle-empty? vterm-mgt--instances) - (vterm-mgt-instantiate) - (if (cycle-focused? vterm-mgt--instances) - (switch-to-buffer (cycle-current vterm-mgt--instances)) - (progn - (cycle-jump 0 vterm-mgt--instances) - (switch-to-buffer (cycle-current vterm-mgt--instances)))))) - -(defun vterm-mgt-rename-buffer (name) - "Rename the current buffer ensuring that its NAME is wrapped in *vterm*<...>. -This function should be called from a buffer running vterm." - (interactive "SRename vterm buffer: ") - (vterm-mgt--assert-vterm-buffer) - (rename-buffer (format "*vterm*<%s>" name))) - -(defun vterm-mgt-reconcile-state () - "Fill `vterm-mgt--instances' with the existing vterm buffers. - -If for whatever reason, the state of `vterm-mgt--instances' is corrupted and - misaligns with the state of vterm buffers in Emacs, use this function to - restore the state." - (interactive) - (setq vterm-mgt--instances - (->> (buffer-list) - (-filter #'vterm-mgt--instance?) - cycle-from-list))) - -(defun vterm-mgt-select () - "Select a vterm instance by name from the list in `vterm-mgt--instances'." - (interactive) - (vterm-mgt-reconcile-state) - (switch-to-buffer - (completing-read "Switch to vterm: " - (->> vterm-mgt--instances - cycle-to-list - (-map #'buffer-name))))) - -(provide 'vterm-mgt) -;;; vterm-mgt.el ends here diff --git a/users/wpcarro/emacs/.emacs.d/wpc/window-manager.el b/users/wpcarro/emacs/.emacs.d/wpc/window-manager.el index 6e00979261..94fb99d427 100644 --- a/users/wpcarro/emacs/.emacs.d/wpc/window-manager.el +++ b/users/wpcarro/emacs/.emacs.d/wpc/window-manager.el @@ -97,12 +97,12 @@ (defun window-manager-next-workspace () "Cycle forwards to the next workspace." (interactive) - (window-manager--change-workspace (cycle-next window-manager--workspaces))) + (window-manager--change-workspace (cycle-next! window-manager--workspaces))) (defun window-manager-prev-workspace () "Cycle backwards to the previous workspace." (interactive) - (window-manager--change-workspace (cycle-prev window-manager--workspaces))) + (window-manager--change-workspace (cycle-prev! window-manager--workspaces))) ;; Here is the code required to toggle EXWM's modes. (defun window-manager--line-mode () @@ -120,7 +120,7 @@ (interactive) (with-current-buffer (window-buffer) (when (eq major-mode 'exwm-mode) - (funcall (cycle-next window-manager--modes))))) + (funcall (cycle-next! window-manager--modes))))) (defun window-manager--label->index (label workspaces) "Return the index of the workspace in WORKSPACES named LABEL." @@ -152,10 +152,10 @@ Currently using super- as the prefix for switching workspaces." (defun window-manager--switch (label) "Switch to a named workspaces using LABEL." - (cycle-focus (lambda (x) - (equal label - (window-manager-named-workspace-label x))) - window-manager--workspaces) + (cycle-focus! (lambda (x) + (equal label + (window-manager-named-workspace-label x))) + window-manager--workspaces) (window-manager--change-workspace (cycle-current window-manager--workspaces))) (defun window-manager-toggle-previous () @@ -196,21 +196,33 @@ predicate." cycle-current window-manager-named-workspace-label)) -(defun window-manager-swap-workspaces () - "Prompt the user to switch the current workspace with another." +(defun window-manager-workspace-move () + "Prompt the user to move the current workspace to another." (interactive) - (let* ((selection (->> window-manager-named-workspaces - (-map #'window-manager-named-workspace-label) - (-reject - (lambda (x) - (s-equals? x (window-manager-current-workspace)))) - (completing-read - (format "Swap current workspace (i.e. \"%s\") with: " - (window-manager-current-workspace))))) - (i (-find-index (lambda (x) - (s-equals? selection (window-manager-named-workspace-label x))) - window-manager-named-workspaces))) - (exwm-workspace-swap exwm-workspace--current (elt exwm-workspace--list i)))) + (exwm-workspace-move + exwm-workspace--current + (window-manager--label->index + (completing-read "Move current workspace to: " + (->> window-manager-named-workspaces + (-map #'window-manager-named-workspace-label)) + nil + t) + window-manager-named-workspaces))) + +(defun window-manager-move-window () + "Prompt the user to move the current window to another workspace." + (interactive) + (let ((window (get-buffer-window)) + (dest (completing-read "Move current window to: " + (->> window-manager-named-workspaces + (-map #'window-manager-named-workspace-label)) + nil + t))) + (exwm-workspace-move-window + (exwm-workspace--workspace-from-frame-or-index + (window-manager--label->index dest window-manager-named-workspaces)) + (exwm--buffer->id window)) + (window-manager--switch dest))) (provide 'window-manager) ;;; window-manager.el ends here diff --git a/users/wpcarro/emacs/.emacs.d/wpc/window.el b/users/wpcarro/emacs/.emacs.d/wpc/window.el deleted file mode 100644 index aec3c7012f..0000000000 --- a/users/wpcarro/emacs/.emacs.d/wpc/window.el +++ /dev/null @@ -1,40 +0,0 @@ -;;; window.el --- Working with windows -*- lexical-binding: t -*- - -;; Author: William Carroll <wpcarro@gmail.com> -;; Version: 0.0.1 -;; Package-Requires: ((emacs "25.1")) - -;;; Commentary: -;; Utilities to make CRUDing windows in Emacs easier. - -;;; Code: - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Dependencies -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -(require 'prelude) -(require 'macros) -(require 'maybe) - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Library -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -(defun window-find (name) - "Find a window by the NAME of the buffer it's hosting." - (let ((buffer (get-buffer name))) - (if (maybe-some? buffer) - (get-buffer-window buffer) - nil))) - -;; TODO: Find a way to incorporate these into function documentation. -(macros-comment - (window-find "*scratch*")) - -(defun window-delete (window) - "Delete the WINDOW reference." - (delete-window window)) - -(provide 'window) -;;; window.el ends here diff --git a/users/wpcarro/emacs/.emacs.d/wpc/wpc-dired.el b/users/wpcarro/emacs/.emacs.d/wpc/wpc-dired.el index 6df7ba4106..7c22a4657f 100644 --- a/users/wpcarro/emacs/.emacs.d/wpc/wpc-dired.el +++ b/users/wpcarro/emacs/.emacs.d/wpc/wpc-dired.el @@ -24,8 +24,7 @@ (progn (require 'dired) (setq dired-recursive-copies 'always - dired-recursive-deletes 'top - dired-dwim-target t) + dired-recursive-deletes 'top) (setq dired-listing-switches "-la --group-directories-first") (general-define-key :keymaps 'dired-mode-map diff --git a/users/wpcarro/emacs/.emacs.d/wpc/wpc-dotnet.el b/users/wpcarro/emacs/.emacs.d/wpc/wpc-dotnet.el new file mode 100644 index 0000000000..03fc430e48 --- /dev/null +++ b/users/wpcarro/emacs/.emacs.d/wpc/wpc-dotnet.el @@ -0,0 +1,16 @@ +;;; wpc-dotnet.el --- C# and company -*- lexical-binding: t -*- + +;; Author: William Carroll <wpcarro@gmail.com> + +;;; Commentary: +;; Windows things v0v. + +;;; Code: + +(require 'macros) + +(use-package csharp-mode) +(macros-support-file-extension "csproj" xml-mode) + +(provide 'wpc-dotnet) +;;; wpc-dotnet.el ends here diff --git a/users/wpcarro/emacs/.emacs.d/wpc/wpc-javascript.el b/users/wpcarro/emacs/.emacs.d/wpc/wpc-javascript.el index 7c1816c561..9e137ad880 100644 --- a/users/wpcarro/emacs/.emacs.d/wpc/wpc-javascript.el +++ b/users/wpcarro/emacs/.emacs.d/wpc/wpc-javascript.el @@ -42,11 +42,6 @@ js-indent-level 2 css-indent-offset 2) -;; Flow for Javascript -(use-package add-node-modules-path - :config - (general-add-hook wpc-javascript--js-hooks #'add-node-modules-path)) - (use-package web-mode :mode "\\.html\\'" :config diff --git a/users/wpcarro/emacs/.emacs.d/wpc/wpc-language-support.el b/users/wpcarro/emacs/.emacs.d/wpc/wpc-language-support.el new file mode 100644 index 0000000000..8363e3c08e --- /dev/null +++ b/users/wpcarro/emacs/.emacs.d/wpc/wpc-language-support.el @@ -0,0 +1,36 @@ +;;; wpc-language-support.el --- Support for miscellaneous programming languages -*- lexical-binding: t -*- + +;; Author: William Carroll <wpcarro@gmail.com> +;; Version: 0.0.1 +;; Package-Requires: ((emacs "25.1")) + +;;; Commentary: +;; I defined this module to declutter my init.el. +;; +;; When a particular programming-language's configuration gets too complicated, +;; I break it out into a dedicated module. Everything else gets dumped in +;; "Miscellaneous Configuration". + +;;; Code: + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Dedicated Modules +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +(require 'wpc-lisp) +(require 'wpc-haskell) +(require 'wpc-elixir) +(require 'wpc-nix) +(require 'wpc-rust) +(require 'wpc-clojure) +(require 'wpc-prolog) +(require 'wpc-dotnet) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Miscellaneous Configuration +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +(use-package terraform-mode) + +(provide 'wpc-language-support) +;;; wpc-language-support.el ends here diff --git a/users/wpcarro/emacs/.emacs.d/wpc/wpc-lisp.el b/users/wpcarro/emacs/.emacs.d/wpc/wpc-lisp.el index 4984e5dccd..599d426204 100644 --- a/users/wpcarro/emacs/.emacs.d/wpc/wpc-lisp.el +++ b/users/wpcarro/emacs/.emacs.d/wpc/wpc-lisp.el @@ -100,10 +100,18 @@ :config (general-add-hook 'emacs-lisp-mode #'ielm-mode)) +(defun wpc-lisp-copy-elisp-eval-output () + "Copy the output of the elisp evaluation" + (interactive) + (call-interactively 'eval-last-sexp) + (clipboard-copy (current-message) + :message (format "%s - copied!" (current-message)))) + (general-define-key :keymaps 'emacs-lisp-mode-map :prefix "<SPC>" :states 'normal + "c" #'wpc-lisp-copy-elisp-eval-output "x" #'eval-defun "X" #'eval-buffer "d" (lambda () diff --git a/users/wpcarro/emacs/.emacs.d/wpc/wpc-misc.el b/users/wpcarro/emacs/.emacs.d/wpc/wpc-misc.el index e2d01e2d23..36fbf8b12c 100644 --- a/users/wpcarro/emacs/.emacs.d/wpc/wpc-misc.el +++ b/users/wpcarro/emacs/.emacs.d/wpc/wpc-misc.el @@ -19,6 +19,7 @@ (require 'tvl) (require 'region) (require 'general) +(require 'constants) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Configuration @@ -67,9 +68,6 @@ (setq sh-basic-offset 2) (setq sh-indentation 2) -;; Emacs library that interfaces with my Linux password manager. -(use-package password-store) - (use-package vterm :config (general-define-key @@ -124,7 +122,7 @@ (company-mode -1) (flyspell-mode 1))) (setq magit-display-buffer-function - #'magit-display-buffer-fullframe-status-v1)) + #'magit-display-buffer-same-window-except-diff-v1)) (use-package magit-popup) @@ -179,12 +177,6 @@ ;; configure ibuffer (setq ibuffer-default-sorting-mode 'major-mode) -;; config Emacs to use $PATH values -(use-package exec-path-from-shell - :if (memq window-system '(mac ns)) - :config - (exec-path-from-shell-initialize)) - ;; Emacs autosave, backup, interlocking files (setq auto-save-default nil make-backup-files nil @@ -225,8 +217,9 @@ (use-package yasnippet :config - (setq yas-snippet-dirs (list (f-join user-emacs-directory "snippets"))) - (yas-global-mode 1)) + (unless constants-ci? + (setq yas-snippet-dirs (list (f-join user-emacs-directory "snippets"))) + (yas-global-mode 1))) (use-package projectile :config @@ -324,11 +317,10 @@ ;; Disable the default styles of: ;; - ascii :P (When this is enabled, the vim command, :x, renders as 😶) ;; - github :smile: - (setq emojify-emoji-styles '(unicode)) - (defun wpc-misc-copy-emoji () - "Select an emoji from the completing-read menu." - (interactive) - (clipboard-copy (emojify-completing-read "Copy: ")))) + (setq emojify-emoji-styles '(unicode))) + +;; Always auto-close parantheses and other pairs +(electric-pair-mode) ;; Start the Emacs server (when (not (server-running-p)) diff --git a/users/wpcarro/emacs/.emacs.d/wpc/wpc-rust.el b/users/wpcarro/emacs/.emacs.d/wpc/wpc-rust.el index dfee2fc86b..b609efb431 100644 --- a/users/wpcarro/emacs/.emacs.d/wpc/wpc-rust.el +++ b/users/wpcarro/emacs/.emacs.d/wpc/wpc-rust.el @@ -6,11 +6,6 @@ ;;; Commentary: ;; Supports my Rust work. -;; -;; Dependencies: -;; - `rustup` -;; - `rustup component add rust-src` -;; - `rustup toolchain add nightly && cargo +nightly install racer` ;;; Code: @@ -18,30 +13,18 @@ ;; Dependencies ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -(require 'macros) +(require 'lsp) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Configuration ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -(use-package racer - :config - (setq rust-sysroot (->> "~/.cargo/bin/rustc --print sysroot" - shell-command-to-string - s-trim-right)) - (setq racer-rust-src-path (f-join rust-sysroot "lib/rustlib/src/rust/src")) - (add-hook 'racer-mode-hook #'eldoc-mode)) - (use-package rust-mode :config - (add-hook 'rust-mode-hook #'racer-mode) - (macros-add-hook-before-save 'rust-mode-hook #'rust-format-buffer) - (define-key rust-mode-map - (kbd "TAB") - #'company-indent-or-complete-common) - (define-key rust-mode-map - (kbd "M-d") - #'racer-describe)) + (setq lsp-rust-server #'rust-analyzer) + (setq rust-format-show-buffer nil) + (setq rust-format-on-save t) + (add-hook 'rust-mode-hook #'lsp)) (provide 'wpc-rust) ;;; wpc-rust.el ends here diff --git a/users/wpcarro/emacs/.emacs.d/wpc/wpc-ui.el b/users/wpcarro/emacs/.emacs.d/wpc/wpc-ui.el index f3fb8324c2..a2f533cec0 100644 --- a/users/wpcarro/emacs/.emacs.d/wpc/wpc-ui.el +++ b/users/wpcarro/emacs/.emacs.d/wpc/wpc-ui.el @@ -13,16 +13,15 @@ ;; Dependencies ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -(require 'constants) -(require 'tvl) -(require 'prelude) +(require '>) (require 'al) +(require 'constants) +(require 'dash) (require 'fonts) -(require 'colorscheme) -(require 'device) -(require 'laptop-battery) -(require 'modeline) (require 'general) +(require 'modeline) +(require 'prelude) +(require 'theme) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Configuration @@ -70,9 +69,6 @@ ;; disable toolbar (tool-bar-mode -1) -;; set default buffer for Emacs -(setq initial-buffer-choice tvl-depot-path) - ;; premium Emacs themes (use-package doom-themes :config @@ -110,16 +106,16 @@ (use-package ivy-prescient :config (ivy-prescient-mode 1) - (prescient-persist-mode 1)) - -(use-package ivy-pass) + (unless constants-ci? + (prescient-persist-mode 1))) ;; all-the-icons (use-package all-the-icons :config - (when (not constants-ci?) - (unless (f-exists? "~/.local/share/fonts/all-the-icons.ttf") - (all-the-icons-install-fonts t)))) + (unless (or constants-ci? + (f-exists? "~/.local/share/fonts/all-the-icons.ttf") + (f-exists? "~/Library/Fonts/all-the-icons.ttf")) + (all-the-icons-install-fonts t))) ;; icons for Ivy (use-package all-the-icons-ivy @@ -140,8 +136,8 @@ ;; example, Google Java projects prefer 100 character width instead of 80 ;; character width. (setq whitespace-line-column 80) - (setq whitespace-style '(face lines-tail)) - (add-hook 'prog-mode-hook #'whitespace-mode)) + (setq whitespace-style '(face lines-tail tabs)) + (global-whitespace-mode t)) ;; dirname/filename instead of filename<dirname> (setq uniquify-buffer-name-style 'forward) @@ -160,15 +156,24 @@ :config (setq alert-default-style 'notifier)) -;; TODO: Should `device-laptop?' be a function or a constant that gets set -;; during initialization? -(when (device-laptop?) (laptop-battery-display)) +(display-battery-mode 1) -(colorscheme-whitelist-set 'doom-peacock) +(setq theme-whitelist + (->> (custom-available-themes) + (list-map #'symbol-name) + (list-filter (>-> (s-starts-with? "doom-"))) + (list-map #'intern) + cycle-from-list)) +(setq theme-linum-color-override "da5478") +(add-hook 'theme-after-change + (lambda () (prelude-set-line-number-color "#da5478"))) +(theme-whitelist-set 'doom-flatwhite) (when window-system - (let ((font "Monospace")) - (fonts-whitelist-set font) + ;; On OSX, JetBrainsMono is installed as "JetBrains Mono", and I'm + ;; not sure how to change that. + (let ((font (if constants-osx? "JetBrains Mono" "JetBrainsMono"))) + (fonts-set font) ;; Some themes (e.g. doom-acario-*) change the font for comments. This ;; should prevent that. (set-face-attribute font-lock-comment-face nil diff --git a/users/wpcarro/emacs/.emacs.d/wpc/zle.el b/users/wpcarro/emacs/.emacs.d/wpc/zle.el deleted file mode 100644 index d4aa88258f..0000000000 --- a/users/wpcarro/emacs/.emacs.d/wpc/zle.el +++ /dev/null @@ -1,91 +0,0 @@ -;;; zle.el --- Functions to mimmick my ZLE KBDs -*- lexical-binding: t -*- - -;; Author: William Carroll <wpcarro@gmail.com> -;; Version: 0.0.1 -;; Package-Requires: ((emacs "24")) - -;;; Commentary: -;; This is primarily for personal use. The keybindings that I choose are those -;; that feel slightly mnemonic while also not shadowing important bindings. -;; It's quite possible that our tastes will differ here. -;; -;; All of these keybindings are intended to shave off milliseconds off your -;; typing. I don't expect these numbers to sum up to a meaningful amount. The -;; primary reason that I wrote this, is that it introduces a small amount of -;; structural editing to my workflow. I've been using these exact keybindings -;; on the command line, and I find them subtely delightful to use. So much so -;; that I decided to bring them to my Emacs configuration. -;; -;; ZLE is the Z-shell line editor. I have some KBDs and functions that I often -;; want in Emacs. -;; -;; Usage: -;; Consider running `(zle-minor-mode)' to run this globally. Depending on your -;; configuration, it could be non-disruptive, disruptive, or extremely -;; disruptive. - -;;; Code: - -;; subshell (C-j) -(defun zle-subshell () - "Insert the characters necessary to create a subshell." - (interactive) - (insert-char ?$) - (insert-char ?\() - (save-excursion - (insert-char ?\)))) - -;; variable (C-v) -(defun zle-variable () - "Insert the characters to reference a variable." - (interactive) - (insert-char ?$) - (insert-char ?{) - (save-excursion - (insert-char ?}))) - -;; 2x dash (C-M--) -(defun zle-dash-dash () - "Insert the characters for flags with 2x dashes." - (interactive) - (insert-char ? ) - (insert-char ?-) - (insert-char ?-)) - -;; 1x quotes (M-') -(defun zle-single-quote () - "Insert the characters to quickly create single quotes." - (interactive) - (insert-char ? ) - (insert-char ?') - (save-excursion - (insert-char ?'))) - -;; 2x quotes (M-") -(defun zle-double-quote () - "Insert the characters to quickly create double quotes." - (interactive) - (insert-char ? ) - (insert-char ?\") - (save-excursion - (insert-char ?\"))) - -(defvar zle-kbds - (let ((map (make-sparse-keymap))) - (bind-keys :map map - ("C-j" . zle-subshell) - ("C-v" . zle-variable) - ("C-M--" . zle-dash-dash) - ("M-'" . zle-single-quote) - ("M-\"" . zle-double-quote)) - map) - "Keybindings shaving milliseconds off of typing.") - -(define-minor-mode zle-minor-mode - "A minor mode mirroring my ZLE keybindings." - :init-value nil - :lighter " zle" - :keymap zle-kbds) - -(provide 'zle) -;;; zle.el ends here |