]> git.earman.xyz Git - emacsinit.git/commitdiff
back to their own dir
authorrearman <rearman@r717.net>
Tue, 5 May 2026 17:09:06 +0000 (13:09 -0400)
committerrearman <rearman@r717.net>
Tue, 5 May 2026 17:09:06 +0000 (13:09 -0400)
re-howm.el [deleted file]
re-mu4e.el [deleted file]
re-org.el [deleted file]
re-packages.el [deleted file]
re-pass-alike.el [deleted file]
re/re-howm.el [new file with mode: 0644]
re/re-mu4e.el [new file with mode: 0644]
re/re-org.el [new file with mode: 0644]
re/re-packages.el [new file with mode: 0644]
re/re-pass-alike.el [new file with mode: 0644]

diff --git a/re-howm.el b/re-howm.el
deleted file mode 100644 (file)
index aff9e5e..0000000
+++ /dev/null
@@ -1,71 +0,0 @@
-;;; re-howm.el -*- lexical-binding: t; -*-
-;; This file is not part of GNU Emacs
-
-;;; Code:
-
-(setq howm-template-list '("= %title%cursor #inbox\n%date %file\n\n"
-                          "= %title%cursor #meeting\n%date %file\n\nAttendees: \n"
-                          "= @%title%cursor\n%date %file\n\n")
-      howm-template howm-template-list
-      howm-keyword-file "~/howm/.howm-keys"
-      howm-history-file "~/howm/.howm-history"
-      howm-menu-file "~/.emacs.d/0000-00-00-000000.txt"
-      howm-file-name-format "%Y%m%dT%H%M%S.txt"
-      howm-keyword-case-fold-search t
-      howm-remember-insertion-format "%s"
-      howm-menu-todo-num 10)
-
-(defun re/howm-menu-new-frame (&optional arg)
-  "Show the howm menu in a new frame"
-  (interactive "P")
-  (re/open-with-new-frame "HOWM" #'howm-menu))
-
-(defun re/howm-create-keyword ()
-  "Reads a keyword from the minibuffer and appends it to the keywords file."
-  (interactive)
-  (append-to-file (concat (read-string "New Keyword: ")
-                         "\n")
-                 nil
-                 howm-keyword-file))
-\f
-;; Menu tweaks
-
-;; add entries in howm-menu (press enter on the text)
-(dolist (aldr-additions '(("\\[Mtg\\]"
-                          (lambda (&optional dummy)
-                            (howm-create 2)))
-                         ("\\[Person\\]"
-                          (lambda (&optional dummy)
-                            (howm-create 3)))))
-  (add-to-list 'action-lock-default-rules
-              aldr-additions
-              t))
-
-(defun re/howm-menu-legend ()
-  (cl-labels ((p (text face) (propertize text 'font-lock-face face)))
-    (concat (format "Top %s" howm-menu-todo-num)
-           " "
-           (p "!Deadline" howm-reminder-deadline-face)
-           "/"
-           (p "+ToDo" howm-reminder-todo-face)
-           "/"
-           (p "@Schedule" howm-reminder-schedule-face)
-           "/"
-           (p "~Defer" howm-reminder-defer-face)
-           "/"
-           (p "-Reminder" howm-reminder-normal-face)
-           " Entries:")))
-
-(add-to-list 'howm-menu-allow 're/howm-menu-legend)
-
-;; add coloring for custom "waiting" state
-(add-to-list 'howm-reminder-font-lock-keywords
-            `(,(howm-reminder-regexp "[w]")
-              (0 howm-reminder-defer-face prepend))
-            t)
-
-(dolist (hooks '(after-save-hook howm-mode-hook))
-  (add-hook hooks 'howm-mode-set-buffer-name))
-
-(provide 're-howm)
-;;; re-howm.el ends here
diff --git a/re-mu4e.el b/re-mu4e.el
deleted file mode 100644 (file)
index 8c9c526..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-;;; re-mu4e.el --- Setup mu4e --- -*- lexical-binding: t; -*-
-;; This file is not part of GNU Emacs
-
-;;; Code:
-
-(use-package mu4e
-  :ensure nil
-  :config
-  (setq mu4e-get-mail-command "mbsync -a"
-       mu4e-update-interval (* 10 60)
-       mu4e-change-filenames-when-moving t
-       mu4e-use-fancy-chars t
-       mu4e-attachment-dir "~/downloads"
-       mu4e-compose-reply-to-address "iv@earman.xyz"
-       mu4e-maildir "~/mail"
-       mu4e-drafts-folder "/iv/Drafts"
-       mu4e-sent-folder "/iv/Sent"
-       mu4e-trash-folder "/iv/Trash"
-       mu4e-maildir-shortcuts '((:maildir "/iv/inbox" :key ?i)
-                                (:maildir "/iv/Sent" :key ?s)
-                                (:maildir "/iv/Trash" :key ?t)
-                                (:maildir "/iv/Drafts" :key ?d))))
-
-(setq mail-user-agent 'message-user-agent
-      message-send-mail-function 'smtpmail-send-it
-      message-citation-line-format "Quoth %f :\n"
-      smtpmail-default-smtp-server "mail.earman.xyz"
-      smtpmail-smtp-server "mail.earman.xyz"
-      smtpmail-smtp-service 587
-      smtpmail-stream-type 'starttls
-      smtpmail-local-domain "earman.xyz"
-      smtpmail-queue-mail nil
-      smtpmail-queue-dir "~/mail/iv/outbox/cur")
-
-(setq user-mail-address "iv@earman.xyz"
-      user-full-name "Rush N. Earman IV"
-      message-signature "Rush Earman IV, PE"
-      message-kill-buffer-on-exit t)
-
-(provide 're-mu4e)
-;;; re-mu4e.el ends here
diff --git a/re-org.el b/re-org.el
deleted file mode 100644 (file)
index a956c61..0000000
--- a/re-org.el
+++ /dev/null
@@ -1,175 +0,0 @@
-;;; re-org.el --- org-mode bespokeniŋ -*- lexical-binding: t; -*-
-;; This file is not part of GNU Emacs
-
-;;; Code:
-
-;; General options
-(add-to-list 'org-export-backends 'md)
-
-(setq org-startup-indented t
-      org-startup-folded 'fold
-      org-startup-with-inline-images t
-      org-cycle-inline-images-display t
-      org-cycle-separator-lines 0
-      org-blank-before-new-entry '((heading) (plain-list-item . auto))
-      org-M-RET-may-split-line nil
-      org-treat-S-cursor-todo-selection-as-state-change nil
-      org-treat-insert-todo-heading-as-state-change nil
-      org-table-export-default-format "orgtbl-to-csv"
-      org-list-allow-alphabetical t
-      org-fold-catch-invisible-edits 'show-and-error
-      org-ellipsis " ↴"
-      org-tags-column 0
-      org-enforce-todo-dependencies t
-      org-enforce-todo-checkbox-dependencies t
-      org-fontify-done-headline nil
-      org-fontify-todo-headline nil
-      org-goto-interface 'outline-path-completion
-      org-outline-path-complete-in-steps nil
-      org-goto-auto-isearch nil
-      org-special-ctrl-a/e t
-      org-special-ctrl-k t
-      org-return-follows-link t
-      org-yank-adjusted-subtrees t
-      org-todo-keyword-faces '(("WAITING" :foreground "#e15400" :weight bold)
-                              ("UNDERTAKEN" :foreground "magenta" :weight bold)
-                              ("MEETING" :foreground "#315e9a" :weight bold)))
-
-(add-hook 'org-agenda-mode-hook #'hl-line-mode)
-
-\f
-;; Time Clocking
-(org-clock-persistence-insinuate)
-(setq org-clock-history-length 10
-      org-clock-in-resume t
-      org-clock-out-remove-zero-time-clocks t
-      org-clock-persist t
-      org-clock-persist-query-resume nil
-      org-clock-report-include-clocking-task t
-      org-time-stamp-rounding-minutes '(1 1))
-
-\f
-;; Agenda and capture
-(setq org-agenda-files (append '("~/org/")
-                        (file-expand-wildcards "~/projects/*/"))
-      org-refile-targets '((nil :maxlevel . 9)
-                          (org-agenda-files :maxlevel . 9))
-      org-refile-use-outline-path 'file
-      org-refile-allow-creating-parent-nodes 'confirm
-      org-todo-keywords '((sequence "TODO(t)" "WAITING(w@)" "|" "DONE(d)" "BELAYED(b@)" "GIVEN(g@)")
-                         (sequence "MEETING(m)" "|" "MET(M)"))
-      org-tag-alist '(("call" . ?c)
-                     ("email" . ?e)
-                     ("errand" . ?r)
-                     ("jobpc" . ?j)
-                     ("license" . ?l)
-                     ("open" . ?o))
-      org-tags-exclude-from-inheritance '("open")
-      org-agenda-restore-windows-after-quit t
-      org-agenda-start-on-weekday nil
-      org-agenda-compact-blocks t
-      org-agenda-span 'day
-      org-deadline-warning-days 30
-      org-agenda-window-setup 'current-window
-      org-agenda-time-grid '((daily today remove-match)
-                            (600 700 800 900 1000 1100 1200 1300 1400 1500 1600 1700 1800 1900)
-                            " ――――― "
-                            "")
-      org-agenda-tags-column 0
-      org-agenda-remove-tags t
-      org-agenda-skip-additional-timestamps-same-entry t
-      org-agenda-skip-deadline-if-done t
-      org-agenda-skip-scheduled-if-done t
-      org-agenda-prefix-format '((agenda . "%25c:%?-12t% s")
-                                (todo . "%25c:%?-12t% s")
-                                (tags . "%25c:%?-12t% s")
-                                (search . "%25c:%?-12t% s"))
-      org-agenda-scheduled-leaders '("BOOKED: " "Booked %2d d. ago: ")
-      org-agenda-deadline-leaders '("DEADLINE: " "In %3d d.: " "%2d d. ago: ")
-      org-read-date-prefer-future 'time
-      org-agenda-custom-commands
-      '(("d" "Done items" todo "DONE|BELAYED|GIVEN|MET" ((org-agenda-skip-function
-                                                         '(org-agenda-skip-entry-if 'notregexp "^\\*\\* "))
-                                                        (org-agenda-overriding-header "DONE - MAYBE KEEP:")))
-       ("f" "Maybe Someday" tags "someday" ((org-agenda-skip-function
-                                             '(org-agenda-skip-entry-if 'regexp "^\\* someday"))
-                                            (org-agenda-overriding-header "SOMEDAY:")))
-       ("i" "Inbox" tags "inbox" ((org-agenda-skip-function
-                                   '(org-agenda-skip-entry-if 'regexp "^\\* inbox"))
-                                  (org-agenda-overriding-header "INBOX:")))
-       ("l" "Licenses" tags "license" ((org-agenda-overriding-header "LICENSES:")))
-       ("n" "Next Actions" tags-todo "-recurring/TODO" ((org-agenda-overriding-header "NEXT:")
-                                                        (org-agenda-sorting-strategy
-                                                         '((agenda tag-up time-up)))))
-       ("p" "JobPCs" tags "jobpc" ((org-agenda-overriding-header "JOB PCS:")))
-       ("u" "Undertakings" tags "open" ((org-agenda-overriding-header "UNDERTAKINGS:")))
-       ("w" "Waiting" todo "WAITING" ((org-agenda-overriding-header "WAITING:")))
-       ("o" "Overview" ((agenda "")
-                        (tags "inbox" ((org-agenda-overriding-header "\nINBOX:")))
-                        (tags "open" ((org-agenda-skip-function
-                                       '(org-agenda-skip-entry-if 'notregexp "^\\* "))
-                                      (org-agenda-overriding-header "\nUNDERTAKINGS:")))
-                        (todo "WAITING" ((org-agenda-overriding-header "\nWAITING:"))))))
-      org-agenda-start-with-log-mode t
-      org-agenda-log-mode-items '(closed clock state)
-      org-log-done 'time
-      org-log-into-drawer t
-      org-capture-templates '(("i" "Inbox" entry
-                              (file "inbox.org")
-                              "* %^{Description}\n%U\n%?"
-                              :clock-in t
-                              :clock-resume t)
-                             ("m" "Meeting" entry
-                              (file "inbox.org")
-                              "* %^{Description}\n%^{Scheduled:}T\n%?"
-                              :clock-in t
-                              :clock-resume t)
-                             ("p" "Phone Call" entry
-                              (file "inbox.org")
-                              "* %^{Description} :call:\n%U\n%?"
-                              :clock-in t
-                              :clock-resume t))
-      org-id-link-to-org-use-id 'create-if-interactive-and-no-custom-id
-      org-id-method 'ts
-      org-clone-delete-id t
-      org-attach-id-to-path-function-list '(org-attach-id-ts-folder-format
-                                           org-attach-id-uuid-folder-format))
-
-(defun re/org-auto-generate-ids-in-file ()
-  "Add ID properties to all headlines in the current
- file which do not already have one."
-  (interactive)
-  (org-map-entries 'org-id-get-create))
-
-(defun re/org-save-all ()
-  "Save all `org-agenda-files' without user confirmation."
-  (interactive)
-  (message "Saving all org-agenda-files buffers...")
-  (save-some-buffers t
-                    (lambda ()
-                      (when (member (buffer-file-name) org-agenda-files) t)))
-  (message "Saving all org-agenda-files buffers... done"))
-
-(advice-add 'org-refile :after (lambda (&rest _) (re/org-save-all)))
-\f
-;; Archiving (use re/org-archive-all periodically)
-(defun re/org-archive-all ()
-  "Archive all tasks marked `DONE' in agenda files"
-  (interactive)
-  (message "Archiving all completed tasks in org-agenda-files...")
-  (org-map-entries (lambda ()
-                    (org-archive-subtree)
-                    (setq org-map-continue-from (org-element-property
-                                                 :begin
-                                                 (org-element-at-point))))
-                  "/DONE"
-                  'agenda)
-  (message "Archiving all completed tasks in org-agenda-files... done"))
-
-(setq org-archive-location (concat "~/org/old.org_keep::datetree/")
-      org-agenda-text-search-extra-files '(agenda-archives))
-
-(add-to-list 'auto-mode-alist '("\\.org_keep\\'" . org-mode))
-
-(provide 're-org)
-;;; re-org.el ends here
diff --git a/re-packages.el b/re-packages.el
deleted file mode 100644 (file)
index 4d4fe4f..0000000
+++ /dev/null
@@ -1,158 +0,0 @@
-;;; re-packages.el --- Load Packs -*-  lexical-binding: t; -*-
-;; This file is not part of Emacs.
-
-;;; Code:
-
-(require 'package)
-
-(add-to-list 'package-archives '("melpa" . "https://melpa.org/packages/") t)
-
-(setq use-package-always-ensure t
-      use-package-always-demand t)
-\f
-;; UI/Editing
-
-(use-package corfu
-  :custom
-  (corfu-auto t)
-  (corfu-auto-delay 0)
-  (corfu-auto-prefix 1)
-  :config
-  (global-corfu-mode))
-
-(use-package corfu-popupinfo
-  :ensure
-  nil ; part of corfu
-  :after
-  corfu
-  :hook
-  (corfu-mode . corfu-popupinfo-mode)
-  :custom
-  (corfu-popupinfo-delay '(nil . 0.01)) ; start with M-t, fast refresh once on
-  (corfu-popupinfo-hide nil)
-  :config
-  (corfu-popupinfo-mode))
-
-(use-package expand-region
-  :bind
-  (("C-=" . er/expand-region)))
-
-(use-package aggressive-indent)
-
-(use-package magit
-  :defer
-  t
-  :config
-  (message "Magit Loaded"))
-
-(use-package page-break-lines
-  :config
-  (global-page-break-lines-mode))
-\f
-;; Filetypes
-(use-package auctex
-  :config
-  (setq TeX-auto-save t
-       TeX-parse-self t
-       TeX-PDF-mode t)
-  (setq-default TeX-master nil))
-
-(use-package csv-mode
-  :config
-  (add-hook 'csv-mode-hook 'csv-align-mode))
-
-(use-package markdown-mode
-  :config
-  (setq markdown-special-ctrl-a/e t)
-  :bind
-  (:map markdown-mode-map
-       ("M-<right>" . markdown-demote)
-       ("M-<left>" . markdown-promote)
-       ("M-<up>" . markdown-move-up)
-       ("M-<down>" . markdown-move-down)
-       ("C-M-u" . markdown-up-heading)
-       ("C-M-b" . markdown-outline-previous-same-level)
-       ("C-M-f" . markdown-outline-next-same-level)
-       ("C-M-p" . markdown-outline-previous)
-       ("C-M-n" . markdown-outline-next)))
-
-(use-package edit-indirect :after 'markdown-mode)
-\f
-;; REPLs
-(use-package sly
-  :config
-  (setq inferior-lisp-program "sbcl"
-       sly-net-coding-system 'utf-8-unix
-       sly-command-switch-to-existing-lisp 'always)
-  (let ((core (expand-file-name "~/sbcl.core-for-sly")))
-    (when (file-exists-p core)
-      (setq sly-lisp-implementations (list `(sbcl ("sbcl" "--core" ,core)))))))
-
-(use-package geiser
-  :config
-  (if (equal system-type 'windows-nt)
-      (setq geiser-chicken-binary '("C:/tools/chicken/bin/csi.exe" "-:c"))
-    (setq geiser-chicken-binary "csi -:c"))
-  (setq scheme-program-name geiser-chicken-binary
-       geiser-active-implementations '(chicken))
-  (add-hook 'scheme-mode-hook 'geiser-mode))
-
-(use-package geiser-chicken :after 'geiser)
-
-(use-package forth-mode)
-\f
-;; PIM
-(use-package org
-  :config
-  (require 're-org)
-  :bind
-  (("C-c l" . org-store-link)
-   ("C-c a" . org-agenda)
-   ("C-c c" . org-capture)
-   ("C-c b" . org-switchb)
-   ("<f10>" . org-clock-out)
-   ("<f2>" . org-clock-goto)
-   :map org-mode-map
-   ("M-<right>" . org-shiftmetaright)
-   ("M-<left>" . org-shiftmetaleft)
-   ("M-S-<right>" . org-metaright)
-   ("M-S-<left>" . org-metaleft)
-   ("C-M-h" . org-mark-subtree)
-   ("C-M-u" . org-up-element)
-   ("C-M-d" . org-down-element)
-   ("C-M-b" . org-backward-heading-same-level)
-   ("C-M-f" . org-forward-heading-same-level)
-   ("C-M-p" . org-previous-visible-heading)
-   ("C-M-n" . org-next-visible-heading)
-   ("<f9>" . org-clock-in)))
-
-(use-package org-transclusion
-  :after
-  org
-  :bind
-  (("C-c t" . org-transclusion-mode)))
-
-(with-eval-after-load 'org-transclusion
-  (add-to-list 'org-transclusion-extensions 'org-transclusion-indent-mode)
-  (require 'org-transclusion-indent-mode))
-
-(use-package howm
-  :config
-  (require 're-howm)
-  :bind
-  (("<f6>" . howm-menu)
-   ("S-<f6>" . re/howm-menu-new-frame)
-   :map howm-mode-map
-   ("C-c , k" . re/howm-create-keyword)
-   ("C-c , =" . howm-narrow-to-memo)))
-\f
-;; MISC
-(use-package trashed
-  :config
-  (setq trashed-action-confirmer 'y-or-n-p
-       trashed-use-header-line t
-       trashed-sort-key '("Date deleted" . t)
-       trashed-date-format "%Y-%m-%d %H:%M:%S"))
-
-(provide 're-packages)
-;;; re-packages.el ends here
diff --git a/re-pass-alike.el b/re-pass-alike.el
deleted file mode 100644 (file)
index 35d3fb7..0000000
+++ /dev/null
@@ -1,149 +0,0 @@
-;;; re-pass-alike.el -*- lexical-binding: t; -*-
-;; This file is not part of GNU Emacs.
-
-;;; Code:
-
-;; Generate totp code
-(dolist (requirement '(bindat gnutls hexl auth-source))
-  (require requirement))
-
-(defun totp--hex-decode-string (string)
-  "Hex-decode STRING and return the result as a unibyte string."
-  (apply #'unibyte-string
-        (seq-map (lambda (s) (hexl-htoi (aref s 0) (aref s 1)))
-                 (seq-partition string 2))))
-
-(defun totp (string &optional time digits)
-  "Return a TOTP token using the secret hex STRING and current time.
-TIME is used as counter value instead of current time, if non-nil.
-DIGITS is the number of pin digits and defaults to 6."
-  (let* ((key-bytes (totp--hex-decode-string (upcase string)))
-        (counter (truncate (/ (or time (time-to-seconds)) 30)))
-        (digits (or digits 6))
-        (format-string (format "%%0%dd" digits))
-        ;; we have to manually split the 64 bit number (u64 not supported in Emacs 27.2)
-        (counter-bytes (bindat-pack  '((:high u32) (:low u32))
-                                     `((:high . ,(ash counter -32)) (:low . ,(logand counter #xffffffff)))))
-        (mac (gnutls-hash-mac 'SHA1 key-bytes counter-bytes))
-        (offset (logand (bindat-get-field (bindat-unpack '((:offset u8)) mac 19) :offset) #xf)))
-    (format format-string
-           (mod
-            (logand (bindat-get-field (bindat-unpack '((:totp-pin u32)) mac  offset) :totp-pin)
-                    #x7fffffff)
-            (expt 10 digits)))))
-
-(defconst base32-alphabet
-  (let ((tbl (make-char-table nil)))
-    (dolist (mapping '(("A" . 0) ("B" . 1) ("C" . 2) ("D" . 3)
-                      ("E" . 4) ("F" . 5) ("G" . 6)
-                      ("H" . 7) ("I" . 8) ("J" . 9) ("K" . 10)
-                      ("L" . 11) ("M" . 12) ("N" . 13)
-                      ("O" . 14) ("P" . 15) ("Q" . 16) ("R" . 17)
-                      ("S" . 18) ("T" . 19) ("U" . 20)
-                      ("V" . 21) ("W" . 22) ("X" . 23) ("Y" . 24)
-                      ("Z" . 25) ("2" . 26) ("3" . 27)
-                      ("4" . 28) ("5" . 29) ("6" . 30) ("7" . 31)))
-      (aset tbl (string-to-char (car mapping)) (cdr mapping)))
-    tbl)
-  "Base-32 mapping table, as defined in RFC 4648.")
-
-(defun base32-hex-decode (string)
-  "The cheats' version of base-32 decode.
-
-This is not a 100% faithful implementation of RFC 4648. The
-concept of encoding partial quanta is not implemented fully.
-
-No attempt is made to pad the output either as that is not
-required for HMAC-TOTP."
-  (unless (mod (length string) 8)
-    (error "Padding is incorrect"))
-  (setq string (upcase string))
-  (let ((trimmed-array (append (string-trim-right string "=+") nil)))
-    (format "%X" (seq-reduce
-                 (lambda (acc char) (+ (ash acc 5) (aref base32-alphabet char)))
-                 trimmed-array 0))))
-
-(defun keyfile-string (filename)
-  "Return a string which is the filepath to a `pass(1)' file."
-  (let ((directory "~/.password-store/"))
-    (if (null filename)
-       (read-file-name "Select a password: " directory nil t nil)
-      (concat directory
-             (if (stringp filename)
-                 filename
-               (symbol-name filename))
-             ".gpg"))))
-
-(defun get-totp (&optional filename)
-  "Generate a totp code given a file with the secret hex string.
-If no filename given, prompt for one.
-Assumes the file has the string by itself on the last line of the file,
-similar to what pass-otp does, but without the full uri.
-Also assumes the file is in `~/.password-store' and has the `.gpg' extension."
-  (totp (base32-hex-decode (re/get-line-from-file (keyfile-string filename) -1))))
-
-(defun otp-to-clipboard (&optional filename)
-  "Copy the returned totp code to the clipboard."
-  (interactive)
-  (kill-new (get-totp filename)))
-\f
-;; Find password from pass(1) entry
-
-(defun get-password (&optional filename)
-  "Return a password given a file where it is stored.
-Assumes same structure as `pass(1)'."
-  (re/get-line-from-file (keyfile-string filename) 1))
-
-(defun password-to-clipboard (&optional filename)
-  "Copy the returned password to the clipboard."
-  (interactive)
-  (kill-new (get-password filename)))
-\f
-;; Password generation
-
-(defconst *alphanumerics*
-  '("a" "b" "c" "d" "e" "f" "g" "h" "i" "j" "k" "l" "m"
-    "n" "o" "p" "q" "r" "s" "t" "u" "v" "w" "x" "y" "z"
-    "A" "B" "C" "D" "E" "F" "G" "H" "I" "J" "K" "L" "M"
-    "N" "O" "P" "Q" "R" "S" "T" "U" "V" "W" "X" "Y" "Z"
-    "0" "1" "2" "3" "4" "5" "6" "7" "8" "9")
-  "List of strings of the upper/lower-case English alphabet, and the single-digit numbers.")
-
-(defconst *special-characters*
-  '("!" "?" "$" "%" "&" "'" "(" ")" "*" "+" "," "-" "."
-    "/" ":" ";" "<" "=" ">" "?" "@" "[" "]" "^" "_" "{"
-    "|" "}" "~")
-  "List of strings containing the special visible characters excluding \\ and \" .")
-
-(defun pw-get-char (&optional no-special-chars)
-  "Select a single character at random to be used in a password.
-If `no-special-chars' is t, use only alpha-numeric characters."
-  (let ((selected-charset (append *alphanumerics*
-                                 (when (null no-special-chars)
-                                   *special-characters*))))
-    (elt selected-charset (random (length selected-charset)))))
-
-(defun pw-get-chars (password-length &optional no-special-chars)
-  "Generate a list of characters as strings to be made into a password.
-If `no-special-chars' is t, use only alpha-numeric characters."
-  (append (list (pw-get-char no-special-chars))
-         (when (> password-length 1)
-           (pw-get-chars (- password-length 1) no-special-chars))))
-
-(defun generate-password (password-length &optional no-special-chars)
-  "Combine a list of randomly-selected characters into a single string of length given.
-calls `pw-get-chars'.  If `no-special-chars' is `t', use only alpha-numeric characters."
-  (apply #'concat (pw-get-chars password-length no-special-chars)))
-
-(defun insert-generated-password (&optional password-length)
-  "Insert a generated password into the current buffer.
-Negative password-length (or negative arg) sets `no-special-chars' for `generate-password'."
-  (interactive "p")
-  (let ((len (if (or (null password-length) (= 1 (abs password-length)))
-                16
-              (abs password-length)))
-       (no-special-p (and (numberp password-length) (< password-length 0))))
-    (insert (generate-password len no-special-p))))
-
-(provide 're-pass-alike)
-;;; re-pass-alike.el ends here
diff --git a/re/re-howm.el b/re/re-howm.el
new file mode 100644 (file)
index 0000000..aff9e5e
--- /dev/null
@@ -0,0 +1,71 @@
+;;; re-howm.el -*- lexical-binding: t; -*-
+;; This file is not part of GNU Emacs
+
+;;; Code:
+
+(setq howm-template-list '("= %title%cursor #inbox\n%date %file\n\n"
+                          "= %title%cursor #meeting\n%date %file\n\nAttendees: \n"
+                          "= @%title%cursor\n%date %file\n\n")
+      howm-template howm-template-list
+      howm-keyword-file "~/howm/.howm-keys"
+      howm-history-file "~/howm/.howm-history"
+      howm-menu-file "~/.emacs.d/0000-00-00-000000.txt"
+      howm-file-name-format "%Y%m%dT%H%M%S.txt"
+      howm-keyword-case-fold-search t
+      howm-remember-insertion-format "%s"
+      howm-menu-todo-num 10)
+
+(defun re/howm-menu-new-frame (&optional arg)
+  "Show the howm menu in a new frame"
+  (interactive "P")
+  (re/open-with-new-frame "HOWM" #'howm-menu))
+
+(defun re/howm-create-keyword ()
+  "Reads a keyword from the minibuffer and appends it to the keywords file."
+  (interactive)
+  (append-to-file (concat (read-string "New Keyword: ")
+                         "\n")
+                 nil
+                 howm-keyword-file))
+\f
+;; Menu tweaks
+
+;; add entries in howm-menu (press enter on the text)
+(dolist (aldr-additions '(("\\[Mtg\\]"
+                          (lambda (&optional dummy)
+                            (howm-create 2)))
+                         ("\\[Person\\]"
+                          (lambda (&optional dummy)
+                            (howm-create 3)))))
+  (add-to-list 'action-lock-default-rules
+              aldr-additions
+              t))
+
+(defun re/howm-menu-legend ()
+  (cl-labels ((p (text face) (propertize text 'font-lock-face face)))
+    (concat (format "Top %s" howm-menu-todo-num)
+           " "
+           (p "!Deadline" howm-reminder-deadline-face)
+           "/"
+           (p "+ToDo" howm-reminder-todo-face)
+           "/"
+           (p "@Schedule" howm-reminder-schedule-face)
+           "/"
+           (p "~Defer" howm-reminder-defer-face)
+           "/"
+           (p "-Reminder" howm-reminder-normal-face)
+           " Entries:")))
+
+(add-to-list 'howm-menu-allow 're/howm-menu-legend)
+
+;; add coloring for custom "waiting" state
+(add-to-list 'howm-reminder-font-lock-keywords
+            `(,(howm-reminder-regexp "[w]")
+              (0 howm-reminder-defer-face prepend))
+            t)
+
+(dolist (hooks '(after-save-hook howm-mode-hook))
+  (add-hook hooks 'howm-mode-set-buffer-name))
+
+(provide 're-howm)
+;;; re-howm.el ends here
diff --git a/re/re-mu4e.el b/re/re-mu4e.el
new file mode 100644 (file)
index 0000000..8c9c526
--- /dev/null
@@ -0,0 +1,41 @@
+;;; re-mu4e.el --- Setup mu4e --- -*- lexical-binding: t; -*-
+;; This file is not part of GNU Emacs
+
+;;; Code:
+
+(use-package mu4e
+  :ensure nil
+  :config
+  (setq mu4e-get-mail-command "mbsync -a"
+       mu4e-update-interval (* 10 60)
+       mu4e-change-filenames-when-moving t
+       mu4e-use-fancy-chars t
+       mu4e-attachment-dir "~/downloads"
+       mu4e-compose-reply-to-address "iv@earman.xyz"
+       mu4e-maildir "~/mail"
+       mu4e-drafts-folder "/iv/Drafts"
+       mu4e-sent-folder "/iv/Sent"
+       mu4e-trash-folder "/iv/Trash"
+       mu4e-maildir-shortcuts '((:maildir "/iv/inbox" :key ?i)
+                                (:maildir "/iv/Sent" :key ?s)
+                                (:maildir "/iv/Trash" :key ?t)
+                                (:maildir "/iv/Drafts" :key ?d))))
+
+(setq mail-user-agent 'message-user-agent
+      message-send-mail-function 'smtpmail-send-it
+      message-citation-line-format "Quoth %f :\n"
+      smtpmail-default-smtp-server "mail.earman.xyz"
+      smtpmail-smtp-server "mail.earman.xyz"
+      smtpmail-smtp-service 587
+      smtpmail-stream-type 'starttls
+      smtpmail-local-domain "earman.xyz"
+      smtpmail-queue-mail nil
+      smtpmail-queue-dir "~/mail/iv/outbox/cur")
+
+(setq user-mail-address "iv@earman.xyz"
+      user-full-name "Rush N. Earman IV"
+      message-signature "Rush Earman IV, PE"
+      message-kill-buffer-on-exit t)
+
+(provide 're-mu4e)
+;;; re-mu4e.el ends here
diff --git a/re/re-org.el b/re/re-org.el
new file mode 100644 (file)
index 0000000..a956c61
--- /dev/null
@@ -0,0 +1,175 @@
+;;; re-org.el --- org-mode bespokeniŋ -*- lexical-binding: t; -*-
+;; This file is not part of GNU Emacs
+
+;;; Code:
+
+;; General options
+(add-to-list 'org-export-backends 'md)
+
+(setq org-startup-indented t
+      org-startup-folded 'fold
+      org-startup-with-inline-images t
+      org-cycle-inline-images-display t
+      org-cycle-separator-lines 0
+      org-blank-before-new-entry '((heading) (plain-list-item . auto))
+      org-M-RET-may-split-line nil
+      org-treat-S-cursor-todo-selection-as-state-change nil
+      org-treat-insert-todo-heading-as-state-change nil
+      org-table-export-default-format "orgtbl-to-csv"
+      org-list-allow-alphabetical t
+      org-fold-catch-invisible-edits 'show-and-error
+      org-ellipsis " ↴"
+      org-tags-column 0
+      org-enforce-todo-dependencies t
+      org-enforce-todo-checkbox-dependencies t
+      org-fontify-done-headline nil
+      org-fontify-todo-headline nil
+      org-goto-interface 'outline-path-completion
+      org-outline-path-complete-in-steps nil
+      org-goto-auto-isearch nil
+      org-special-ctrl-a/e t
+      org-special-ctrl-k t
+      org-return-follows-link t
+      org-yank-adjusted-subtrees t
+      org-todo-keyword-faces '(("WAITING" :foreground "#e15400" :weight bold)
+                              ("UNDERTAKEN" :foreground "magenta" :weight bold)
+                              ("MEETING" :foreground "#315e9a" :weight bold)))
+
+(add-hook 'org-agenda-mode-hook #'hl-line-mode)
+
+\f
+;; Time Clocking
+(org-clock-persistence-insinuate)
+(setq org-clock-history-length 10
+      org-clock-in-resume t
+      org-clock-out-remove-zero-time-clocks t
+      org-clock-persist t
+      org-clock-persist-query-resume nil
+      org-clock-report-include-clocking-task t
+      org-time-stamp-rounding-minutes '(1 1))
+
+\f
+;; Agenda and capture
+(setq org-agenda-files (append '("~/org/")
+                        (file-expand-wildcards "~/projects/*/"))
+      org-refile-targets '((nil :maxlevel . 9)
+                          (org-agenda-files :maxlevel . 9))
+      org-refile-use-outline-path 'file
+      org-refile-allow-creating-parent-nodes 'confirm
+      org-todo-keywords '((sequence "TODO(t)" "WAITING(w@)" "|" "DONE(d)" "BELAYED(b@)" "GIVEN(g@)")
+                         (sequence "MEETING(m)" "|" "MET(M)"))
+      org-tag-alist '(("call" . ?c)
+                     ("email" . ?e)
+                     ("errand" . ?r)
+                     ("jobpc" . ?j)
+                     ("license" . ?l)
+                     ("open" . ?o))
+      org-tags-exclude-from-inheritance '("open")
+      org-agenda-restore-windows-after-quit t
+      org-agenda-start-on-weekday nil
+      org-agenda-compact-blocks t
+      org-agenda-span 'day
+      org-deadline-warning-days 30
+      org-agenda-window-setup 'current-window
+      org-agenda-time-grid '((daily today remove-match)
+                            (600 700 800 900 1000 1100 1200 1300 1400 1500 1600 1700 1800 1900)
+                            " ――――― "
+                            "")
+      org-agenda-tags-column 0
+      org-agenda-remove-tags t
+      org-agenda-skip-additional-timestamps-same-entry t
+      org-agenda-skip-deadline-if-done t
+      org-agenda-skip-scheduled-if-done t
+      org-agenda-prefix-format '((agenda . "%25c:%?-12t% s")
+                                (todo . "%25c:%?-12t% s")
+                                (tags . "%25c:%?-12t% s")
+                                (search . "%25c:%?-12t% s"))
+      org-agenda-scheduled-leaders '("BOOKED: " "Booked %2d d. ago: ")
+      org-agenda-deadline-leaders '("DEADLINE: " "In %3d d.: " "%2d d. ago: ")
+      org-read-date-prefer-future 'time
+      org-agenda-custom-commands
+      '(("d" "Done items" todo "DONE|BELAYED|GIVEN|MET" ((org-agenda-skip-function
+                                                         '(org-agenda-skip-entry-if 'notregexp "^\\*\\* "))
+                                                        (org-agenda-overriding-header "DONE - MAYBE KEEP:")))
+       ("f" "Maybe Someday" tags "someday" ((org-agenda-skip-function
+                                             '(org-agenda-skip-entry-if 'regexp "^\\* someday"))
+                                            (org-agenda-overriding-header "SOMEDAY:")))
+       ("i" "Inbox" tags "inbox" ((org-agenda-skip-function
+                                   '(org-agenda-skip-entry-if 'regexp "^\\* inbox"))
+                                  (org-agenda-overriding-header "INBOX:")))
+       ("l" "Licenses" tags "license" ((org-agenda-overriding-header "LICENSES:")))
+       ("n" "Next Actions" tags-todo "-recurring/TODO" ((org-agenda-overriding-header "NEXT:")
+                                                        (org-agenda-sorting-strategy
+                                                         '((agenda tag-up time-up)))))
+       ("p" "JobPCs" tags "jobpc" ((org-agenda-overriding-header "JOB PCS:")))
+       ("u" "Undertakings" tags "open" ((org-agenda-overriding-header "UNDERTAKINGS:")))
+       ("w" "Waiting" todo "WAITING" ((org-agenda-overriding-header "WAITING:")))
+       ("o" "Overview" ((agenda "")
+                        (tags "inbox" ((org-agenda-overriding-header "\nINBOX:")))
+                        (tags "open" ((org-agenda-skip-function
+                                       '(org-agenda-skip-entry-if 'notregexp "^\\* "))
+                                      (org-agenda-overriding-header "\nUNDERTAKINGS:")))
+                        (todo "WAITING" ((org-agenda-overriding-header "\nWAITING:"))))))
+      org-agenda-start-with-log-mode t
+      org-agenda-log-mode-items '(closed clock state)
+      org-log-done 'time
+      org-log-into-drawer t
+      org-capture-templates '(("i" "Inbox" entry
+                              (file "inbox.org")
+                              "* %^{Description}\n%U\n%?"
+                              :clock-in t
+                              :clock-resume t)
+                             ("m" "Meeting" entry
+                              (file "inbox.org")
+                              "* %^{Description}\n%^{Scheduled:}T\n%?"
+                              :clock-in t
+                              :clock-resume t)
+                             ("p" "Phone Call" entry
+                              (file "inbox.org")
+                              "* %^{Description} :call:\n%U\n%?"
+                              :clock-in t
+                              :clock-resume t))
+      org-id-link-to-org-use-id 'create-if-interactive-and-no-custom-id
+      org-id-method 'ts
+      org-clone-delete-id t
+      org-attach-id-to-path-function-list '(org-attach-id-ts-folder-format
+                                           org-attach-id-uuid-folder-format))
+
+(defun re/org-auto-generate-ids-in-file ()
+  "Add ID properties to all headlines in the current
+ file which do not already have one."
+  (interactive)
+  (org-map-entries 'org-id-get-create))
+
+(defun re/org-save-all ()
+  "Save all `org-agenda-files' without user confirmation."
+  (interactive)
+  (message "Saving all org-agenda-files buffers...")
+  (save-some-buffers t
+                    (lambda ()
+                      (when (member (buffer-file-name) org-agenda-files) t)))
+  (message "Saving all org-agenda-files buffers... done"))
+
+(advice-add 'org-refile :after (lambda (&rest _) (re/org-save-all)))
+\f
+;; Archiving (use re/org-archive-all periodically)
+(defun re/org-archive-all ()
+  "Archive all tasks marked `DONE' in agenda files"
+  (interactive)
+  (message "Archiving all completed tasks in org-agenda-files...")
+  (org-map-entries (lambda ()
+                    (org-archive-subtree)
+                    (setq org-map-continue-from (org-element-property
+                                                 :begin
+                                                 (org-element-at-point))))
+                  "/DONE"
+                  'agenda)
+  (message "Archiving all completed tasks in org-agenda-files... done"))
+
+(setq org-archive-location (concat "~/org/old.org_keep::datetree/")
+      org-agenda-text-search-extra-files '(agenda-archives))
+
+(add-to-list 'auto-mode-alist '("\\.org_keep\\'" . org-mode))
+
+(provide 're-org)
+;;; re-org.el ends here
diff --git a/re/re-packages.el b/re/re-packages.el
new file mode 100644 (file)
index 0000000..dc202d5
--- /dev/null
@@ -0,0 +1,156 @@
+;;; re-packages.el --- Load Packs -*-  lexical-binding: t; -*-
+;; This file is not part of Emacs.
+
+;;; Code:
+
+(require 'package)
+
+(add-to-list 'package-archives '("melpa" . "https://melpa.org/packages/") t)
+
+(setq use-package-always-ensure t
+      use-package-always-defer t)
+\f
+;; UI/Editing
+
+(use-package corfu
+  :demand
+  t
+  :custom
+  (corfu-auto t)
+  (corfu-auto-delay 0)
+  (corfu-auto-prefix 1)
+  :config
+  (global-corfu-mode))
+
+(use-package corfu-popupinfo
+  :ensure
+  nil ; part of corfu
+  :after
+  corfu
+  :hook
+  (corfu-mode . corfu-popupinfo-mode)
+  :custom
+  (corfu-popupinfo-delay '(1.0 . 0.01)) ; start with M-t, fast refresh once on
+  (corfu-popupinfo-hide nil)
+  :config
+  (corfu-popupinfo-mode))
+
+(use-package expand-region
+  :bind
+  (("C-=" . er/expand-region)))
+
+(use-package aggressive-indent :defer t)
+
+(use-package magit
+  :config
+  (message "Magit Loaded"))
+
+(use-package page-break-lines
+  :demand
+  t
+  :config
+  (global-page-break-lines-mode))
+\f
+;; Filetypes
+(use-package auctex
+  :config
+  (setq TeX-auto-save t
+       TeX-parse-self t
+       TeX-PDF-mode t)
+  (setq-default TeX-master nil))
+
+(use-package csv-mode
+  :config
+  (add-hook 'csv-mode-hook 'csv-align-mode))
+
+(use-package markdown-mode
+  :config
+  (setq markdown-special-ctrl-a/e t)
+  :bind
+  (:map markdown-mode-map
+       ("M-<right>" . markdown-demote)
+       ("M-<left>" . markdown-promote)
+       ("M-<up>" . markdown-move-up)
+       ("M-<down>" . markdown-move-down)
+       ("C-M-u" . markdown-up-heading)
+       ("C-M-b" . markdown-outline-previous-same-level)
+       ("C-M-f" . markdown-outline-next-same-level)
+       ("C-M-p" . markdown-outline-previous)
+       ("C-M-n" . markdown-outline-next)))
+
+(use-package edit-indirect :after 'markdown-mode)
+\f
+;; REPLs
+(use-package sly
+  :config
+  (setq inferior-lisp-program "sbcl"
+       sly-net-coding-system 'utf-8-unix
+       sly-command-switch-to-existing-lisp 'always)
+  (let ((core (expand-file-name "~/sbcl.core-for-sly")))
+    (when (file-exists-p core)
+      (setq sly-lisp-implementations (list `(sbcl ("sbcl" "--core" ,core)))))))
+
+(use-package geiser
+  :config
+  (if (equal system-type 'windows-nt)
+      (setq geiser-chicken-binary '("C:/tools/chicken/bin/csi.exe" "-:c"))
+    (setq geiser-chicken-binary "csi -:c"))
+  (setq scheme-program-name geiser-chicken-binary
+       geiser-active-implementations '(chicken))
+  (add-hook 'scheme-mode-hook 'geiser-mode))
+
+(use-package geiser-chicken :after 'geiser)
+
+(use-package forth-mode)
+\f
+;; PIM
+(use-package org
+  :config
+  (require 're-org)
+  :bind
+  (("C-c l" . org-store-link)
+   ("C-c a" . org-agenda)
+   ("C-c c" . org-capture)
+   ("C-c b" . org-switchb)
+   ("<f10>" . org-clock-out)
+   ("<f2>" . org-clock-goto)
+   :map org-mode-map
+   ("M-<right>" . org-shiftmetaright)
+   ("M-<left>" . org-shiftmetaleft)
+   ("M-S-<right>" . org-metaright)
+   ("M-S-<left>" . org-metaleft)
+   ("C-M-h" . org-mark-subtree)
+   ("C-M-u" . org-up-element)
+   ("C-M-d" . org-down-element)
+   ("C-M-b" . org-backward-heading-same-level)
+   ("C-M-f" . org-forward-heading-same-level)
+   ("C-M-p" . org-previous-visible-heading)
+   ("C-M-n" . org-next-visible-heading)
+   ("<f9>" . org-clock-in)))
+
+(use-package org-transclusion
+  :after
+  org
+  :bind
+  (("C-c t" . org-transclusion-mode)))
+
+(use-package howm
+  :config
+  (require 're-howm)
+  :bind
+  (("<f6>" . howm-menu)
+   ("S-<f6>" . re/howm-menu-new-frame)
+   :map howm-mode-map
+   ("C-c , k" . re/howm-create-keyword)
+   ("C-c , =" . howm-narrow-to-memo)))
+\f
+;; MISC
+(use-package trashed
+  :config
+  (setq trashed-action-confirmer 'y-or-n-p
+       trashed-use-header-line t
+       trashed-sort-key '("Date deleted" . t)
+       trashed-date-format "%Y-%m-%d %H:%M:%S"))
+
+(provide 're-packages)
+;;; re-packages.el ends here
diff --git a/re/re-pass-alike.el b/re/re-pass-alike.el
new file mode 100644 (file)
index 0000000..35d3fb7
--- /dev/null
@@ -0,0 +1,149 @@
+;;; re-pass-alike.el -*- lexical-binding: t; -*-
+;; This file is not part of GNU Emacs.
+
+;;; Code:
+
+;; Generate totp code
+(dolist (requirement '(bindat gnutls hexl auth-source))
+  (require requirement))
+
+(defun totp--hex-decode-string (string)
+  "Hex-decode STRING and return the result as a unibyte string."
+  (apply #'unibyte-string
+        (seq-map (lambda (s) (hexl-htoi (aref s 0) (aref s 1)))
+                 (seq-partition string 2))))
+
+(defun totp (string &optional time digits)
+  "Return a TOTP token using the secret hex STRING and current time.
+TIME is used as counter value instead of current time, if non-nil.
+DIGITS is the number of pin digits and defaults to 6."
+  (let* ((key-bytes (totp--hex-decode-string (upcase string)))
+        (counter (truncate (/ (or time (time-to-seconds)) 30)))
+        (digits (or digits 6))
+        (format-string (format "%%0%dd" digits))
+        ;; we have to manually split the 64 bit number (u64 not supported in Emacs 27.2)
+        (counter-bytes (bindat-pack  '((:high u32) (:low u32))
+                                     `((:high . ,(ash counter -32)) (:low . ,(logand counter #xffffffff)))))
+        (mac (gnutls-hash-mac 'SHA1 key-bytes counter-bytes))
+        (offset (logand (bindat-get-field (bindat-unpack '((:offset u8)) mac 19) :offset) #xf)))
+    (format format-string
+           (mod
+            (logand (bindat-get-field (bindat-unpack '((:totp-pin u32)) mac  offset) :totp-pin)
+                    #x7fffffff)
+            (expt 10 digits)))))
+
+(defconst base32-alphabet
+  (let ((tbl (make-char-table nil)))
+    (dolist (mapping '(("A" . 0) ("B" . 1) ("C" . 2) ("D" . 3)
+                      ("E" . 4) ("F" . 5) ("G" . 6)
+                      ("H" . 7) ("I" . 8) ("J" . 9) ("K" . 10)
+                      ("L" . 11) ("M" . 12) ("N" . 13)
+                      ("O" . 14) ("P" . 15) ("Q" . 16) ("R" . 17)
+                      ("S" . 18) ("T" . 19) ("U" . 20)
+                      ("V" . 21) ("W" . 22) ("X" . 23) ("Y" . 24)
+                      ("Z" . 25) ("2" . 26) ("3" . 27)
+                      ("4" . 28) ("5" . 29) ("6" . 30) ("7" . 31)))
+      (aset tbl (string-to-char (car mapping)) (cdr mapping)))
+    tbl)
+  "Base-32 mapping table, as defined in RFC 4648.")
+
+(defun base32-hex-decode (string)
+  "The cheats' version of base-32 decode.
+
+This is not a 100% faithful implementation of RFC 4648. The
+concept of encoding partial quanta is not implemented fully.
+
+No attempt is made to pad the output either as that is not
+required for HMAC-TOTP."
+  (unless (mod (length string) 8)
+    (error "Padding is incorrect"))
+  (setq string (upcase string))
+  (let ((trimmed-array (append (string-trim-right string "=+") nil)))
+    (format "%X" (seq-reduce
+                 (lambda (acc char) (+ (ash acc 5) (aref base32-alphabet char)))
+                 trimmed-array 0))))
+
+(defun keyfile-string (filename)
+  "Return a string which is the filepath to a `pass(1)' file."
+  (let ((directory "~/.password-store/"))
+    (if (null filename)
+       (read-file-name "Select a password: " directory nil t nil)
+      (concat directory
+             (if (stringp filename)
+                 filename
+               (symbol-name filename))
+             ".gpg"))))
+
+(defun get-totp (&optional filename)
+  "Generate a totp code given a file with the secret hex string.
+If no filename given, prompt for one.
+Assumes the file has the string by itself on the last line of the file,
+similar to what pass-otp does, but without the full uri.
+Also assumes the file is in `~/.password-store' and has the `.gpg' extension."
+  (totp (base32-hex-decode (re/get-line-from-file (keyfile-string filename) -1))))
+
+(defun otp-to-clipboard (&optional filename)
+  "Copy the returned totp code to the clipboard."
+  (interactive)
+  (kill-new (get-totp filename)))
+\f
+;; Find password from pass(1) entry
+
+(defun get-password (&optional filename)
+  "Return a password given a file where it is stored.
+Assumes same structure as `pass(1)'."
+  (re/get-line-from-file (keyfile-string filename) 1))
+
+(defun password-to-clipboard (&optional filename)
+  "Copy the returned password to the clipboard."
+  (interactive)
+  (kill-new (get-password filename)))
+\f
+;; Password generation
+
+(defconst *alphanumerics*
+  '("a" "b" "c" "d" "e" "f" "g" "h" "i" "j" "k" "l" "m"
+    "n" "o" "p" "q" "r" "s" "t" "u" "v" "w" "x" "y" "z"
+    "A" "B" "C" "D" "E" "F" "G" "H" "I" "J" "K" "L" "M"
+    "N" "O" "P" "Q" "R" "S" "T" "U" "V" "W" "X" "Y" "Z"
+    "0" "1" "2" "3" "4" "5" "6" "7" "8" "9")
+  "List of strings of the upper/lower-case English alphabet, and the single-digit numbers.")
+
+(defconst *special-characters*
+  '("!" "?" "$" "%" "&" "'" "(" ")" "*" "+" "," "-" "."
+    "/" ":" ";" "<" "=" ">" "?" "@" "[" "]" "^" "_" "{"
+    "|" "}" "~")
+  "List of strings containing the special visible characters excluding \\ and \" .")
+
+(defun pw-get-char (&optional no-special-chars)
+  "Select a single character at random to be used in a password.
+If `no-special-chars' is t, use only alpha-numeric characters."
+  (let ((selected-charset (append *alphanumerics*
+                                 (when (null no-special-chars)
+                                   *special-characters*))))
+    (elt selected-charset (random (length selected-charset)))))
+
+(defun pw-get-chars (password-length &optional no-special-chars)
+  "Generate a list of characters as strings to be made into a password.
+If `no-special-chars' is t, use only alpha-numeric characters."
+  (append (list (pw-get-char no-special-chars))
+         (when (> password-length 1)
+           (pw-get-chars (- password-length 1) no-special-chars))))
+
+(defun generate-password (password-length &optional no-special-chars)
+  "Combine a list of randomly-selected characters into a single string of length given.
+calls `pw-get-chars'.  If `no-special-chars' is `t', use only alpha-numeric characters."
+  (apply #'concat (pw-get-chars password-length no-special-chars)))
+
+(defun insert-generated-password (&optional password-length)
+  "Insert a generated password into the current buffer.
+Negative password-length (or negative arg) sets `no-special-chars' for `generate-password'."
+  (interactive "p")
+  (let ((len (if (or (null password-length) (= 1 (abs password-length)))
+                16
+              (abs password-length)))
+       (no-special-p (and (numberp password-length) (< password-length 0))))
+    (insert (generate-password len no-special-p))))
+
+(provide 're-pass-alike)
+;;; re-pass-alike.el ends here