How do I search a buffer via Lisp?

Hi, thanks for the amazing work!

I am doing some work to mix Emacs and Nyxt and I got stuck (again).

I would like to search the current buffer via Common Lisp and move the focus on the first matching text.
Interactively, I can do that with nyxt/web-mode::search-buffer, but I would like to do it via Swank instead (so I cannot really use “prompt”, right?).

After a little research, I got to:
(NYXT/WEB-MODE::QUERY-BUFFER :QUERY
“some text I want to find”)

The problem is that highlights the matches and returns some JSON.

What are the chances that there is already a way to say “go to the nth match”?

I would like to copy from how “prompt” is defined, but unluckily is a compiled function and I am not sure where the source code is…

Thanks again!

Thanks for the kind words!

The source code is in the prompter library.

Firstly, to transform that JSON into CL objects you can use: (matches-from-json (query-buffer)). Then, given your matches list, you can use the highlight-selected-hint function. You’ll probably need to adapt it a bit for your needs:

(define-parenscript highlight-selected-hint (&key link-hint scroll)

  (defun update-hints ()
    (ps:let* ((new-element (nyxt/ps:qs document (ps:lisp (format nil "#nyxt-hint-~a" (identifier link-hint))))))
      (when new-element
        (unless ((ps:@ new-element class-list contains) "nyxt-highlight-hint")
          (ps:let ((old-elements (nyxt/ps:qsa document ".nyxt-highlight-hint")))
            (ps:dolist (e old-elements)
              (setf (ps:@ e class-name) "nyxt-hint"))))
        (setf (ps:@ new-element class-name) "nyxt-hint nyxt-highlight-hint")
        (if (ps:lisp scroll)
            (ps:chain new-element (scroll-into-view
                                   (ps:create block "nearest")))))))

  (update-hints))

hopefully that helps!

2 Likes

You are amazing! That is just what I needed :sunny:
I can finish my blog post now and the amazing integration with Emacs :smiley:
We are commanding webview via JavaScript then!? I always wanted to use parenscript!

A little question: given I installed Nyxt via Guix, how come I cannot find nyxt/ps:qs (I had the same problem for CL-STRINGS::replace-all and I ended up redefining myself)?

I’m not sure, I’m not so familiar with Guix. @ambrevar ?

1 Like

cl-strings is not used by Nyxt.

@Andrea Can you give more details about your setup?

Are you trying to “go to definition”? If so, it won’t work with just the Guix package because it does not include the source.
For now, if you want to see the definitions of the Nyxt symbols, you need to work from the Git checkout.
Hopefully someone (me?) will find time to fix the Guix package in the future.

1 Like

Thanks @ambrevar for pulling together the Guix package, it helped me a lot setting things up! I described my setup in detail at Browsing in Common Lisp: Nyxt and Emacs - Where parallels cross, but in summary I just installed Guix, installed nyxt and connected to it with Emacs via Slime.

Actually I was trying to use that definition because I misunderstood @jmercouris initial answer as I needed to define that highlight-selected-hint function myself in the Slime REPL. When I tried, I got an error saying that nyxt/ps:qs was not defined. Then I asked why some functions seem not to be available.

I mentioned cl-strings because was in one of the initial articles examples (Nyxt) and I was wondering how the author was using a package that you have to install via QuickLisp. Evidently Pierre was running Nyxt building it from source where he had access to his QuickLisp.

Cool article! Thanks for sharing!

@Andrea, I suppose you’re trying to use nyxt/ps:qs in Lisp code?

If so, it won’t work. nyxt/ps:qs is a Parenscript macro and thus it only works inside ps:ps forms :slight_smile:

It should be available given it’s inside ps:ps (or any other Parenscript form, including the body of define-parenscript), with no outside dependencies required.

1 Like

Ah thanks @aartaka ! I am learning Common Lisp a little bite at the time: I bet you are right. I will try out and let you know if it wasn’t the case. Thanks again!