diff options
author | Case Duckworth | 2020-11-24 08:33:37 -0600 |
---|---|---|
committer | Case Duckworth | 2020-11-24 08:33:37 -0600 |
commit | 6a2a0d46e63c0198d9e1164e5a74e776341b4375 (patch) | |
tree | 6fdbffb1bb94661c5ea980cb8eefba64d1da9350 | |
parent | Various better-defaults-style changes (diff) | |
download | emacs-6a2a0d46e63c0198d9e1164e5a74e776341b4375.tar.gz emacs-6a2a0d46e63c0198d9e1164e5a74e776341b4375.zip |
Ensure blank lines in Org Mode
-rw-r--r-- | config.org | 155 |
1 files changed, 154 insertions, 1 deletions
diff --git a/config.org b/config.org index c90e586..d8f0325 100644 --- a/config.org +++ b/config.org | |||
@@ -698,9 +698,162 @@ I'm going to be honest -- most of this is a stab in the dark. | |||
698 | (org-pretty-entities t)) | 698 | (org-pretty-entities t)) |
699 | #+end_src | 699 | #+end_src |
700 | 700 | ||
701 | *** Ensure blank lines between headings and before contents | ||
702 | |||
703 | from [[https://github.com/alphapapa/unpackaged.el#ensure-blank-lines-between-headings-and-before-contents][unpackaged.el]] | ||
704 | |||
705 | #+begin_src emacs-lisp | ||
706 | ;;;###autoload | ||
707 | (defun unpackaged/org-fix-blank-lines (&optional prefix) | ||
708 | "Ensure that blank lines exist between headings and between | ||
709 | headings and their contents. With prefix, operate on whole | ||
710 | buffer. Ensures that blank lines exist after each headings's | ||
711 | drawers." | ||
712 | (interactive "P") | ||
713 | (org-map-entries | ||
714 | (lambda () | ||
715 | (org-with-wide-buffer | ||
716 | ;; `org-map-entries' narrows the buffer, which prevents us | ||
717 | ;; from seeing newlines before the current heading, so we | ||
718 | ;; do this part widened. | ||
719 | (while (not (looking-back "\n\n" nil)) | ||
720 | ;; Insert blank lines before heading. | ||
721 | (insert "\n"))) | ||
722 | (let ((end (org-entry-end-position))) | ||
723 | ;; Insert blank lines before entry content. | ||
724 | (forward-line) | ||
725 | (while (and (org-at-planning-p) | ||
726 | (< (point) (point-max))) | ||
727 | ;; Skip planning lines | ||
728 | (forward-line)) | ||
729 | (while (re-search-forward org-drawer-regexp end t) | ||
730 | ;; Skip drawers. You might think that | ||
731 | ;; `org-at-drawer-p' would suffice, but for some reason | ||
732 | ;; it doesn't work correctly when operating on hidden | ||
733 | ;; text. This works, taken from | ||
734 | ;; `org-agenda-get-some-entry-text'. | ||
735 | (re-search-forward "^[ \t]*:END:.*\n?" end t) | ||
736 | (goto-char (match-end 0))) | ||
737 | (unless (or (= (point) (point-max)) | ||
738 | (org-at-heading-p) | ||
739 | (looking-at-p "\n")) | ||
740 | (insert "\n")))) | ||
741 | t (if prefix | ||
742 | nil | ||
743 | 'tree))) | ||
744 | #+end_src | ||
745 | |||
746 | *** ~org-return-dwim~ | ||
747 | |||
748 | from [[https://github.com/alphapapa/unpackaged.el#org-return-dwim][unpackaged.el]] | ||
749 | |||
750 | #+begin_src emacs-lisp | ||
751 | (defun unpackaged/org-element-descendant-of (type element) | ||
752 | "Return non-nil if ELEMENT is a descendant of TYPE. | ||
753 | TYPE should be an element type, like `item' or `paragraph'. | ||
754 | ELEMENT should be a list like that returned by | ||
755 | `org-element-context'." | ||
756 | ;; MAYBE: Use `org-element-lineage'. | ||
757 | (when-let* ((parent (org-element-property :parent element))) | ||
758 | (or (eq type (car parent)) | ||
759 | (unpackaged/org-element-descendant-of type parent)))) | ||
760 | |||
761 | ;;;###autoload | ||
762 | (defun unpackaged/org-return-dwim (&optional default) | ||
763 | "A helpful replacement for `org-return'. With prefix, call `org-return'. | ||
764 | |||
765 | On headings, move point to position after entry content. In | ||
766 | lists, insert a new item or end the list, with checkbox if | ||
767 | appropriate. In tables, insert a new row or end the table." | ||
768 | ;; Inspired by John Kitchin: http://kitchingroup.cheme.cmu.edu/blog/2017/04/09/A-better-return-in-org-mode/ | ||
769 | (interactive "P") | ||
770 | (if default | ||
771 | (org-return) | ||
772 | (cond | ||
773 | ;; Act depending on context around point. | ||
774 | |||
775 | ;; NOTE: I prefer RET to not follow links, but by uncommenting this block, | ||
776 | ;; links will be followed. | ||
777 | |||
778 | ;; ((eq 'link (car (org-element-context))) | ||
779 | ;; ;; Link: Open it. | ||
780 | ;; (org-open-at-point-global)) | ||
781 | |||
782 | ((org-at-heading-p) | ||
783 | ;; Heading: Move to position after entry content. | ||
784 | ;; NOTE: This is probably the most interesting feature of this function. | ||
785 | (let ((heading-start (org-entry-beginning-position))) | ||
786 | (goto-char (org-entry-end-position)) | ||
787 | (cond ((and (org-at-heading-p) | ||
788 | (= heading-start (org-entry-beginning-position))) | ||
789 | ;; Entry ends on its heading; add newline after | ||
790 | (end-of-line) | ||
791 | (insert "\n\n")) | ||
792 | (t | ||
793 | ;; Entry ends after its heading; back up | ||
794 | (forward-line -1) | ||
795 | (end-of-line) | ||
796 | (when (org-at-heading-p) | ||
797 | ;; At the same heading | ||
798 | (forward-line) | ||
799 | (insert "\n") | ||
800 | (forward-line -1)) | ||
801 | ;; FIXME: looking-back is supposed to be called with more arguments. | ||
802 | (while (not (looking-back (rx (repeat 3 (seq (optional blank) "\n"))))) | ||
803 | (insert "\n")) | ||
804 | (forward-line -1))))) | ||
805 | |||
806 | ((org-at-item-checkbox-p) | ||
807 | ;; Checkbox: Insert new item with checkbox. | ||
808 | (org-insert-todo-heading nil)) | ||
809 | |||
810 | ((org-in-item-p) | ||
811 | ;; Plain list. Yes, this gets a little complicated... | ||
812 | (let ((context (org-element-context))) | ||
813 | (if (or (eq 'plain-list (car context)) ; First item in list | ||
814 | (and (eq 'item (car context)) | ||
815 | (not (eq (org-element-property :contents-begin context) | ||
816 | (org-element-property :contents-end context)))) | ||
817 | (unpackaged/org-element-descendant-of 'item context)) ; Element in list item, e.g. a link | ||
818 | ;; Non-empty item: Add new item. | ||
819 | (org-insert-item) | ||
820 | ;; Empty item: Close the list. | ||
821 | ;; TODO: Do this with org functions rather than operating on the text. Can't seem to find the right function. | ||
822 | (delete-region (line-beginning-position) (line-end-position)) | ||
823 | (insert "\n")))) | ||
824 | |||
825 | ((when (fboundp 'org-inlinetask-in-task-p) | ||
826 | (org-inlinetask-in-task-p)) | ||
827 | ;; Inline task: Don't insert a new heading. | ||
828 | (org-return)) | ||
829 | |||
830 | ((org-at-table-p) | ||
831 | (cond ((save-excursion | ||
832 | (beginning-of-line) | ||
833 | ;; See `org-table-next-field'. | ||
834 | (cl-loop with end = (line-end-position) | ||
835 | for cell = (org-element-table-cell-parser) | ||
836 | always (equal (org-element-property :contents-begin cell) | ||
837 | (org-element-property :contents-end cell)) | ||
838 | while (re-search-forward "|" end t))) | ||
839 | ;; Empty row: end the table. | ||
840 | (delete-region (line-beginning-position) (line-end-position)) | ||
841 | (org-return)) | ||
842 | (t | ||
843 | ;; Non-empty row: call `org-return'. | ||
844 | (org-return)))) | ||
845 | (t | ||
846 | ;; All other cases: call `org-return'. | ||
847 | (org-return))))) | ||
848 | |||
849 | (bind-key "RET" #'unpackaged/org-return-dwim 'org-mode-map) | ||
850 | #+end_src | ||
851 | |||
701 | * Coding | 852 | * Coding |
702 | 853 | ||
703 | ** Indenting | 854 | ** Formatting |
855 | |||
856 | *** Indenting | ||
704 | 857 | ||
705 | #+begin_src emacs-lisp | 858 | #+begin_src emacs-lisp |
706 | (use-package aggressive-indent | 859 | (use-package aggressive-indent |