scimax-ob-line-numbers/scimax-ob-line-numbers.el

78 lines
3.0 KiB
EmacsLisp

;;; scimax-ob-line-numbers.el --- Description -*- lexical-binding: t; -*-
;;
;; Copyright (C) 2025 Ionut Adrian Ciolan
;;
;; Author: https://github.com/jkitchin/scimax/
;; Maintainer: Ionut Adrian Ciolan <iadrian@ciolan.net>
;; Created: June 29, 2025
;; Modified: June 29, 2025
;; Version: 0.0.1
;; Original code: https://github.com/jkitchin/scimax/blob/master/scimax-ob.el#L301
;; Homepage:
;; Package-Requires: ((emacs "24.3"))
;;
;; This file is not part of GNU Emacs.
;;
;; Description
;; Add line numbers in org code-blocks
;;; Code:
(require 's)
(require 'org)
(require 'cl-lib)
(defvar scimax-ob-number-line-overlays '()
"List of overlays for line numbers.")
(make-variable-buffer-local 'scimax-ob-number-line-overlays)
(defun scimax-ob-toggle-line-numbers ()
"Toggle line numbers in the current Org source block."
(interactive)
(if scimax-ob-number-line-overlays
(scimax-ob-remove-line-numbers)
(scimax-ob-add-line-numbers)))
(defun scimax-ob-remove-line-numbers ()
"Remove line numbers from the current Org source block."
(interactive)
(mapc #'delete-overlay scimax-ob-number-line-overlays)
(setq-local scimax-ob-number-line-overlays '())
(remove-hook 'post-command-hook #'scimax-ob-add-line-numbers t))
(defun scimax-ob-add-line-numbers ()
"Add line numbers to an org src-block."
(interactive)
(save-excursion
(let* ((src-block (org-element-context)))
(when (eq (org-element-type src-block) 'src-block)
;;iAdrian patch - fix 'wrong-type-argument stringp nil' coming from the 'org-element-property :value src-block => nil' when trying to add linenumbers outside of a src-block (see commented code below which is the original version)
(let* ((value (org-element-property :value src-block))
(nlines (if value (1- (length (s-split "\n" value))) 0)))
;; (let* ((src-block (org-element-context))
;; (nlines (- (length (s-split "\n" (org-element-property :value src-block))) 1)))
;; clear any existing overlays
(scimax-ob-remove-line-numbers)
(goto-char (org-element-property :begin src-block))
;; the beginning may be header, so we move forward to get the #+BEGIN
;; line. Then jump one more to get in the code block
(while (not (looking-at "#\\+BEGIN"))
(forward-line))
(forward-line)
(cl-loop for i from 1 to nlines
do
(beginning-of-line)
(let ((ov (make-overlay (point) (point))))
(overlay-put
ov
'before-string (propertize
(format "%03s " (number-to-string i))
'font-lock-face '(:foreground "fg-main" :background "bg-main")))
(push ov scimax-ob-number-line-overlays))
(forward-line))))))
(add-hook 'post-command-hook #'scimax-ob-add-line-numbers nil 'local))
(provide 'scimax-ob-line-numbers)
;;; scimax-ob-line-numbers.el ends here