diff --git a/init.el b/init.el index 7c40722..8503809 100644 --- a/init.el +++ b/init.el @@ -192,6 +192,148 @@ In short, DO NOT USE THIS FUNCTION!!!" (setup calendar (:option calendar-week-start-day 1)) +(setup (:straight circe) + (require 'circe) + (require 'acdw-irc) + + (:option acdw-irc/left-margin 12 + acdw-irc/post-my-nick "-> " + circe-channel-killed-confirmation nil + circe-color-nicks-everywhere t + circe-default-nick "acdw" + circe-default-part-message "See You, Space Cowpokes . . ." + circe-default-user "acdw" + circe-format-action + (lambda (&rest plist) + (concat + (acdw-irc/margin-format "" "*" "*" t) + " " (plist-get plist :nick) " " (plist-get plist :body))) + circe-format-say + (lambda (&rest plist) + (concat + (acdw-irc/margin-format (plist-get plist :nick) "" " |" t) + " " (plist-get plist :body))) + circe-format-self-action + (lambda (&rest plist) + (concat + (acdw-irc/margin-format "" "-*" " *" t) + " " (plist-get plist :nick) " " (plist-get plist :body))) + circe-format-self-say + (lambda (&rest plist) + (concat + (acdw-irc/margin-format (plist-get plist :nick) "-" " >" t) + " " (plist-get plist :body))) + ;; circe-highlight-nick-type 'message + circe-network-options + `(("Libera Chat" + :channels ("#emacs" "#systemcrafters" "##webpals") + :sasl-username ,circe-default-nick + :sasl-password ,(acdw/make-password-fetcher + :host "libera.chat")) + ("Tilde Chat" :host "irc.tilde.chat" :port 6697 :use-tls t + :channels ("#meta" "#bread" "#dadjokes" "#team" + "#emacs") + :sasl-username ,circe-default-nick + :sasl-password ,(acdw/make-password-fetcher + :host "tilde.chat")) + ("Casa" :host "m455.casa" :port 6697 :use-tls t + :channels ("#basement") + :sasl-username ,circe-default-nick + :sasl-password ,(acdw/make-password-fetcher + :host "m455.casa")) + ("Pissnet" :host "piss.hmm.st" :port 6697 :use-tls t + :channels ("#i-just-peed") + :sasl-username ,circe-default-nick + :sasl-password ,(acdw/make-password-fetcher + :host "piss.hmm.st")) + ;; TODO: irc.chat.twitch.tv + ) + circe-reduce-lurker-spam t + circe-server-auto-join-default-type :after-auth + circe-server-buffer-action (lambda (buf) + (message "Connected to %s" buf))) + + ;; (:face circe-nick-highlight-face + ;; ((t (:inherit (modus-themes-hl-line))))) + + (:bind "C-c C-p" #'circe-command-PART + "C-l" #'lui-track-jump-to-indicator) + + (:advise circe-command-PART :after + (defun circe-part@kill-buffer (&rest _) + (let ((circe-channel-killed-confirmation nil)) + (kill-buffer))) + + circe-command-QUIT :after + (defun circe-quit@kill-buffer (&rest _) + ;; `circe-server-killed-confirmation' set to nil, and manually + ;; deleting all chat buffers, pending Github issue #402 + ;; (https://github.com/emacs-circe/circe/issues/402) + (let ((circe-server-killed-confirmation nil)) + (with-circe-server-buffer + (dolist (buf (circe-server-chat-buffers)) + (let ((circe-channel-killed-confirmation nil)) + (kill-buffer buf))) + (kill-buffer)))) + + circe-command-GQUIT :after + (defun circe-gquit@kill-buffer (&rest _) + ;; `circe-server-killed-confirmation' set to nil, and manually + ;; deleting all chat buffers, pending Github issue #402 + ;; (https://github.com/emacs-circe/circe/issues/402) + (let ((circe-server-killed-confirmation nil)) + (dolist (buf (circe-server-buffers)) + (with-current-buffer buf + (dolist (buf (circe-server-chat-buffers)) + (let ((circe-channel-killed-confirmation nil)) + (kill-buffer buf))) + (message "%s: %s" buf circe-server-killed-confirmation) + (kill-buffer)))))) + + (defun circe-command-SHORTEN (url) + "Shorten URL using `0x0-shorten-uri'." + (interactive "sURL to shorten: ") + ;; TODO: enable /shorten URL comment syntax + (let ((short-url (0x0-shorten-uri (0x0--choose-server) url))) + (circe-command-SAY short-url))) + + (:with-mode circe-chat-mode + (:hook #'acdw/stop-paren-annoyances + #'enable-circe-color-nicks + #'enable-circe-display-images + #'enable-circe-new-day-notifier + (defun circe-chat@set-prompt () + (lui-set-prompt + (concat + (propertize + (acdw-irc/margin-format (buffer-name) "" ">") + 'face 'circe-prompt-face + 'read-only t + 'intangible t + 'cursor-intangible t) + " "))))) + + (autoload 'circe-nick-color-reset "circe-color-nicks") + (add-hook 'modus-themes-after-load-theme-hook + #'circe-nick-color-reset) + + (:with-mode lui-mode + (:option lui-fill-column fill-column + lui-fill-type (repeat-string acdw-irc/left-margin " ") + lui-time-stamp-position 'right-margin + lui-time-stamp-format "%H:%M" + lui-track-behavior 'before-switch-to-buffer + lui-track-indicator 'fringe) + + (:local-set fringes-outside-margins t + right-margin-width 5 + scroll-margin 0 + word-wrap t + wrap-prefix (repeat-string acdw-irc/left-margin " ") + line-number-mode nil) + + (:hook #'enable-lui-track))) + (setup completion (:option completion-ignore-case t read-buffer-completion-ignore-case t @@ -209,13 +351,18 @@ In short, DO NOT USE THIS FUNCTION!!!" (blink-cursor-mode +1)) (setup cus-edit - (:option custom-file null-device ; don't store customizations + (:option custom-file (acdw/dir "custom.el") custom-magic-show nil custom-magic-show-button t custom-raised-buttons nil custom-unlispify-tag-names nil custom-variable-default-form 'lisp) + ;; I need this to save `safe-local-variables' between Emacs invocations. For + ;; now, of course .... I would /love/ a better solution. + (when (file-exists-p custom-file) + (load custom-file nil nil)) + ;; `Custom-mode-hook' fires /before/ the widgets are built, so I have to ;; install advice after the widgets are made. (:advise custom-buffer-create :after @@ -341,6 +488,28 @@ In short, DO NOT USE THIS FUNCTION!!!" ;; https://oremacs.com/2015/01/17/setting-up-ediff/ (add-hook 'ediff-after-quit-hook-internal #'winner-undo)) +(setup (:straight edit-indirect)) + +;; requires extension: +;; https://addons.mozilla.org/en-US/firefox/addon/edit-with-emacs1/ +(setup (:straight edit-server) + (:require edit-server) + (edit-server-start) + + (:option edit-server-default-major-mode 'text-mode + edit-server-url-major-mode-alist + (list (cons (rx (| "reddit.com" + "tildes.net")) + 'markdown-mode) + (cons (rx "github.com") + 'gfm-mode))) + + (:advise edit-server-make-frame :before + (defun edit-server@set-a-variable (&rest _) + (setq-local edit-server-frame-p t)))) + +(setup (:straight el-patch)) + (setup eldoc (:option eldoc-idle-delay 0.1 eldoc-echo-area-use-multiline-p nil)) @@ -1486,7 +1655,7 @@ specific to most general, they are these: (:with-feature flyspell (:bind "C-." #'flyspell-correct-wrapper "" #'acdw/flyspell-correct-f7) - (:unbind "C-," "C-." "C-M-i"))) + (:unbind "C-;" "C-," "C-." "C-M-i"))) (setup (:straight-if forge (acdw/system :home)) @@ -1634,9 +1803,26 @@ specific to most general, they are these: w3m-link w3m-message-link)) (link-hint-define-type type - :open-secondary browse-url-secondary-browser-function)) + :open-secondary browse-url-secondary-browser-function + :open-secondary-multiple t)) - (:option link-hint-avy-style 'at) + (defun acdw/link-hint-open-all-links (prefix) + "Open all visible links. +When PREFIX is non-nil, open links with +`browse-url-secondary-browser-function'." + (interactive "P") + (avy-with link-hint-open-all-links + (link-hint--all (if prefix :open-secondary :open)))) + + (defun acdw/link-hint-open-multiple-links (prefix) + "Use `avy' to open multiple visible links at once. +When PREFIX is non-nil, open links with +`browse-url-secondary-browser-function'." + (interactive "P") + (avy-with link-hint-open-multiple-links + (link-hint--multiple (if prefix :open-secondary :open)))) + + (:option link-hint-avy-style 'post) (:global "C-;" (defun acdw/link-hint-open-link (arg) "Open a link using `link-hint-open-link', prefix-aware. @@ -1933,6 +2119,39 @@ browser defined in `browse-url-secondary-browser-function'." (setup (:straight powerthesaurus) (:global "C-c l t" #'powerthesaurus-lookup-word-dwim)) +;; (setup (:straight prism) +;; (dolist (mode lispy-modes) +;; (add-hook (intern (format "%s-hook" mode)) #'prism-mode))) + +(setup prog + (:option show-paren-delay 0 + show-paren-style 'mixed + show-paren-when-point-inside-paren t + show-paren-when-point-in-periphery t + smie-indent-basic tab-width) + + (:hook show-paren-mode + electric-pair-local-mode + acdw/setup-fringes + + (defun prog-mode@auto-fill () + (setq-local comment-auto-fill-only-comments t) + (turn-on-auto-fill))) + + (mapc (lambda (buf) + (with-current-buffer buf + (when (funcall persistent-scratch-scratch-buffer-p-function) + (persistent-scratch-mode +1)))) + + (buffer-list))) + +(setup (:straight-if pkgbuild-mode + (executable-find "makepkg")) + (:file-match "PKGBUILD")) + +(setup (:straight powerthesaurus) + (:global "C-c l t" #'powerthesaurus-lookup-word-dwim)) + (setup (:straight prism) (dolist (mode lispy-modes) (add-hook (intern (format "%s-hook" mode)) #'prism-mode))) diff --git a/lisp/acdw-irc.el b/lisp/acdw-irc.el index b4b75ec..305dc93 100644 --- a/lisp/acdw-irc.el +++ b/lisp/acdw-irc.el @@ -73,6 +73,41 @@ and right on t." (dolist (network (mapcar #'car circe-network-options)) (circe-maybe-connect network))) +(el-patch-feature circe) +(with-eval-after-load 'circe + (defvar circe-server-buffer-action 'pop-to-buffer-same-window + "What to do with `circe-server' buffers when created.") + + (el-patch-defun circe (network-or-server &rest server-options) + "Connect to IRC. + +Connect to the given network specified by NETWORK-OR-SERVER. + +When this function is called, it collects options from the +SERVER-OPTIONS argument, the user variable +`circe-network-options', and the defaults found in +`circe-network-defaults', in this order. + +If NETWORK-OR-SERVER is not found in any of these variables, the +argument is assumed to be the host name for the server, and all +relevant settings must be passed via SERVER-OPTIONS. + +All SERVER-OPTIONS are treated as variables by getting the string +\"circe-\" prepended to their name. This variable is then set +locally in the server buffer. + +See `circe-network-options' for a list of common options." + (interactive (circe--read-network-and-options)) + (let* ((options (circe--server-get-network-options network-or-server + server-options)) + (buffer (circe--server-generate-buffer options))) + (with-current-buffer buffer + (circe-server-mode) + (circe--server-set-variables options) + (circe-reconnect)) + (el-patch-swap (pop-to-buffer-same-window buffer) + (funcall circe-server-buffer-action buffer))))) + (defun circe-network-connected-p (network) "Return non-nil if there's any Circe server-buffer whose `circe-server-netwok' is NETWORK." diff --git a/lisp/acdw.el b/lisp/acdw.el index d3b0bf9..dcf7b19 100644 --- a/lisp/acdw.el +++ b/lisp/acdw.el @@ -402,6 +402,30 @@ first." (setq deactivate-mark t) nil) +(defun acdw/org-export-copy () + "copy a tree" + (interactive) + (require 'ox-ascii) + (let ((extracted-heading (acdw/org-extract-heading-text))) + ;; Export to ASCII - not async, subtree only, visible-only, body-only + (let ((org-export-show-temporary-export-buffer nil)) + (org-ascii-export-as-ascii nil t t t)) + (with-current-buffer "*Org ASCII Export*" + (goto-char (point-min)) + (insert extracted-heading) + (newline) + (newline) + + (unfill-region (point-min) (point-max)) + (flush-lines "^$" (point-min) (point-max)) + + (copy-region-as-kill (point-min) (point-max))) + + (when (called-interactively-p 'interactive) + (indicate-copied-region)) + (setq deactivate-mark t) + nil)) + (defun acdw/org-extract-heading-text () "Extract the heading text from an `org-mode' heading." (let ((heading (org-no-properties (org-get-heading t t t t))))