Compare commits

..

3 commits

Author SHA1 Message Date
Howard Abrams
e5891170a0 Fix minor bug when quitting presentations 2024-11-16 10:43:10 -08:00
Howard Abrams
6ea135ca41 Move searching for noweb references into the Literate section 2024-11-16 10:42:43 -08:00
Howard Abrams
77fd8f3bcb Adding a Session REPL to the Literate Mode 2024-11-05 19:48:38 -08:00
3 changed files with 54 additions and 43 deletions

View file

@ -2,7 +2,7 @@
#+author: Howard X. Abrams #+author: Howard X. Abrams
#+date: 2024-10-18 #+date: 2024-10-18
#+filetags: emacs hamacs #+filetags: emacs hamacs
#+lastmod: [2024-11-05 Tue] #+lastmod: [2024-11-09 Sat]
A literate programming file for creating and running demonstrations A literate programming file for creating and running demonstrations
@ -199,7 +199,7 @@ Ive used [[https://github.com/takaxp/org-tree-slide][org-tree-slide]] for yea
"C" #'ha-demo-toggle-cursor "C" #'ha-demo-toggle-cursor
"n" #'org-tree-slide-move-next-tree "n" #'org-tree-slide-move-next-tree
"N" #'org-tree-slide-move-previous-tree "N" #'org-tree-slide-move-previous-tree
"Q" (lambda () (interactive) (org-slide-tree-mode -1))) "Q" (lambda () (interactive) (org-tree-slide-mode -1)))
:hook :hook
((org-tree-slide-play . ha-org-tree-slide-start) ((org-tree-slide-play . ha-org-tree-slide-start)
@ -458,9 +458,10 @@ Displaying a File with:
All options? Should I use Common Lisps =cl-defun= for the keyword parameters? All options? Should I use Common Lisps =cl-defun= for the keyword parameters?
#+BEGIN_SRC emacs-lisp :tangle no #+BEGIN_SRC emacs-lisp
(cl-defun ha-demo-show-file (filename &key position size modeline (cl-defun ha-demo-show-file (filename &key position size modeline
line heading shift commands) line heading shift cursor
commands)
"Show a file, FILENAME, in a buffer based on keyed parameters. "Show a file, FILENAME, in a buffer based on keyed parameters.
POSITION can be 'full 'right or 'below and positions the window. POSITION can be 'full 'right or 'below and positions the window.
SIZE is an integer for the font size based on the default size. SIZE is an integer for the font size based on the default size.
@ -491,6 +492,11 @@ All options? Should I use Common Lisps =cl-defun= for the keyword parameters?
(goto-char (point-min)) (goto-char (point-min))
(when cursor
(if (or (eq cursor 'yes) (eq cursor 'show))
(ha-demo-show-cursor)
(ha-demo-hide-cursor)))
;; Step 3: Increase the font size ;; Step 3: Increase the font size
(when size (when size
(text-scale-set size)) (text-scale-set size))

View file

@ -2,7 +2,7 @@
#+author: Howard Abrams #+author: Howard Abrams
#+date: 2024-07-07 #+date: 2024-07-07
#+filetags: emacs hamacs #+filetags: emacs hamacs
#+lastmod: [2024-10-29 Tue] #+lastmod: [2024-11-11 Mon]
A literate programming file for literate programming in Emacs Org Files. A literate programming file for literate programming in Emacs Org Files.
@ -311,7 +311,7 @@ This magical incantation connects our function to Xref with an =org= backend:
This helper function does the work of calling =ripgrep=, parsing its output, and filtering only the /matches/ line. Yes, an interesting feature of =rg= is that it spits out a /sequence/ of JSON-formatted text, so we can use =seq-filter= to grab lines that represent a match, and =seq-map= to “do the work”. Since we have a couple of ways of /doing the work/, we pass in a function, =processor=, which, along with transforming the results, could spit out =nulls=, so the =seq-filter= with the =identity= function eliminates that. This helper function does the work of calling =ripgrep=, parsing its output, and filtering only the /matches/ line. Yes, an interesting feature of =rg= is that it spits out a /sequence/ of JSON-formatted text, so we can use =seq-filter= to grab lines that represent a match, and =seq-map= to “do the work”. Since we have a couple of ways of /doing the work/, we pass in a function, =processor=, which, along with transforming the results, could spit out =nulls=, so the =seq-filter= with the =identity= function eliminates that.
#+begin_src emacs-lisp #+begin_src emacs-lisp
(defun ha-literate--ripgrep-matches (processor regex) (defun ha-literate--ripgrep-matches (processor regex &optional symb)
"Return list of running PROCESSOR of `rg' matches from REGEX. "Return list of running PROCESSOR of `rg' matches from REGEX.
PROCESSOR is called with an assoc-list of the JSON output from PROCESSOR is called with an assoc-list of the JSON output from
the call to ripgrep." the call to ripgrep."
@ -321,7 +321,9 @@ This helper function does the work of calling =ripgrep=, parsing its output, and
(search-str (rxt-elisp-to-pcre regex)) (search-str (rxt-elisp-to-pcre regex))
(command (format "rg --json --type org '%s'" search-str))) (command (format "rg --json --type org '%s'" search-str)))
(message "Literate xref Calling: %s" command) ;; (message "Literate xref Calling: %s" command)
(message "Searching `%s' %s..." default-directory
(if symb (format "for `%s' " symb) ""))
(thread-last command (thread-last command
(shell-command-to-list) (shell-command-to-list)
(seq-map 'ha-literate--parse-rg-line) (seq-map 'ha-literate--parse-rg-line)
@ -392,7 +394,8 @@ As mentioned above, lets assume we can use =ripgrep= to search for /definiti
The location is based on a regular expression starting with The location is based on a regular expression starting with
`(defxyz SYMB' where this can be `defun' or `defvar', etc." `(defxyz SYMB' where this can be `defun' or `defvar', etc."
(ha-literate--ripgrep-matches 'ha-literate--process-rg-line (ha-literate--ripgrep-matches 'ha-literate--process-rg-line
(ha-literate-definition-rx symb))) (ha-literate-definition-rx symb)
symb))
#+end_src #+end_src
The work of processing a match for the =ha-literate-definition= function. It calls =xref-make= to create an object for the Xref system. This takes two parameters, the text and the location. We create a location with =xref-make-file-location=. The work of processing a match for the =ha-literate-definition= function. It calls =xref-make= to create an object for the Xref system. This takes two parameters, the text and the location. We create a location with =xref-make-file-location=.
@ -574,11 +577,45 @@ To finish the connections, we need to create a /hook/ that I only allow to turn
At this point, we can jump to functions and variables that I define in my org file, or even references to standard symbols like =xref-make= or =xref-backend-functions=. At this point, we can jump to functions and variables that I define in my org file, or even references to standard symbols like =xref-make= or =xref-backend-functions=.
I can jump around my literate code as if they were =.el= files. I may want to think about expanding the definitions to figure out the language of the destination. I can jump around my literate code as if they were =.el= files. I may want to think about expanding the definitions to figure out the language of the destination.
** Noweb References
A noweb definition, e.g. =<<something-something>>= should /jump/ to the =#name= definition.
Since [[https://github.com/BurntSushi/ripgrep][ripgrep]] is pretty fast, Ill call it instead of attempting to build a [[https://stackoverflow.com/questions/41933837/understanding-the-ctags-file-format][CTAGS]] table. Oooh, the =rg= takes a =—json= option, which makes it easier to parse.
#+begin_src emacs-lisp :noweb no
(defun ha-org-noweb-block-jump (str pos)
"Go to a literate org file containing a symbol, STR.
The POS is ignored."
;; Sometimes I wrap a function name in `=' characters, and these should be removed:
(when (string-match (rx "<<" (group (one-or-more any)) ">>") str)
(setq str (match-string 1 str)))
(ignore-errors
(let* ((default-directory (project-root (project-current)))
(command (format "rg --ignore-case --json '#\\+name: +%s' *.org" str))
(results (thread-last command
shell-command-to-list
second
json-parse-string))
(file (thread-last results
(gethash "data")
(gethash "path")
(gethash "text")))
(line (thread-last results
(gethash "data")
(gethash "line_number"))))
(find-file file)
(goto-line line))))
(when (fboundp 'evil-goto-definition-functions)
(add-to-list 'evil-goto-definition-functions 'ha-org-noweb-block-jump))
#+end_src
** Searching by Header ** Searching by Header
:PROPERTIES: :PROPERTIES:
:ID: de536693-f0b0-48d0-9b13-c29d7a8caa62 :ID: de536693-f0b0-48d0-9b13-c29d7a8caa62
:END: :END:
As large literate programming projects grow, I refine, re-organize and refactor content. I dont 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. As large literate programming projects grow, I refine, re-organize and refactor content. I dont 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]] or [[help:org-consult-heading][org-consult-heading]] to get to the right location, but that assumes I have the correct file loaded.
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-=: 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-=:
@ -872,6 +909,7 @@ With a lovely collection of functions, we need to have a way to easily call them
("T" org-babel-detangle "from File")) ("T" org-babel-detangle "from File"))
"Misc" "Misc"
(("e" avy-org-babel-edit-src-block "Edit Block ") (("e" avy-org-babel-edit-src-block "Edit Block ")
("s" org-babel-pop-to-session-maybe "Session REPL")
("v" ha-org-babel-tangle-visit-file "Visit Tangled")))) ("v" ha-org-babel-tangle-visit-file "Visit Tangled"))))
#+end_src #+end_src

View file

@ -3,7 +3,7 @@
#+date: 2020-09-18 #+date: 2020-09-18
#+tags: emacs org #+tags: emacs org
#+startup: inlineimages #+startup: inlineimages
#+lastmod: [2024-10-30 Wed] #+lastmod: [2024-11-09 Sat]
A literate programming file for configuring org-mode and those files. A literate programming file for configuring org-mode and those files.
@ -395,39 +395,6 @@ And turn on ALL the languages:
(plantuml . t))) (plantuml . t)))
#+end_src #+end_src
*** Searching Literate Files
A noweb definition, e.g. =<<something-something>>= could /jump/ to the =#name= definition.
Since [[https://github.com/BurntSushi/ripgrep][ripgrep]] is pretty fast, Ill call it instead of attempting to build a [[https://stackoverflow.com/questions/41933837/understanding-the-ctags-file-format][CTAGS]] table. Oooh, the =rg= takes a =—json= option, which makes it easier to parse.
#+begin_src emacs-lisp :noweb no
(defun ha-org-noweb-block-jump (str pos)
"Go to a literate org file containing a symbol, STR.
The POS is ignored."
;; Sometimes I wrap a function name in `=' characters, and these should be removed:
(when (string-match (rx "<<" (group (one-or-more any)) ">>") str)
(setq str (match-string 1 str)))
(ignore-errors
(let* ((default-directory (project-root (project-current)))
(command (format "rg --ignore-case --json '#\\+name: +%s' *.org" str))
(results (thread-last command
shell-command-to-list
second
json-parse-string))
(file (thread-last results
(gethash "data")
(gethash "path")
(gethash "text")))
(line (thread-last results
(gethash "data")
(gethash "line_number"))))
(find-file file)
(goto-line line))))
(when (fboundp 'evil-goto-definition-functions)
(add-to-list 'evil-goto-definition-functions 'ha-org-noweb-block-jump))
#+end_src
*** REST Web Services *** REST Web Services
Emacs has two ways to query and investigate REST-oriented web services. The [[https://github.com/zweifisch/ob-http][ob-http]] adds HTTP calls to standard org blocks. Emacs has two ways to query and investigate REST-oriented web services. The [[https://github.com/zweifisch/ob-http][ob-http]] adds HTTP calls to standard org blocks.
#+begin_src emacs-lisp #+begin_src emacs-lisp