A little bit of Scheme

January 14, 2020

A question came through this morning on how to do something in Scheme. I don’t usually have time to answer individual Scheme questions unfortunately however this one caught my eye and I gave it a go.

The user wanted to define a Scheme function to select a line in the text editor based on the position of the cursor. This could then be attached to an editor toolbar button.

The problem can be broken down as follows:

  1. Get the start of the line the cursor is currently on.
  2. Find the end of the line.
  3. Select the line.

A clue on how to get the start of the current line can be found in the beorg library.org (the file that defines a bunch of Scheme code used internally by beorg):

(define (line-start)
  (+ (string-search-backward "\n" (buffer-substring (point-min) (point))) 2))

More difficult is to get the end of the line. Once you know the start of the line the trick is to either find the next newline, or failing that the end of the current buffer. The following solution does highlight a few inefficiencies in the available integration with the text editor, but it should work well enough on files which aren’t huge:

(define (line-end)
  (let* ((start-of-line (line-start))
         (rest-of-buffer (buffer-substring start-of-line (point-max)))
         (next-newline (string-search-forward "\n" rest-of-buffer)))
    (if next-newline
        (+ start-of-line next-newline)
        (point-max))))

You can now use these to create a new toolbar button. Here is the text editor toolbar with a new button “Line” to select the current line:

(set! editor-toolbar-items '(("icon-left" (backward-char))
                             ("icon-right" (forward-char))
                             ("icon-list" (insert "+ "))
                             ("icon-todolist" (insert "+ [ ] "))
                             ("icon-change" (show-transform-commands))
                             ("icon-tools" (show-tools-commands))
                             ("icon-settings" (insert-code-snippet))
                             ("Line" (region-set (line-start) (line-end)))))

Download now for iPhone and iPad

Follow us on Mastodon

Privacy Policy | Press Kit