From 2aabdb28e5052f558fdfc6da22dc5ffc9ea68754 Mon Sep 17 00:00:00 2001 From: Howard Abrams Date: Wed, 10 Jul 2024 22:08:10 -0700 Subject: [PATCH] More literate programming function cleanup --- README.org | 2 ++ ha-org-literate.org | 51 ++++++++++++++++++--------------------------- 2 files changed, 22 insertions(+), 31 deletions(-) diff --git a/README.org b/README.org index e0a51da..bdcdd61 100644 --- a/README.org +++ b/README.org @@ -29,6 +29,7 @@ To create [[file:~/.emacs.d/init.el][~/.emacs.d/init.el]] which starts the proce - [[file:bootstrap.org][Bootstrap]] :: configures =straight= and loads basic libraries the rest of the code depends on. It then loads the following files in order. - [[file:ha-config.org][Configuration]] :: contains /most/ of my configuration, setting up my sequence key menus, evil, etc. - [[file:ha-evil.org][Evilness]] :: configuration for using VI, er, ~vim~ keybindings in Emacs. + - [[file:ha-general.org][Leader]] :: using the ~SPC~ to kick off a hierarchal order of functions. - [[file:ha-display.org][GUI Display]] :: sets up the visual aspects of an Emacs GUI, including themes and fonts. - [[file:ha-dashboard.org][Dashboard]] :: sets up initial window layout of the =main= project with a dashboard. - [[file:ha-data.org][Data]] :: functions for dealing with a buffer-full of data. @@ -36,6 +37,7 @@ To create [[file:~/.emacs.d/init.el][~/.emacs.d/init.el]] which starts the proce ** Org Mode Configuration - [[file:ha-org.org][Initial Org Configuration]] :: configures the basics for org-mode formatted files. Specific features come from their own files. - [[file:ha-org-word-processor.org][Word Processing]] :: attempts to make Org files /visually/ look like a word processor, including turning off the colors for headers, and instead increasing their size. + - [[file:ha-org-literate.org][Literate Programming]] :: functions to support literate programming techniques. I use this most prevalently with this Emacs configuration. - [[file:ha-org-clipboard.org][Clipboard]] :: automatically converting HTML from a clipboard into Org-formatted content. - [[file:ha-org-journaling.org][Journaling]] :: for writing journal entries and tasks. - [[file:ha-org-publishing.org][Publishing]] :: code for publishing my website, [[http://howardism.org][www.howardism.org]]. diff --git a/ha-org-literate.org b/ha-org-literate.org index be7a114..1aaf4ca 100644 --- a/ha-org-literate.org +++ b/ha-org-literate.org @@ -2,7 +2,7 @@ #+author: Howard Abrams #+date: 2024-07-07 #+filetags: emacs hamacs -#+lastmod: [2024-07-07 Sun] +#+lastmod: [2024-07-16 Tue] A literate programming file for literate programming in Emacs Org Files. @@ -31,7 +31,6 @@ A literate programming file for literate programming in Emacs Org Files. ;; ;;; Code: #+end_src - * Introduction I do a lot of /literate programming/ using capabilities found in the Org project. Over the years, I’ve smoothed some of the rough edges by writing supporting functions, collected below. @@ -63,30 +62,6 @@ For instance, the following function can be used to quickly select a source code I need to take advantage of this feature more. * Evaluating Code Hitting ~C-c C-c~ in a source code block /evaluates/ the code. Simple, sure, but the following enhancements make this more accessible. -** Syncing Tangled Code Automatically -Any file can set [[https://emacsdocs.org/docs/emacs/File-Variables][file-local Emacs variables]] when a file is loaded, but we can also run Emacs functions with the =eval:= sequence. If you place the following code at the bottom of your Org file, saving the buffer automatically tangles it: - -#+begin_src org - # Local Variables: - # eval: (add-hook 'after-save-hook #'org-babel-tangle t t) - # End: -#+end_src - -If you set the =comments= header argument to =link=, you can actually make direct changes to your tangled code to have them update your original literate org file. For instance, add: - -#+begin_src org -#+PROPERTY: header-args: :tangle yes :comments link -#+end_src - -See also the [[https://gitlab.com/mtekman/org-tanglesync.el][org-tanglesync]] project for putting a bit of controls around this feature. - -Another idea is to call =org-babel-execute-buffer= when a file is loaded to automatically evaluate all blocks: - -#+begin_src org -# eval: (org-babel-execute-buffer) -#+end_src - -Personally, I find that I would like to call this function manually instead of automatically. ** Evaluating a Block At times I would like to jump to a particular block, evaluate the code, and jump back. This seems like a great job for the [[https://github.com/abo-abo/avy][avy project]]. The =avy-jump= function takes a regular expression of text /in the frame/ (which means you can specify text in other windows), and highlights each match. Normally, selecting a match moves the cursor to that match, the =avy-jump= accepts a function to execute instead: @@ -104,12 +79,14 @@ At times I would like to jump to a particular block, evaluate the code, and jump the point." (interactive) (avy-jump (rx "#+begin_src ") - :action - 'org-babel-execute-src-block-at-point)) + :action 'org-babel-execute-src-block-at-point)) #+end_src +In this case, =avy-org-babel-execute-src-block= highlights all /visible blocks/ on the frame, with a letter on each. Selecting the letter, evaluates that block without moving the cursor. + +TODO Screenshot of multiple highlighted blocks. ** Evaluating a Section -A trick to =org-babel-tangle=, is that it tangles /what is available/, that is, it will only tangle code blocks that are visible after narrowing to the current org section. +A trick to =org-babel-tangle=, is that it tangles /what is shown/, that is, it will only tangle code blocks that are visible after narrowing to the current org section. This means, we can call =org-narrow-to-subtree= to temporary hide everything in the org file except the current heading, evaluate all blocks in the “now visible” buffer, and then widen: #+begin_src emacs-lisp :results silent (defun org-babel-execute-subtree () @@ -121,6 +98,8 @@ A trick to =org-babel-tangle=, is that it tangles /what is available/, that is, (widen))) #+end_src ** Editing a Block +Why navigate to a block, just to focus on that block in a dedicated buffer, when we can take advantage of the =avy-jump= and edit any visible block? + #+begin_src emacs-lisp (defun org-babel-edit-src-block-at-point (&optional point) "Call `org-babel-execute-src-block' at POINT." @@ -140,16 +119,19 @@ A trick to =org-babel-tangle=, is that it tangles /what is available/, that is, #+end_src * Finding Code -One of the issues with literate programming is using the same interface for moving around code when the source code is in org files. +One of the issues with literate programming is not being able to use the same interface for moving around code when the source code is in org files. ** Searching by Function Name I wrote a function, =ha-org-code-block-jump= to use the standard =xref= interface to jump to a function definition /in the literate org file/. Since the code is specific to /Emacs Lisp/ (the bulk of my literate programming code is in Lisp), I’m leaving it in my [[file:ha-programming-elisp.org::*Goto Definitions][programming-elisp]] configuration. TODO: Do all the =xref-= functions for search an collection of org files, not just definition. ** Searching by Header +:PROPERTIES: +:ID: de536693-f0b0-48d0-9b13-c29d7a8caa62 +:END: As large literate programming projects grow, I refine, re-organize and refactor content. I don’t always remember where I put particular code. For instance, in my Emacs configuration, did I configure /eww/, in [[file:ha-config.org][my default config]] file, or did I move it somewhere? Originally, after loading the file, I could issue a call to [[file:ha-general.org::*Consult][consult-imenu]] to get to the right location, but that assumes I have the correct file loaded. -The following section shows some code I wrote one evening, to use the fuzzy matching features of [[file:ha-config.org::*Orderless][Orderless]], to choose a headline in any of my Org files in a project, and then load that file and jump to that headline. The interface is =ha-hamacs-edit-file-heading=, and the supporting functions begin with =ha-hamacs-edit-=: +The following section shows some code to use the fuzzy matching features of [[file:ha-config.org::*Orderless][Orderless]], to choose a headline in any of my Org files in a project, and then load that file and jump to that headline. The interface is =ha-hamacs-edit-file-heading=, and the supporting functions begin with =ha-hamacs-edit-=: #+begin_src emacs-lisp (defun ha-hamacs-edit-file-heading (&optional project-root) @@ -248,6 +230,13 @@ Not every header should be a destination, as many of my org files have duplicate "Regular expression matching headers to purge.") #+end_src +Note: This variable should be set in the =.dir-locals.el= for a particular project, as in: + +#+begin_src emacs-lisp :tangle no +((org-mode . ((ha-hamacs-edit-flush-headers . + "\\*[[:space:]]+\\(?:Background\\|Summary\\)")))) +#+end_src + And this next function is callable by the filter function, it uses the regular expression and returns true (well, non-nil) if the line entry given, =rg-input=, should be removed: #+begin_src emacs-lisp