summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--config.org1325
1 files changed, 553 insertions, 772 deletions
diff --git a/config.org b/config.org index c622e62..4596ef6 100644 --- a/config.org +++ b/config.org
@@ -448,9 +448,7 @@ Since this /comes/ with smart mode line, I’m just going to use it, instead of
448 :height 100))) 448 :height 100)))
449 449
450 (set-face-from-alternatives 'fixed-pitch 450 (set-face-from-alternatives 'fixed-pitch
451 '(("Libertinus Mono" 451 '(("Linux Libertine Mono O"
452 :height 110)
453 ("Linux Libertine Mono O"
454 :height 110) 452 :height 110)
455 ("Go Mono" 453 ("Go Mono"
456 :height 100) 454 :height 100)
@@ -459,7 +457,7 @@ Since this /comes/ with smart mode line, I’m just going to use it, instead of
459 457
460 (set-face-from-alternatives 'variable-pitch 458 (set-face-from-alternatives 'variable-pitch
461 '(("Libertinus Serif" 459 '(("Libertinus Serif"
462 :height 120) 460 :height 110)
463 ("Linux Libertine O" 461 ("Linux Libertine O"
464 :height 120) 462 :height 120)
465 ("Georgia" 463 ("Georgia"
@@ -468,948 +466,731 @@ Since this /comes/ with smart mode line, I’m just going to use it, instead of
468 (remove-function after-focus-change-function #'acdw/setup-fonts))) 466 (remove-function after-focus-change-function #'acdw/setup-fonts)))
469 467
470 (add-function :before after-focus-change-function #'acdw/setup-fonts) 468 (add-function :before after-focus-change-function #'acdw/setup-fonts)
471#+end_src 469#+END_SRC
472 470
473**** Variable-pitch in text modes 471**** Custom faces
474 472
475#+begin_src emacs-lisp 473#+begin_src emacs-lisp
476 (add-hook 'text-mode-hook #'variable-pitch-mode) 474(custom-set-faces `(font-lock-comment-face
475 ((t (:inherit (custom-comment italic variable-pitch))))))
477#+end_src 476#+end_src
478 477
479**** Line spacing 478**** Line spacing
480 479
481#+begin_src emacs-lisp 480#+BEGIN_SRC emacs-lisp
482 (cuss line-spacing 0.1) 481(cuss line-spacing 0.1
483#+end_src 482 "Add 10% extra space below each line.")
483#+END_SRC
484 484
485**** Unicode fonts 485**** Unicode Fonts
486 486
487#+begin_src emacs-lisp 487 #+BEGIN_SRC emacs-lisp
488 (straight-use-package 'unicode-fonts) 488 (straight-use-package 'unicode-fonts)
489 (with-eval-after-load 'unicode-fonts 489 (require 'unicode-fonts)
490 (unicode-fonts-setup)) 490 (unicode-fonts-setup)
491#+end_src 491 #+END_SRC
492
493* Interactivity
494
495** Async
496 492
497#+begin_src emacs-lisp 493** Interactivity
498 (straight-use-package 'async)
499 (autoload 'dired-async-mode "dired-async.el" nil t)
500 (dired-async-mode +1)
501 494
502 (async-bytecomp-package-mode +1) 495*** Completing read
503#+end_src
504 496
505** Completing-read 497**** Shadow file names in =completing-read=.
506 498
507*** Shadow file names 499 #+BEGIN_SRC emacs-lisp
508 500 (cuss file-name-shadow-properties '(invisible t))
509#+begin_src emacs-lisp
510 (cuss file-name-shadow-properties '(invisible t))
511 501
512 (file-name-shadow-mode +1) 502 (file-name-shadow-mode +1)
513#+end_src 503 #+END_SRC
514 504
515*** Selectrum 505**** Ignore case in =completing-read=
516 506
517 #+begin_src emacs-lisp 507 #+BEGIN_SRC emacs-lisp
518 (straight-use-package 'selectrum) 508 (cuss completion-ignore-case t)
519 (require 'selectrum) 509 (cuss read-buffer-completion-ignore-case t)
520 (selectrum-mode +1) 510 (cuss read-file-name-completion-ignore-case t)
521 #+end_src 511 #+END_SRC
522 512
523*** Prescient 513**** Selectrum
524 514
525 #+begin_src emacs-lisp 515 #+BEGIN_SRC emacs-lisp
526 (straight-use-package 'prescient) 516 (straight-use-package 'selectrum)
527 (require 'prescient) 517 (require 'selectrum)
518 (selectrum-mode +1)
519 #+END_SRC
528 520
529 (prescient-persist-mode +1) 521**** Prescient
530 522
531 (straight-use-package 'selectrum-prescient) 523 #+BEGIN_SRC emacs-lisp
524 (straight-use-package 'prescient)
525 (require 'prescient)
526 (prescient-persist-mode +1)
532 527
533 (with-eval-after-load 'prescient 528 (straight-use-package 'selectrum-prescient)
534 (with-eval-after-load 'selectrum 529 (require 'selectrum-prescient)
535 (selectrum-prescient-mode +1))) 530 (selectrum-prescient-mode +1)
536 #+end_src 531 #+END_SRC
537 532
538*** Consult 533**** Consult
539 534
540 #+begin_src emacs-lisp 535 #+BEGIN_SRC emacs-lisp
541 (straight-use-package '(consult 536 (straight-use-package '(consult
542 :host github 537 :host github
543 :repo "minad/consult")) 538 :repo "minad/consult"))
544 (require 'consult) 539 (require 'consult)
545 540
541 (straight-use-package '(consult-selectrum
542 :host github
543 :repo "minad/consult"))
544 (require 'consult-selectrum)
545
546 (define-key ctl-x-map "b" #'consult-buffer) 546 (define-key ctl-x-map "b" #'consult-buffer)
547 (define-key ctl-x-map (kbd "C-r") #'consult-buffer)
547 (define-key ctl-x-map "4b" #'consult-buffer-other-window) 548 (define-key ctl-x-map "4b" #'consult-buffer-other-window)
548 (define-key ctl-x-map "5b" #'consult-buffer-other-frame) 549 (define-key ctl-x-map "5b" #'consult-buffer-other-frame)
550
549 (define-key goto-map "o" #'consult-outline) 551 (define-key goto-map "o" #'consult-outline)
552 (define-key goto-map "g" #'consult-line)
553 (define-key goto-map (kbd "M-g") #'consult-line)
550 (define-key goto-map "l" #'consult-line) 554 (define-key goto-map "l" #'consult-line)
555 (define-key goto-map "m" #'consult-mark)
556 (define-key goto-map "k" #'consult-global-mark)
557 (define-key goto-map "i" #'consult-imenu)
558 (define-key goto-map "e" #'consult-error)
559
551 (global-set-key (kbd "M-y") #'consult-yank-pop) 560 (global-set-key (kbd "M-y") #'consult-yank-pop)
561
552 (define-key help-map "a" #'consult-apropos) 562 (define-key help-map "a" #'consult-apropos)
553 563
554 (fset 'multi-occur #'consult-multi-occur) 564 (fset 'multi-occur #'consult-multi-occur)
565 #+END_SRC
555 566
556 (straight-use-package '(consult-selectrum 567**** Marginalia
557 :host github
558 :repo "minad/consult"))
559 #+end_src
560
561*** Marginalia
562
563 #+begin_src emacs-lisp
564 (straight-use-package '(marginalia
565 :host github
566 :repo "minad/marginalia"
567 :branch "main"))
568
569 (cuss marginalia-annotators
570 (if (eq system-type 'windows-nt)
571 '(marginalia-annotators-light
572 marginalia-annotators-heavy)
573 '(marginalia-annotators-heavy
574 marginalia-annotators-light)))
575
576 (marginalia-mode +1)
577 #+end_src
578 568
579** Ignore case 569 #+BEGIN_SRC emacs-lisp
580 570 (straight-use-package '(marginalia
581#+begin_src emacs-lisp 571 :host github
582 (cuss completion-ignore-case t) 572 :repo "minad/marginalia"
583 (cuss read-buffer-completion-ignore-case t) 573 :branch "main"))
584 (cuss read-file-name-completion-ignore-case t)
585#+end_src
586 574
587** Search 575 (cuss marginalia-annotators
576 '(marginalia-annotators-heavy
577 marginalia-annotators-light))
588 578
589#+begin_src emacs-lisp 579 (marginalia-mode +1)
590 (straight-use-package 'ctrlf) 580 #+END_SRC
591 (require 'ctrlf)
592 581
593 (cuss ctrlf-show-match-count-at-eol nil) 582**** COMMENT Ido
594 583
595 (cuss ctrlf-mode-bindings 584[[https://wandersoncferreira.github.io/blog/ido/][Let’s try this out]].
596 '(("C-s" . ctrlf-forward-regexp)
597 ("C-r" . ctrlf-backward-regexp)
598 ("C-M-s" . ctrlf-forward-literal)
599 ("C-M-r" . ctrlf-backward-literal)
600 ("M-s _" . ctrlf-forward-symbol)
601 ("M-s ." . ctrlf-forward-symbol-at-point)))
602
603 (ctrlf-mode +1)
604#+end_src
605
606** Replace
607 585
608#+begin_src emacs-lisp 586#+begin_src emacs-lisp
609 (straight-use-package 'anzu) 587 (defun ido-choose-from-recentf ()
610 (global-anzu-mode +1) 588 "Use ido to select recently visited files."
611 589 (interactive)
612 (cuss anzu-replace-to-string-separator " → ") 590 (find-file (ido-completing-read "Open file: " recentf-list nil t)))
613 (global-set-key (kbd "M-%") #'anzu-query-replace-regexp)
614 (global-set-key (kbd "M-C-%") #'anzu-query-replace)
615#+end_src
616
617** Mouse
618
619*** Fix scrolling in margins
620
621This is not /quite/ correct yet. For example, scrolling in the margins with a trackpad isn’t picked up (a trackpad sends different mouse events).
622 591
623#+begin_src emacs-lisp 592 (defun bk/go-straight-home ()
624 (dolist (vec '([left-margin wheel-down] 593 (interactive)
625 [right-margin wheel-down] 594 (cond
626 [left-margin wheel-up] 595 ((looking-back "~/") (insert "projects/"))
627 [right-margin wheel-up])) 596 ((looking-back "/") (insert "~/"))
628 (global-set-key vec #'mwheel-scroll)) 597 (:else (call-interactively 'self-insert-command))))
598
599 (defun ido-disable-line-truncation ()
600 (set (make-local-variable 'truncate-lines) nil))
601
602 (defun ido-define-keys ()
603 (define-key ido-completion-map (kbd "C-n") 'ido-next-match)
604 (define-key ido-completion-map (kbd "C-p") 'ido-prev-match))
605
606 (setq ido-enable-flex-matching t
607 ido-use-filename-at-point nil
608 ido-create-new-buffer 'always
609 confirm-nonexistent-file-or-buffer nil
610 completion-ignored-extensions (cons "*.aux" completion-ignored-extensions)
611 max-mini-window-height 0.5
612 ido-enable-tramp-completion t
613 ido-auto-merge-work-directories-length -1
614 ido-confirm-unique-completion t
615 ido-default-file-method 'selected-window
616 ido-case-fold t
617 ido-show-dot-for-dired t
618 ido-everywhere t
619 ido-ignore-buffers (list (rx (or (and bos " ")
620 (and bos
621 (or "*Completions*"
622 "*Compile-Log*"
623 "*Ido Completions*"
624 "*Shell Command Output*"
625 "*vc-diff*")
626 eos))))
627 ido-decorations (quote ("\n-> " "" "\n " "\n ..." "[" "]" "
628 [No match]" " [Matched]" " [Not readable]" " [Too big]" "
629 [Confirm]")))
630
631 (with-eval-after-load 'ido
632 (define-key ido-common-completion-map (kbd "M-SPC") 'just-one-space)
633 (define-key ido-common-completion-map (kbd "SPC") 'self-insert-command)
634 (define-key ido-file-completion-map (kbd "~") 'bk/go-straight-home)
635
636 (add-hook 'ido-setup-hook 'ido-define-keys)
637
638 (add-hook 'ido-minibuffer-setup-hook 'ido-disable-line-truncation)
639
640 (set-default 'imenu-auto-rescan t)
641
642 (add-to-list 'ido-ignore-directories "target")
643 (add-to-list 'ido-ignore-directories "node_modules")
644 )
645
646 (defun setup-ido-mode ()
647 (require 'ido)
648 (ido-mode +1)
649 (ido-everywhere +1))
650
651 (add-hook 'after-init-hook #'setup-ido-mode)
629#+end_src 652#+end_src
630 653
631** Keyboard 654** Keyboard
632 655
633*** Use =ESC= as a cancel key 656*** =ESC= cancels all
634 657
635From [[https://github.com/link0ff/emacs-init][link0ff]]. I thought they made a great point that =ESC= isn’t necessary to copy the =META= key on window-systems, which is where I use Emacs, anyway. 658#+BEGIN_SRC emacs-lisp
659(global-set-key (kbd "<escape>") #'keyboard-escape-quit)
660#+END_SRC
636 661
637#+begin_src emacs-lisp 662*** Personal prefix key: =C-z=
638 (when window-system
639 (global-set-key [escape] 'keyboard-escape-quit)
640 (define-key isearch-mode-map [escape] 'isearch-cancel))
641#+end_src
642 663
643*** Make =C-z= more useful as a prefix key 664#+BEGIN_SRC emacs-lisp
665(defvar acdw/map
666 (let ((map (make-sparse-keymap))
667 (c-z (global-key-binding "\C-z")))
668 (global-unset-key "\C-z")
669 (define-key global-map "\C-z" map)
670 (define-key map "\C-z" c-z)
671 map))
644 672
645Also from link0ff. See the above for a link. 673(run-hooks 'acdw/map-defined-hook)
646 674#+END_SRC
647#+begin_src emacs-lisp
648 (defvar acdw/map
649 (let ((map (make-sparse-keymap))
650 (c-z (global-key-binding "\C-z")))
651 (global-unset-key "\C-z")
652 (define-key global-map "\C-z" map)
653 (define-key map "\C-z" c-z)
654 map))
655 (run-hooks 'acdw/map-defined-hook)
656#+end_src
657 675
658*** Which-key 676** Persistence
659 677
660#+begin_src emacs-lisp 678*** Minibuffer history
661 (straight-use-package 'which-key)
662 679
663 (which-key-mode +1) 680#+BEGIN_SRC emacs-lisp
664#+end_src 681(require 'savehist)
665 682
666*** Bindings 683(cuss savehist-additional-variables
684 '(kill-ring
685 search-ring
686 regexp-search-ring)
687 "Other variables to save alongside the minibuffer history.")
667 688
668**** Switch to another window 689(cuss history-length t
690 "Don't truncate history.")
669 691
670#+begin_src emacs-lisp 692(cuss history-delete-duplicates t
671 (global-set-key (kbd "M-o") #'other-window) 693 "Delete history duplicates.")
672#+end_src
673 694
674* Persistence 695(savehist-mode +1)
696#+END_SRC
675 697
676** Save history 698*** File places
677 699
678#+begin_src emacs-lisp 700#+BEGIN_SRC emacs-lisp
679 (require 'savehist) 701(require 'saveplace) ; this isn't required, but ... I like having it here
680 702
681 (cuss savehist-additional-variables 703(cuss save-place-forget-unreadable-files t
682 '(kill-ring 704 "Don't check if files are readable or not.")
683 search-ring
684 regexp-search-ring))
685 705
686 (cuss savehist-save-minibuffer-history t) 706(save-place-mode +1)
707#+END_SRC
687 708
688 (cuss history-length t) 709*** Recent files
689 710
690 (cuss history-delete-duplicates t) 711#+BEGIN_SRC emacs-lisp
712(require 'recentf)
691 713
692 (savehist-mode +1) 714(cuss recentf-max-menu-items 100
693#+end_src 715 "The maximum number of items in the recentf menu.")
716(cuss recentf-max-saved-items nil
717 "Don't limit the number of recent files.")
694 718
695** Save places in files 719(with-eval-after-load 'no-littering
720 (add-to-list 'recentf-exclude no-littering-var-directory)
721 (add-to-list 'recentf-exclude no-littering-etc-directory))
696 722
697#+begin_src emacs-lisp 723(recentf-mode +1)
698 (require 'saveplace)
699 724
700 (cuss save-place-forget-unreadable-files 725;; save the recentf-list every 5 minutes
701 (not (eq system-type 'windows-nt))) 726(run-at-time nil (* 5 60) 'recentf-save-list)
702 727#+END_SRC
703 (save-place-mode 1)
704#+end_src
705
706** Recent files
707
708#+begin_src emacs-lisp
709 (require 'recentf)
710
711 (cuss recentf-max-menu-items 100)
712 (cuss recentf-max-saved-items 100)
713
714 (with-eval-after-load 'no-littering
715 (add-to-list 'recentf-exclude no-littering-var-directory)
716 (add-to-list 'recentf-exclude no-littering-etc-directory))
717
718 (recentf-mode 1)
719#+end_src
720
721*** Easily navigate recent files
722
723#+begin_src emacs-lisp
724 (defun recentf-find-file ()
725 "Find a recent file using `completing-read'."
726 (interactive)
727 (let ((file (completing-read "Recent file: " recentf-list nil t)))
728 (when file
729 (find-file file))))
730
731 (global-set-key (kbd "C-x C-r") #'recentf-find-file)
732#+end_src
733 728
734** Undo 729** Undo
735 730
736#+begin_src emacs-lisp 731#+BEGIN_SRC emacs-lisp
737 (straight-use-package 'undo-fu) 732(straight-use-package 'undo-fu)
738 (require 'undo-fu) 733(require 'undo-fu)
739 734
740 (global-set-key (kbd "C-/") #'undo-fu-only-undo) 735(global-set-key (kbd "C-/") #'undo-fu-only-undo)
741 (global-set-key (kbd "C-?") #'undo-fu-only-redo) 736(global-set-key (kbd "C-?") #'undo-fu-only-redo)
742 737
743 (straight-use-package 'undo-fu-session) 738(straight-use-package 'undo-fu-session)
744 (require 'undo-fu-session) 739(require 'undo-fu-session)
745 740
746 (cuss undo-fu-session-incompatible-files 741(cuss undo-fu-session-incompatible-files
747 '("/COMMIT_EDITMSG\\'" 742 '("/COMMIT_EDITMSG\\'"
748 "/git-rebase-todo\\'")) 743 "/git-rebase-todo\\'")
744 "A list of files that are incompatible with the concept of undo sessions.")
749 745
750 (global-undo-fu-session-mode +1) 746(with-eval-after-load 'no-littering
747 (let ((dir (no-littering-expand-var-file-name "undos")))
748 (make-directory dir 'parents)
749 (cuss undo-fu-session-directory dir)))
751 750
752#+end_src 751(global-undo-fu-session-mode +1)
752#+END_SRC
753 753
754* Editing 754** Files
755 755
756** Operate visually on lines 756*** Encoding
757 757
758#+begin_src emacs-lisp 758**** UTF-8
759 (global-visual-line-mode +1)
760#+end_src
761 759
762** Require a final newline 760 #+BEGIN_SRC emacs-lisp
761 (set-language-environment "UTF-8")
762 (set-terminal-coding-system 'utf-8)
763 (cuss locale-coding-system 'utf-8)
764 (set-default-coding-systems 'utf-8)
765 (set-selection-coding-system 'utf-8)
766 (prefer-coding-system 'utf-8)
767 #+END_SRC
763 768
764#+begin_src emacs-lisp 769**** Convert all files to UNIX-style line endings
765 (cuss require-final-newline t)
766#+end_src
767 770
768** Killing & Yanking 771 from [[https://www.emacswiki.org/emacs/EndOfLineTips][Emacs Wiki]].
769 772
770*** Replace selection when typing 773 #+BEGIN_SRC emacs-lisp
774 (defun ewiki/no-junk-please-were-unixish ()
775 "Convert line endings to UNIX, dammit."
776 (let ((coding-str (symbol-name buffer-file-coding-system)))
777 (when (string-match "-\\(?:dos\\|mac\\)$" coding-str)
778 (set-buffer-file-coding-system 'unix))))
779 #+END_SRC
780
781 I add it to the ~find-file-hook~ /and/ ~before-save-hook~ because I
782 don't want to ever work with anything other than UNIX line endings
783 ever again. I just don't care. Even Microsoft Notepad can handle
784 UNIX line endings, so I don't want to hear it.
771 785
772#+begin_src emacs-lisp 786 #+BEGIN_SRC emacs-lisp
773 (delete-selection-mode +1) 787 (add-hook 'find-file-hook #'ewiki/no-junk-please-were-unixish)
774#+end_src 788 (add-hook 'before-save-hook #'ewiki/no-junk-please-were-unixish)
789 #+END_SRC
775 790
776*** Save existing clipboard text into kill ring before replacing it 791*** Backups
777 792
778#+begin_src emacs-lisp 793#+BEGIN_SRC emacs-lisp
779 (cuss save-interprogram-paste-before-kill t) 794(cuss backup-by-copying 1)
780#+end_src 795(cuss delete-old-versions -1)
796(cuss version-control t)
797(cuss vc-make-backup-files t)
781 798
782*** Sync the system clipboard and the kill ring 799(with-eval-after-load 'no-littering
800 (let ((dir (no-littering-expand-var-file-name "backup")))
801 (make-directory dir 'parents)
802 (cuss backup-directory-alist
803 `((".*" . ,dir)))))
804#+END_SRC
783 805
784#+begin_src emacs-lisp 806*** Auto-saves
785 (cuss yank-pop-change-selection t)
786#+end_src
787 807
788** So long mode 808#+BEGIN_SRC emacs-lisp
809(with-eval-after-load 'no-littering
810 (let ((dir (no-littering-expand-var-file-name "autosaves")))
811 (make-directory dir 'parents)
812 (cuss auto-save-file-name-transforms
813 `((".*" ,dir t))))
789 814
790#+begin_src emacs-lisp 815 (auto-save-visited-mode +1))
791 (when (fboundp 'global-so-long-mode) 816#+END_SRC
792 (global-so-long-mode))
793#+end_src
794 817
795** Multiple cursors 818*** Auto-revert buffers to files on disk
796 819
797#+begin_src emacs-lisp 820#+BEGIN_SRC emacs-lisp
798 (straight-use-package 'multiple-cursors) 821(global-auto-revert-mode +1)
822#+END_SRC
799 823
800 (global-set-key (kbd "C->") #'mc/mark-next-like-this) 824*** Add a timestamp to files
801 (global-set-key (kbd "C-<") #'mc/mark-previous-like-this)
802 (global-set-key (kbd "C-c C-<") #'mc/mark-all-like-this)
803#+end_src
804 825
805** Expand region 826#+BEGIN_SRC emacs-lisp
827(add-hook 'before-save-hook #'time-stamp)
828#+END_SRC
806 829
807#+begin_src emacs-lisp 830*** Require a final new line
808 (straight-use-package 'expand-region)
809 831
810 (global-set-key (kbd "C-=") #'er/expand-region) 832#+BEGIN_SRC emacs-lisp
811 (global-set-key (kbd "C-+") #'er/contract-region) 833(cuss require-final-newline t)
812#+end_src 834#+END_SRC
813 835
814** Highlight modified regions 836** Text editing
815 837
816#+begin_src emacs-lisp 838*** Operate visually on lines
817 (straight-use-package 'goggles)
818 839
819 (cuss goggles-pulse nil) 840#+BEGIN_SRC emacs-lisp
841(global-visual-line-mode +1)
842#+END_SRC
820 843
821 (goggles-mode +1) 844*** Stay snappy with long-lined files
822#+end_src
823 845
824* Files 846#+BEGIN_SRC emacs-lisp
847(when (fboundp 'global-so-long-mode)
848 (global-so-long-mode +1))
849#+END_SRC
825 850
826** Encoding 851*** Killing & Yanking
827 852
828*** UTF-8 853**** Replace selection when typing
829 854
830 #+begin_src emacs-lisp 855#+BEGIN_SRC emacs-lisp
831 (set-language-environment "UTF-8") 856(delete-selection-mode +1)
832 (set-terminal-coding-system 'utf-8) 857#+END_SRC
833 (cuss locale-coding-system 'utf-8)
834 (set-default-coding-systems 'utf-8)
835 (set-selection-coding-system 'utf-8)
836 (prefer-coding-system 'utf-8)
837 #+end_src
838 858
839*** Convert all files to UNIX-style line endings 859**** Work better with the system clipboard
840 860
841 from [[https://www.emacswiki.org/emacs/EndOfLineTips][Emacs Wiki]]. 861#+BEGIN_SRC emacs-lisp
862(cuss save-interprogram-paste-before-kill t
863 "Save existing clipboard text into the kill ring before
864 replacing it.")
842 865
843 #+begin_src emacs-lisp 866(cuss yank-pop-change-selection t
844 (defun ewiki/no-junk-please-were-unixish () 867 "Update the X selection when rotating the kill ring.")
845 "Convert line endings to UNIX, dammit." 868#+END_SRC
846 (let ((coding-str (symbol-name buffer-file-coding-system)))
847 (when (string-match "-\\(?:dos\\|mac\\)$" coding-str)
848 (set-buffer-file-coding-system 'unix))))
849 #+end_src
850 869
851 I add it to the ~find-file-hook~ /and/ ~before-save-hook~ because I don't want to ever work with anything other than UNIX line endings ever again. I just don't care. Even Microsoft Notepad can handle UNIX line endings, so I don't want to hear it. 870*** Searching & Replacing
852 871
853 #+begin_src emacs-lisp 872**** COMMENT Search with CtrlF
854 (add-hook 'find-file-hook #'ewiki/no-junk-please-were-unixish)
855 (add-hook 'before-save-hook #'ewiki/no-junk-please-were-unixish)
856 #+end_src
857 873
858** Backups 874For right now, I’m /just/ using Anzu – I don’t like parts of =isearch= but … CtrlF doesn’t match with that sweet replace flow.
859 875
860#+begin_src emacs-lisp 876#+begin_src emacs-lisp
861 (cuss backup-by-copying 1) 877 (straight-use-package 'ctrlf)
862 (cuss delete-old-versions -1) 878 (ctrlf-mode +1)
863 (cuss version-control t)
864 (cuss vc-make-backup-files t)
865#+end_src 879#+end_src
866 880
867** Auto-saves 881**** Replace with Anzu
868 882
869#+begin_src emacs-lisp 883#+begin_src emacs-lisp
870 (auto-save-visited-mode 1) 884 (straight-use-package 'anzu)
871#+end_src 885 (require 'anzu)
872 886
873** Revert files 887 ;; show search count in the modeline
888 (global-anzu-mode +1)
874 889
875#+begin_src emacs-lisp 890 (cuss anzu-replace-to-string-separator " → "
876 (cuss auto-revert-verbose nil) 891 "What to separate the search from the replacement.")
877 (global-auto-revert-mode +1)
878#+end_src
879 892
880** Add a timestamp to files 893 (global-set-key [remap query-replace] #'anzu-query-replace)
881 894 (global-set-key [remap query-replace-regexp] #'anzu-query-replace-regexp)
882#+begin_src emacs-lisp
883 (add-hook 'before-save-hook #'time-stamp)
884#+end_src
885 895
886* Programming 896 (define-key isearch-mode-map [remap isearch-query-replace] #'anzu-isearch-query-replace)
897 (define-key isearch-mode-map [remap isearch-query-replace-regexp] #'anzu-isearch-query-replace-regexp)
887 898
888** Which function are we in?
889 899
890#+begin_src emacs-lisp
891 (which-function-mode +1)
892#+end_src 900#+end_src
893 901
894** Parentheses 902* Programming
895
896*** Show parentheses
897 903
898#+begin_src emacs-lisp 904** Parentheses
899 (cuss show-paren-delay 0 "Show matching parens immediately.")
900 (cuss show-paren-style 'mixed
901 "Show parenthesis, or whole expression, depending on visibility.")
902 (cuss show-paren-when-point-in-periphery t
903 "Show paren when point is near-to paren.")
904 (cuss show-paren-when-point-inside-paren t
905 "Show surrounding parens.")
906
907 (add-hook 'prog-mode-hook #'show-paren-mode)
908#+end_src
909 905
910*** Smart parentheses 906*** Smart parentheses
911 907
912#+begin_src emacs-lisp 908#+BEGIN_SRC emacs-lisp
913 (straight-use-package 'smartparens) 909(straight-use-package 'smartparens)
914 (require 'smartparens-config) 910(require 'smartparens-config)
915
916 (show-smartparens-global-mode +1)
917 (add-to-list 'sp-ignore-modes-list 'org-mode)
918 911
919 (add-hook 'prog-mode-hook #'smartparens-strict-mode) 912;; replace show-paren
920#+end_src
921 913
922** COMMENT Line numbers 914(cuss sp-show-pair-delay 0
915 "Don't delay before showing the pairs.")
916(cuss sp-show-pair-from-inside t
917 "Highlight the enclosing pair when immediately inside.")
923 918
924#+begin_src emacs-lisp 919(add-hook 'prog-mode-hook #'show-smartparens-mode +1)
925 (defun acdw/enable-line-numbers ()
926 "Enable line numbers, through either
927 `display-line-numbers-mode' or through `linum-mode'."
928 (if (and (fboundp 'display-line-numbers-mode)
929 (display-graphic-p))
930 (display-line-numbers-mode +1)
931 (linum-mode +1)))
932
933 (cuss display-line-numbers-width 2
934 "Always have at least 2 digits for line numbers.")
935
936 (add-hook 'prog-mode-hook #'acdw/enable-line-numbers)
937#+end_src
938 920
939** Indenting 921;; enable strict smartparens in prog mode
922(add-hook 'prog-mode-hook #'smartparens-strict-mode)
923#+END_SRC
940 924
941#+begin_src emacs-lisp 925** Indent aggressively
942 (straight-use-package 'aggressive-indent)
943 926
944 (global-aggressive-indent-mode +1) 927#+BEGIN_SRC emacs-lisp
945#+end_src 928(straight-use-package 'aggressive-indent)
946 929
947** Completion 930(global-aggressive-indent-mode +1)
931#+END_SRC
948 932
949#+begin_src emacs-lisp 933** Language-specific packages
950 (unless (eq system-type 'windows-nt)
951 (straight-use-package 'company)
952 (cuss company-idle-delay 0.1)
953 (cuss company-minimum-prefix-length 2)
954
955 (add-hook 'prog-mode-hook #'company-mode)
956
957 (straight-use-package 'company-prescient)
958 (add-hook 'company-mode-hook #'company-prescient-mode)
959
960 (straight-use-package 'company-posframe)
961
962 (with-eval-after-load 'company
963 (company-posframe-mode +1)
964 (define-key company-active-map (kbd "C-n")
965 (lambda ()
966 (interactive)
967 (company-complete-common-or-cycle +1)))
968 (define-key company-active-map (kbd "C-p")
969 (lambda ()
970 (interactive)
971 (company-complete-common-or-cycle -1)))))
972#+end_src
973
974** Languages
975
976*** Lua
977
978#+begin_src emacs-lisp
979 (straight-use-package 'lua-mode)
980 (add-to-list 'auto-mode-alist '("\\.lua\\'" . lua-mode))
981 (add-to-list 'interpreter-mode-alist '("lua" . lua-mode))
982#+end_src
983
984*** Fennel
985
986#+begin_src emacs-lisp
987 (straight-use-package 'fennel-mode)
988 (add-to-list 'auto-mode-alist '("\\.fnl\\'" . fennel-mode))
989#+end_src
990 934
991*** Emacs lisp 935*** Emacs lisp
992 936
993#+begin_src emacs-lisp 937#+BEGIN_SRC emacs-lisp
994 (cuss eval-expression-print-length nil 938(cuss eval-expression-print-length nil
995 "Don't truncate printed expressions by length.") 939 "Don't truncate printed expressions by length.")
996 (cuss eval-expression-print-level nil 940(cuss eval-expression-print-level nil
997 "Don't truncate printed expressions by level.") 941 "Don't truncate printed expressions by level.")
998#+end_src 942#+END_SRC
999 943
1000* Writing 944* Writing
1001 945
1002** Visual Fill Column 946** Visual fill column
1003
1004#+begin_src emacs-lisp
1005 (straight-use-package 'visual-fill-column)
1006
1007 (cuss split-window-preferred-function
1008 'visual-fill-column-split-window-sensibly)
1009 (cuss visual-fill-column-center-text t)
1010 (cuss fill-column 80)
1011
1012 (advice-add 'text-scale-adjust
1013 :after #'visual-fill-column-adjust)
1014
1015 (add-hook 'text-mode-hook #'visual-fill-column-mode)
1016#+end_src
1017
1018*** COMMENT Split windows /more/ sensibly
1019
1020from [[https://stackoverflow.com/questions/23659909/reverse-evaluation-order-of-split-height-threshold-and-split-width-threshold-in][Stack Overflow]].
1021
1022#+begin_src emacs-lisp
1023 (defun my-split-window-sensibly (&optional window)
1024 (let ((window (or window (selected-window))))
1025 (or (and (window-splittable-p window t)
1026 ;; Split window horizontally.
1027 (with-selected-window window
1028 (split-window-right)))
1029 (and (window-splittable-p window)
1030 ;; Split window vertically.
1031 (with-selected-window window
1032 (split-window-below)))
1033 (and (eq window (frame-root-window (window-frame window)))
1034 (not (window-minibuffer-p window))
1035 ;; If WINDOW is the only window on its frame and is not the
1036 ;; minibuffer window, try to split it horizontally disregarding
1037 ;; the value of `split-width-threshold'.
1038 (let ((split-width-threshold 0))
1039 (when (window-splittable-p window t)
1040 (with-selected-window window
1041 (split-window-right))))))))
1042
1043 (setq split-window-preferred-function #'my-split-window-sensibly)
1044#+end_src
1045 947
1046** Type nice-looking quote-type marks 948*** Fix scrolling in margins
1047
1048#+begin_src emacs-lisp
1049 (straight-use-package 'typo)
1050 (add-hook 'text-mode-hook #'typo-mode)
1051#+end_src
1052 949
1053** Insert /kaomoji/ 950This has to be done /before/ loading the package. It's included in =visual-fill-column=, too, but for some reason isn't loaded there.
1054 951
1055#+begin_src emacs-lisp 952#+BEGIN_SRC emacs-lisp
1056 (straight-use-package 'insert-kaomoji) 953(global-set-key [right-margin mouse-1] (global-key-binding [mouse-1])) ; #'mouse-set-point
1057 (global-set-key (kbd "C-x 8 k") #'insert-kaomoji) 954(global-set-key [right-margin mouse-2] (global-key-binding [mouse-2])) ; #'mouse-yank-primary
1058#+end_src 955(global-set-key [right-margin mouse-3] (global-key-binding [mouse-3])) ; #'mouse-save-then-kill
956(global-set-key [right-margin drag-mouse-1] #'ignore)
957(global-set-key [right-margin drag-mouse-2] #'ignore)
958(global-set-key [right-margin drag-mouse-3] #'ignore)
959(global-set-key [right-margin double-mouse-1] #'ignore)
960(global-set-key [right-margin double-mouse-2] #'ignore)
961(global-set-key [right-margin double-mouse-3] #'ignore)
962(global-set-key [right-margin triple-mouse-1] #'ignore)
963(global-set-key [right-margin triple-mouse-2] #'ignore)
964(global-set-key [right-margin triple-mouse-3] #'ignore)
965(global-set-key [left-margin mouse-1] (global-key-binding [mouse-1])) ; #'mouse-set-point
966(global-set-key [left-margin mouse-2] (global-key-binding [mouse-2])) ; #'mouse-yank-primary
967(global-set-key [left-margin mouse-3] (global-key-binding [mouse-3])) ; #'mouse-save-then-kill
968(global-set-key [left-margin drag-mouse-1] #'ignore)
969(global-set-key [left-margin drag-mouse-2] #'ignore)
970(global-set-key [left-margin drag-mouse-3] #'ignore)
971(global-set-key [left-margin double-mouse-1] #'ignore)
972(global-set-key [left-margin double-mouse-2] #'ignore)
973(global-set-key [left-margin double-mouse-3] #'ignore)
974(global-set-key [left-margin triple-mouse-1] #'ignore)
975(global-set-key [left-margin triple-mouse-2] #'ignore)
976(global-set-key [left-margin triple-mouse-3] #'ignore)
977
978(mouse-wheel-mode +1)
979
980(when (bound-and-true-p mouse-wheel-mode)
981 (global-set-key [right-margin mouse-wheel-down-event] #'mwheel-scroll)
982 (global-set-key [right-margin mouse-wheel-up-event] #'mwheel-scroll)
983 (global-set-key [right-margin wheel-down] #'mwheel-scroll)
984 (global-set-key [right-margin wheel-up] #'mwheel-scroll)
985 (global-set-key [left-margin mouse-wheel-down-event] #'mwheel-scroll)
986 (global-set-key [left-margin mouse-wheel-up-event] #'mwheel-scroll)
987 (global-set-key [left-margin wheel-down] #'mwheel-scroll)
988 (global-set-key [left-margin wheel-up] #'mwheel-scroll))
989#+END_SRC
990
991*** Load the package
992
993#+BEGIN_SRC emacs-lisp
994(straight-use-package 'visual-fill-column)
995
996(cuss visual-fill-column-center-text nil
997 "Whether to center the text in the frame.")
998
999(cuss fill-column 84
1000 "Width of fill-column, and thus, visual-fill-column.")
1001
1002(advice-add 'text-scale-adjust
1003 :after #'visual-fill-column-adjust)
1004
1005(global-visual-fill-column-mode +1)
1006#+END_SRC
1007
1008** Typographical niceties
1009
1010*** Typo mode
1011
1012#+BEGIN_SRC emacs-lisp
1013(straight-use-package 'typo)
1014
1015(add-hook 'text-mode-hook #'typo-mode)
1016#+END_SRC
1059 1017
1060* Applications 1018* Applications
1061 1019
1062** Magit
1063
1064#+begin_src emacs-lisp
1065 (straight-use-package 'magit)
1066
1067 (define-key acdw/map "g" #'magit-status)
1068#+end_src
1069
1070** Org mode 1020** Org mode
1071 1021
1072I’ve put org mode under Applications, as opposed to Writing, because it’s more generally-applicable than that. 1022I’ve put org mode under Applications, as opposed to Writing, because it’s more generally-applicable than that.
1073 1023
1074#+begin_src emacs-lisp 1024*** Basics
1075 (straight-use-package 'org) 1025
1076 1026#+BEGIN_SRC emacs-lisp
1077 (with-eval-after-load 'org 1027(straight-use-package 'org)
1078 (require 'org-tempo) 1028
1079 (require 'ox-md) 1029(with-eval-after-load 'org
1080 (define-key org-mode-map (kbd "M-n") #'outline-next-visible-heading) 1030 (require 'org-tempo)
1081 (define-key org-mode-map (kbd "M-p") #'outline-previous-visible-heading)) 1031 (require 'ox-md)
1082 1032 (define-key org-mode-map (kbd "M-n") #'outline-next-visible-heading)
1083 (cuss org-hide-emphasis-markers t) 1033 (define-key org-mode-map (kbd "M-p") #'outline-previous-visible-heading))
1084 (cuss org-fontify-done-headline t) 1034
1085 (cuss org-fontify-whole-heading-line t) 1035(cuss org-hide-emphasis-markers t)
1086 (cuss org-fontify-quote-and-verse-blocks t) 1036(cuss org-fontify-done-headline t)
1087 (cuss org-pretty-entities t) 1037(cuss org-fontify-whole-heading-line t)
1088 (cuss org-num-mode +1) 1038(cuss org-fontify-quote-and-verse-blocks t)
1089 (cuss org-src-tab-acts-natively t) 1039(cuss org-pretty-entities t)
1090 (cuss org-src-fontify-natively t) 1040(cuss org-num-mode +1)
1091 (cuss org-src-window-setup 'current-window) 1041(cuss org-src-tab-acts-natively t)
1092 (cuss org-confirm-babel-evaluate nil) 1042(cuss org-src-fontify-natively t)
1093 (cuss org-directory "~/Org") 1043(cuss org-src-window-setup 'current-window)
1094#+end_src 1044(cuss org-confirm-babel-evaluate nil)
1045(cuss org-directory "~/Org")
1046#+END_SRC
1095 1047
1096*** Org Agenda 1048*** Org Agenda
1097 1049
1098#+begin_src emacs-lisp 1050#+BEGIN_SRC emacs-lisp
1099 (cuss org-agenda-files (no-littering-expand-etc-file-name "agenda-files")) 1051(cuss org-agenda-files (no-littering-expand-etc-file-name "agenda-files"))
1100
1101 (if (and (stringp org-agenda-files)
1102 (not (file-exists-p org-agenda-files)))
1103 (with-temp-buffer (write-file org-agenda-files)))
1104
1105 (define-key acdw/map (kbd "C-a") #'org-agenda)
1106#+end_src
1107 1052
1108*** COMMENT Make bullets look like bullets 1053(if (and (stringp org-agenda-files)
1054 (not (file-exists-p org-agenda-files)))
1055 (with-temp-buffer (write-file org-agenda-files)))
1109 1056
1110#+begin_src emacs-lisp 1057(define-key acdw/map (kbd "C-a") #'org-agenda)
1111 (font-lock-add-keywords 1058#+END_SRC
1112 'org-mode
1113 '(("^ *\\([-+]\\) "
1114 (0 (prog1 ()
1115 (compose-region (match-beginning 1)
1116 (match-end 1)
1117 "•"))))))
1118#+end_src
1119 1059
1120*** [[http://kitchingroup.cheme.cmu.edu/blog/2017/04/09/A-better-return-in-org-mode/][A better return in Org mode]] 1060*** [[http://kitchingroup.cheme.cmu.edu/blog/2017/04/09/A-better-return-in-org-mode/][A better return in Org mode]]
1121 1061
1122#+begin_src emacs-lisp 1062#+BEGIN_SRC emacs-lisp
1123 (require 'org-inlinetask) 1063(require 'org-inlinetask)
1124 1064
1125 (defun scimax/org-return (&optional ignore) 1065(defun scimax/org-return (&optional ignore)
1126 "Add new list item, heading or table row with RET. 1066 "Add new list item, heading or table row with RET.
1127 A double return on an empty element deletes it. 1067A double return on an empty element deletes it.
1128 Use a prefix arg to get regular RET." 1068Use a prefix arg to get regular RET."
1129 (interactive "P") 1069 (interactive "P")
1130 (if ignore 1070 (if ignore
1131 (org-return) 1071 (org-return)
1132 (cond 1072 (cond
1133 1073
1134 ((eq 'line-break (car (org-element-context))) 1074 ((eq 'line-break (car (org-element-context)))
1135 (org-return t)) 1075 (org-return t))
1136 1076
1137 ;; Open links like usual, unless point is at the end of a line. 1077 ;; Open links like usual, unless point is at the end of a line.
1138 ;; and if at beginning of line, just press enter. 1078 ;; and if at beginning of line, just press enter.
1139 ((or (and (eq 'link (car (org-element-context))) (not (eolp))) 1079 ((or (and (eq 'link (car (org-element-context))) (not (eolp)))
1140 (bolp)) 1080 (bolp))
1141 (org-return)) 1081 (org-return))
1142 1082
1143 ;; It doesn't make sense to add headings in inline tasks. Thanks Anders 1083 ;; It doesn't make sense to add headings in inline tasks. Thanks Anders
1144 ;; Johansson! 1084 ;; Johansson!
1145 ((org-inlinetask-in-task-p) 1085 ((org-inlinetask-in-task-p)
1146 (org-return)) 1086 (org-return))
1147 1087
1148 ;; checkboxes too 1088 ;; checkboxes too
1149 ((org-at-item-checkbox-p) 1089 ((org-at-item-checkbox-p)
1150 (org-insert-todo-heading nil)) 1090 (org-insert-todo-heading nil))
1151 1091
1152 ;; lists end with two blank lines, so we need to make sure we are also not 1092 ;; lists end with two blank lines, so we need to make sure we are also not
1153 ;; at the beginning of a line to avoid a loop where a new entry gets 1093 ;; at the beginning of a line to avoid a loop where a new entry gets
1154 ;; created with only one blank line. 1094 ;; created with only one blank line.
1155 ((org-in-item-p) 1095 ((org-in-item-p)
1156 (if (save-excursion (beginning-of-line) (org-element-property :contents-begin (org-element-context))) 1096 (if (save-excursion (beginning-of-line) (org-element-property :contents-begin (org-element-context)))
1157 (org-insert-heading) 1097 (org-insert-heading)
1158 (beginning-of-line) 1098 (beginning-of-line)
1159 (delete-region (line-beginning-position) (line-end-position)) 1099 (delete-region (line-beginning-position) (line-end-position))
1160 (org-return))) 1100 (org-return)))
1161 1101
1162 ;; org-heading 1102 ;; org-heading
1163 ((org-at-heading-p) 1103 ((org-at-heading-p)
1164 (if (not (string= "" (org-element-property :title (org-element-context)))) 1104 (if (not (string= "" (org-element-property :title (org-element-context))))
1165 (progn (org-end-of-meta-data) 1105 (progn (org-end-of-meta-data)
1166 (org-insert-heading-respect-content) 1106 (org-insert-heading-respect-content)
1167 (outline-show-entry)) 1107 (outline-show-entry))
1168 (beginning-of-line) 1108 (beginning-of-line)
1169 (setf (buffer-substring 1109 (setf (buffer-substring
1170 (line-beginning-position) (line-end-position)) ""))) 1110 (line-beginning-position) (line-end-position)) "")))
1171 1111
1172 ;; tables 1112 ;; tables
1173 ((org-at-table-p) 1113 ((org-at-table-p)
1174 (if (-any? 1114 (if (-any?
1175 (lambda (x) (not (string= "" x))) 1115 (lambda (x) (not (string= "" x)))
1176 (nth 1116 (nth
1177 (- (org-table-current-dline) 1) 1117 (- (org-table-current-dline) 1)
1178 (org-table-to-lisp))) 1118 (org-table-to-lisp)))
1179 (org-return) 1119 (org-return)
1180 ;; empty row 1120 ;; empty row
1181 (beginning-of-line) 1121 (beginning-of-line)
1182 (setf (buffer-substring 1122 (setf (buffer-substring
1183 (line-beginning-position) (line-end-position)) "") 1123 (line-beginning-position) (line-end-position)) "")
1184 (org-return))) 1124 (org-return)))
1185 1125
1186 ;; fall-through case 1126 ;; fall-through case
1187 (t 1127 (t
1188 (org-return))))) 1128 (org-return)))))
1189 1129
1190 1130
1191 (define-key org-mode-map (kbd "RET") 1131(define-key org-mode-map (kbd "RET")
1192 'scimax/org-return) 1132 'scimax/org-return)
1193#+end_src 1133#+END_SRC
1194 1134
1195*** Insert blank lines 1135*** Insert blank lines around headers
1196 1136
1197from [[https://github.com/alphapapa/unpackaged.el#ensure-blank-lines-between-headings-and-before-contents][unpackaged.el]]. 1137from [[https://github.com/alphapapa/unpackaged.el#ensure-blank-lines-between-headings-and-before-contents][unpackaged.el]].
1198 1138
1199#+begin_src emacs-lisp 1139#+BEGIN_SRC emacs-lisp
1200 ;;;###autoload 1140;;;###autoload
1201 (defun unpackaged/org-fix-blank-lines (&optional prefix) 1141(defun unpackaged/org-fix-blank-lines (&optional prefix)
1202 "Ensure that blank lines exist between headings and between headings and their contents. 1142 "Ensure that blank lines exist between headings and between headings and their contents.
1203 With prefix, operate on whole buffer. Ensures that blank lines 1143With prefix, operate on whole buffer. Ensures that blank lines
1204 exist after each headings's drawers." 1144exist after each headings's drawers."
1205 (interactive "P") 1145 (interactive "P")
1206 (org-map-entries (lambda () 1146 (org-map-entries (lambda ()
1207 (org-with-wide-buffer 1147 (org-with-wide-buffer
1208 ;; `org-map-entries' narrows the buffer, which prevents us 1148 ;; `org-map-entries' narrows the buffer, which prevents us
1209 ;; from seeing newlines before the current heading, so we 1149 ;; from seeing newlines before the current heading, so we
1210 ;; do this part widened. 1150 ;; do this part widened.
1211 (while (not (looking-back "\n\n" nil)) 1151 (while (not (looking-back "\n\n" nil))
1212 ;; Insert blank lines before heading. 1152 ;; Insert blank lines before heading.
1213 (insert "\n"))) 1153 (insert "\n")))
1214 (let ((end (org-entry-end-position))) 1154 (let ((end (org-entry-end-position)))
1215 ;; Insert blank lines before entry content 1155 ;; Insert blank lines before entry content
1216 (forward-line) 1156 (forward-line)
1217 (while (and (org-at-planning-p) 1157 (while (and (org-at-planning-p)
1218 (< (point) (point-max))) 1158 (< (point) (point-max)))
1219 ;; Skip planning lines 1159 ;; Skip planning lines
1220 (forward-line)) 1160 (forward-line))
1221 (while (re-search-forward org-drawer-regexp end t) 1161 (while (re-search-forward org-drawer-regexp end t)
1222 ;; Skip drawers. You might think that `org-at-drawer-p' 1162 ;; Skip drawers. You might think that `org-at-drawer-p'
1223 ;; would suffice, but for some reason it doesn't work 1163 ;; would suffice, but for some reason it doesn't work
1224 ;; correctly when operating on hidden text. This 1164 ;; correctly when operating on hidden text. This
1225 ;; works, taken from `org-agenda-get-some-entry-text'. 1165 ;; works, taken from `org-agenda-get-some-entry-text'.
1226 (re-search-forward "^[ \t]*:END:.*\n?" end t) 1166 (re-search-forward "^[ \t]*:END:.*\n?" end t)
1227 (goto-char (match-end 0))) 1167 (goto-char (match-end 0)))
1228 (unless (or (= (point) (point-max)) 1168 (unless (or (= (point) (point-max))
1229 (org-at-heading-p) 1169 (org-at-heading-p)
1230 (looking-at-p "\n")) 1170 (looking-at-p "\n"))
1231 (insert "\n")))) 1171 (insert "\n"))))
1232 t (if prefix 1172 t (if prefix
1233 nil 1173 nil
1234 'tree))) 1174 'tree)))
1235#+end_src 1175#+END_SRC
1236 1176
1237**** Add a before-save-hook 1177**** Add a before-save-hook
1238 1178
1239#+begin_src emacs-lisp 1179#+BEGIN_SRC emacs-lisp
1240 (defun cribbed/org-mode-fix-blank-lines () 1180(defun cribbed/org-mode-fix-blank-lines ()
1241 (when (eq major-mode 'org-mode) 1181 (when (eq major-mode 'org-mode)
1242 (let ((current-prefix-arg 4)) ; Emulate C-u 1182 (let ((current-prefix-arg 4)) ; Emulate C-u
1243 (call-interactively 'unpackaged/org-fix-blank-lines)))) 1183 (call-interactively 'unpackaged/org-fix-blank-lines))))
1244 1184
1245 (add-hook 'before-save-hook #'cribbed/org-mode-fix-blank-lines) 1185(add-hook 'before-save-hook #'cribbed/org-mode-fix-blank-lines)
1246#+end_src 1186#+END_SRC
1247
1248** Elpher
1249
1250#+begin_src emacs-lisp
1251 (straight-use-package '(elpher
1252 :repo "git://thelambdalab.xyz/elpher.git"
1253 :branch "patch_multiple_buffers"))
1254
1255 (cuss elpher-ipv4-always t)
1256
1257 (custom-set-faces
1258 `(elpher-gemini-heading1
1259 ((t (:inherit (modus-theme-heading1)))))
1260 `(elpher-gemini-heading2
1261 ((t (:inherit (modus-theme-heading2)))))
1262 `(elpher-gemini-heading3
1263 ((t (:inherit (modus-theme-heading3))))))
1264
1265 (defun elpher:eww-browse-url (original url &optional new-window)
1266 "Handle gemini/gopher links with eww."
1267 (cond ((string-match-p "\\`\\(gemini\\|gopher\\)://" url)
1268 (require 'elpher)
1269 (elpher-go url))
1270 (t (funcall original url new-window))))
1271
1272 (advice-add 'eww-browse-url :around 'elpher:eww-browse-url)
1273
1274 (unless (fboundp 'elpher-bookmarks)
1275 (autoload #'elpher-bookmarks "elpher" nil t))
1276
1277 (define-key acdw/map "e" #'elpher-bookmarks)
1278
1279 (with-eval-after-load 'elpher
1280 (dolist (key '(("n" . elpher-next-link)
1281 ("p" . elpher-prev-link)
1282 ("o" . elpher-follow-current-link)
1283 ("G" . elpher-go-current)))
1284 (define-key elpher-mode-map (car key) (cdr key))))
1285
1286 (add-hook 'elpher-mode-hook #'visual-fill-column-mode)
1287#+end_src
1288
1289*** Gemini mode
1290
1291#+begin_src emacs-lisp
1292 (straight-use-package
1293 '(gemini-mode
1294 :repo "https://git.carcosa.net/jmcbray/gemini.el.git"))
1295
1296 (add-to-list 'auto-mode-alist
1297 '("\\.\\(gemini\\|gmi\\)\\'" . gemini-mode))
1298
1299 (defun acdw/setup-gemini-mode ()
1300 (visual-fill-column-mode +1)
1301 (variable-pitch-mode -1))
1302
1303 (add-hook 'gemini-mode-hook #'acdw/setup-gemini-mode)
1304#+end_src
1305
1306*** Gemini write
1307
1308#+begin_src emacs-lisp
1309 (straight-use-package
1310 '(gemini-write
1311 :repo "https://alexschroeder.ch/cgit/gemini-write"))
1312#+end_src
1313 1187
1314*** Ox-gemini 1188** Git
1315 1189
1316#+begin_src emacs-lisp 1190#+begin_src emacs-lisp
1317 (straight-use-package 1191 (straight-use-package 'magit)
1318 '(ox-gemini
1319 :repo "https://git.sr.ht/~abrahms/ox-gemini"
1320 :branch "main"))
1321#+end_src
1322
1323** Pastebin
1324
1325#+begin_src emacs-lisp
1326 (straight-use-package '0x0)
1327
1328 (cuss 0x0-default-service 'ttm)
1329#+end_src
1330
1331** RSS
1332
1333#+begin_src emacs-lisp
1334 (cuss newsticker-url-list
1335 ;; LABEL URL [START-TIME] [INERVAL] [WGET-ARGUMENTS]
1336 '(("wsinatra" "http://lambdacreate.com/static/feed.rss")
1337 ("elioat" "https://eli.li/feed.rss")
1338 ("ACDW" "https://www.acdw.net/atom.xml")
1339 ("june" "https://text.causal.agency/feed.atom")
1340 ("kylie - notes" "https://www.somas.is/notes.atom")
1341 ("kylie - rhizome" "https://www.somas.is/rhizome.atom")
1342 ("brennan" "https://p1k3.com/all.xml")
1343 ("Planet Emacs" "https://planet.emacslife.com/atom.xml")
1344 ("nullprogram, Chris Wellons" "https://nullprogram.com/feed/")
1345 ("Malleable Systems" "https://malleable.systems/blog/index.xml"))
1346 )
1347
1348 (add-hook 'newsticker-treeview-item-mode-hook #'visual-fill-column-mode)
1349#+end_src
1350
1351** Web browsing
1352
1353*** Open youtube links in mpv
1354
1355from [[https://karthinks.com/software/more-batteries-included-with-emacs/#regexp-builder--m-x-re-builder][karthinks]].
1356
1357#+begin_src emacs-lisp
1358 (require 'browse-url)
1359
1360 (when (executable-find "mpv")
1361 (defun browse-url-mpv (url &optional single)
1362 (start-process "mpv" nil (if single "mpv" "umpv")
1363 (shell-quote-wildcard-pattern url)))
1364
1365 (defun browse-url-at-point-mpv (&optional single)
1366 "Open a link in mpv."
1367 (interactive "P")
1368 (let ((browse-url-browser-function
1369 (if single
1370 (lambda
1371 (url &optional _new-window)
1372 (browse-url-mpv url t))
1373 #'browse-url-mpv)))
1374 (browse-url-at-point)))
1375
1376 (cuss browse-url-browser-function
1377 '(("https?:\\/\\/www\\.youtu\\.*be." . browse-url-mpv)
1378 ("." . browse-url-generic))))
1379#+end_src
1380
1381** Reading e-books
1382
1383#+begin_src emacs-lisp
1384 (straight-use-package 'nov)
1385
1386 (add-to-list 'auto-mode-alist '("\\.epub\\'" . nov-mode))
1387
1388 (defun acdw/setup-nov-mode ()
1389 (visual-line-mode +1)
1390 (visual-fill-column-mode +1)
1391 (variable-pitch-mode +1)
1392 (setq cursor-type nil))
1393
1394 (cuss nov-text-width t)
1395
1396 (add-hook 'nov-mode-hook #'acdw/setup-nov-mode)
1397#+end_src
1398
1399** Eshell
1400
1401#+begin_src emacs-lisp
1402 (when (executable-find "bash")
1403 (straight-use-package 'bash-completion))
1404
1405 (when (executable-find "fish")
1406 (straight-use-package 'fish-completion)
1407 (require 'fish-completion)
1408 (cuss fish-completion-fallback-on-bash-p (executable-find "bash"))
1409 (global-fish-completion-mode +1)
1410 1192
1411 (straight-use-package 'fish-mode) 1193 (define-key acdw/map "g" #'magit-status)
1412 (add-to-list 'auto-mode-alist '("\\.fish\\'" . fish-mode)))
1413#+end_src 1194#+end_src
1414 1195
1415* Appendices 1196* Appendices