feat(emacs): Fill some search-related stubs

This commit is contained in:
Madeleine Sydney
2025-02-20 15:45:20 -07:00
parent 98a71dc13b
commit e2193dbd53
13 changed files with 227 additions and 26 deletions

View File

@@ -643,6 +643,29 @@ Run various checks on the system.
List persistent files per user, and show their mount strategy.
- Show info about ~sydnix.impermanence.cache~ values. Extend that option to have "description" and "consequences" fields, which are shown to users before clearing them. e.g.
#+begin_src nix
{
sydnix.impermanence.cache.directories.".local/share/emacs/cache" = {
description = "Root of all caches for Emacs and Emacs packages.";
consequences = [
"All known projects will be forgotten"
"All trusted .dir-locals.el files and values will be forgotten"
];
};
}
#+end_src
#+begin_example
$ sydnix cache clear
Recursively remove `~/.local/share/emacs/cache'?
- All known projects will be forgotten
- All trusted .dir-locals.el files and values will be forgotten
[y/n]
«more caches…»
#+end_example
* References
Following is a subset of the many places I've learnt from. Most important of all are Doom Emacs and Faye's Wishsys.

View File

@@ -19,17 +19,56 @@
;;
;;; Code:
(syd-define-stub
syd/search-buffer
"Conduct a text search on the current buffer.
(cl-defun syd-search-region (beg end &key initial)
(save-restriction
(narrow-to-region beg end)
(consult-line initial)))
(defun syd-search--escape-regexp (str)
(require 'syd-text)
(replace-regexp-in-string " " "\\\\ "
(syd-pcre-quote str)))
(defun syd-search-buffer (buffer)
"Conduct a text search on BUFFER.
If a selection is active and multi-line, perform a search restricted to that
region.
If a selection is active and not multi-line, use the selection as the initial
input and search the whole buffer for it.
input and search the whole buffer for it."
(interactive (list (current-buffer)))
(save-restriction
(let* ((beg (region-beginning))
(end (region-end))
(multiline-p (/= (line-number-at-pos beg)
(line-number-at-pos end))))
(if (and beg end (region-active-p))
(progn (deactivate-mark)
(if multiline-p
(syd-search-region beg end)
;; Treat as a single pattern, not several
;; space-separated patterns.
(consult-line (syd-search--escape-regexp
(buffer-substring-no-properties beg end)))))
(consult-line)))))
;;;###autoload
(defun syd-search-directory (dir)
(interactive (list (read-directory-name
"Search directory: "
default-directory nil t)))
(cond ((executable-find "rg")
(consult-ripgrep dir))
((executable-find "grep")
(message "Couldn't find ripgrep; using grep")
(consult-grep dir))))
;;;###autoload
(defun syd-search-current-directory ()
(interactive)
(syd-search-directory default-directory))
See `+default/search-buffer'.")
(provide 'syd-search)
;;; syd-search.el ends here

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1 @@
src:/home/crumb/.m2/repository/cider/cider-nrepl/0.52.0/cider-nrepl-0.52.0.jar:/home/crumb/.m2/repository/http-kit/http-kit/2.8.0/http-kit-2.8.0.jar:/home/crumb/.m2/repository/nrepl/nrepl/1.3.1/nrepl-1.3.1.jar:/home/crumb/.m2/repository/org/babashka/cli/0.8.62/cli-0.8.62.jar:/home/crumb/.m2/repository/org/clojars/pntblnk/clj-ldap/0.0.17/clj-ldap-0.0.17.jar:/home/crumb/.m2/repository/org/clojure/clojure/1.12.0/clojure-1.12.0.jar:/home/crumb/.m2/repository/cider/orchard/0.30.0/orchard-0.30.0.jar:/home/crumb/.m2/repository/mx/cider/logjam/0.3.0/logjam-0.3.0.jar:/home/crumb/.m2/repository/com/unboundid/unboundid-ldapsdk/5.1.1/unboundid-ldapsdk-5.1.1.jar:/home/crumb/.m2/repository/org/clojure/core.specs.alpha/0.4.74/core.specs.alpha-0.4.74.jar:/home/crumb/.m2/repository/org/clojure/spec.alpha/0.5.238/spec.alpha-0.5.238.jar

View File

@@ -0,0 +1,4 @@
-m
nrepl.cmdline
--middleware
[cider.nrepl/cider-middleware]

10
scripts/ldap-nginx-plumber/.gitignore vendored Normal file
View File

@@ -0,0 +1,10 @@
result
.nrepl
.nrepl-port
.cpcache/
.cache/
.lsp/
.clj-kondo
.cpcache
.lsp
.nrepl

View File

@@ -0,0 +1 @@
/nix/store/4ir60qbhfgrf1r9xa1dnig13x4clhir0-ldap-nginx-plumber-1.0.0

View File

@@ -63,15 +63,13 @@ If FORCE-P, delete without confirmation."
:desc "Move current file. See `doom/move-this-file'."
:interactive t)
(syd-define-stub
syd/find-file-under-emacs-user-directory
:desc "Find under `emacs-user-directory'. See `doom/find-file-in-private-config'."
:interactive t)
(syd-define-stub
syd/find-file-under-here
:desc "Find under CWD. See `+default/find-file-under-here'."
:interactive t)
(defun syd-find-file-in (root)
(interactive (list (read-directory-name
"Find file in: " default-directory nil t)))
;; HACK: To avoid reimplementation, we pretend `root' is a project and
;; delegate the work to project.el.
(syd-with-project-root root
(project-find-file)))
(syd-define-stub
syd/yank-buffer-path
@@ -81,11 +79,21 @@ If FORCE-P, delete without confirmation."
(defun syd/find-file-in-emacs-user-directory ()
(interactive)
(unless (file-directory-p user-emacs-directory)
(user-error "`emacs-user-directory' doesn't exist! (%s)"
(abbreviate-file-name emacs-user-directory)))
(user-error "`user-emacs-directory' doesn't exist! (%s)"
(abbreviate-file-name user-emacs-directory)))
(let ((default-directory user-emacs-directory))
(call-interactively #'find-file)))
(defun syd-switch-to-emacs-user-directory ()
"Switch project to `user-emacs-directory' via `project-switch-project'."
(interactive)
(require 'syd-project)
(if (file-directory-p user-emacs-directory)
(syd-with-project-root user-emacs-directory
(project-switch-project user-emacs-directory))
(user-error "`user-emacs-directory' (%s) does not exist or is not a directory!"
(abbreviate-file-name user-emacs-directory))))
(syd-define-stub
syd/open-this-file-as-root
:desc "Open current file as root. See `doom/sudo-this-file'."
@@ -137,6 +145,7 @@ If FORCE-P, delete without confirmation."
base-file
conflict-file)))
;;;###autoload
(defun syd-split-tramp-file-name (file-name)
"Split FILE-NAME into (TRAMP-PREFIX . LOCAL-NAME). Returns (nil . FILE-NAME)
if FILE-NAME has no TRAMP prefix."

View File

@@ -8,9 +8,32 @@
(when-let* ((project (project-current nil dir)))
(project-root project)))
(defun syd-cd-project ()
(defun syd-project-cd ()
"Change the working directory to the root of the current project."
(cd (syd-project-root)))
(define-obsolete-function-alias 'syd-cd-project 'syd-project-cd
"2025-02-20")
(defmacro syd-with-project-root (root &rest body)
"Execute BODY with ROOT recognised as what project.el calls a \"transient
project\"."
(declare (indent defun))
(let ((root* (gensym "root"))
(forget-after-p (gensym "forget-after-p")))
`(let* ((,root* ,root)
(,forget-after-p
(not (member ,root* (project-known-project-roots)))))
(let ((project-find-functions (lambda (_) (cons 'transient ,root*))))
,@body)
(when ,forget-after-p
(project-forget-project ,root*)))))
(defun syd-project-search ()
(interactive)
(require 'syd-file)
;; TODO: Prompt for path project root is not found.
(syd-search-directory (syd-project-root)))
(provide 'syd-project)
;;; syd-project.el ends here

View File

@@ -0,0 +1,55 @@
;;; syd-search.el -*- lexical-binding: t; -*-
(cl-defun syd-search-region (beg end &key initial)
(save-restriction
(narrow-to-region beg end)
(consult-line initial)))
(defun syd-search--escape-regexp (str)
(require 'syd-text)
(replace-regexp-in-string " " "\\\\ "
(syd-pcre-quote str)))
(defun syd-search-buffer (buffer)
"Conduct a text search on BUFFER.
If a selection is active and multi-line, perform a search restricted to that
region.
If a selection is active and not multi-line, use the selection as the initial
input and search the whole buffer for it."
(interactive (list (current-buffer)))
(save-restriction
(let* ((beg (region-beginning))
(end (region-end))
(multiline-p (/= (line-number-at-pos beg)
(line-number-at-pos end))))
(if (and beg end (region-active-p))
(progn (deactivate-mark)
(if multiline-p
(syd-search-region beg end)
;; Treat as a single pattern, not several
;; space-separated patterns.
(consult-line (syd-search--escape-regexp
(buffer-substring-no-properties beg end)))))
(consult-line)))))
;;;###autoload
(defun syd-search-directory (dir)
(interactive (list (read-directory-name
"Search directory: "
default-directory nil t)))
(cond ((executable-find "rg")
(consult-ripgrep dir))
((executable-find "grep")
(message "Couldn't find ripgrep; using grep")
(consult-grep dir))))
;;;###autoload
(defun syd-search-current-directory ()
(interactive)
(syd-search-directory default-directory))
(provide 'syd-search)
;;; syd-search.el ends here

View File

@@ -120,4 +120,16 @@ in some cases."
(interactive "P<x><y>")
(syd-evil-paste t arg register yank-handler))
;;;###autoload
(defun syd-pcre-quote (str)
"Like `reqexp-quote', but for PCREs."
(let ((special '(?. ?^ ?$ ?* ?+ ?? ?{ ?\\ ?\[ ?\| ?\())
(quoted nil))
(mapc (lambda (c)
(when (memq c special)
(push ?\\ quoted))
(push c quoted))
str)
(concat (nreverse quoted))))
(provide 'syd-text)

View File

@@ -23,10 +23,12 @@
"r" `("Revert buffer" . ,#'revert-buffer))
;; Search
(require 'syd-search)
(general-def
:prefix-map 'syd-leader-search-map
"i" `("IMenu" . ,#'consult-imenu)
"b" `("Search buffer" . ,#'syd/search-buffer))
"b" `("Search buffer" . ,#'syd-search-buffer)
"d" `("Search directory" . ,#'syd-search-directory))
;; File
(require 'syd-file)
@@ -35,9 +37,8 @@
"D" `("Delete file" . ,#'syd/delete-this-file)
"R" `("Move file" . ,#'syd/move-this-file)
"C" `("Copy file" . ,#'syd/copy-this-file)
;; "F" `("Find file under here" . ,#'syd/find-file-under-here)
;; "p" `("Find under Emacs config" . ,#'syd/find-file-under-emacs-user-directory)
"P" `("Browse Emacs config" . ,#'syd/find-file-in-emacs-user-directory)
"F" `("Find file in" . ,#'syd-find-file-in)
"P" `("Browse Emacs config" . ,#'syd-switch-to-emacs-user-directory)
"u" `("Find file as root" . ,#'syd/find-file-as-root)
"U" `("Open this file as root" . ,#'syd/open-this-file-as-root)
"y" `("Yank buffer path" . ,#'syd/yank-buffer-path)
@@ -78,7 +79,8 @@
;; Project
(general-def
:prefix-map 'syd-leader-project-map
"C" `("Compile project" . ,#'project-compile))
"C" `("Compile project" . ,#'project-compile)
"." `("Browse project from root" . ,#'project-root-find-file))
(general-def
:prefix-map 'syd-leader-help-package-map
@@ -140,7 +142,9 @@
"s" `("Search" . ,syd-leader-search-map)
"h" `("Help" . ,help-map)
"n" `("Notes" . ,syd-leader-notes-map)
"i" `("Insert" . ,syd-leader-insert-map)))
"i" `("Insert" . ,syd-leader-insert-map)
"," `("Switch buffer in project" . ,#'consult-project-buffer)
"<" `("Switch buffer" . ,#'consult-buffer)))
(syd-keybinds-initialise)

View File

@@ -2,9 +2,28 @@
(require 'syd-constants)
(use-package project
:custom ((project-list-file (file-name-concat syd-cache-dir
"known-projects"))))
(with-eval-after-load 'project ; Built-in
;; Stay out of my config directory!
(setq project-list-file (file-name-concat syd-cache-dir "known-projects"))
;; For each command in `project-switch-commands' will assign it the key found
;; in `project-prefix-map'. We emulate that behaviour but for our own
;; `syd-leader-project-map'.
(let* ((project-key
(lambda (f)
(key-description
(where-is-internal
f
;; If the keymap is not wrapped in a list,
;; `where-is-internal' will also search the
;; global ;; keymaps
(list syd-leader-project-map)
;; First result only.
t))))
(switch-cmd (lambda (command name &optional key)
(append (list command name)
(list (or key (funcall project-key command)))))))
(add-to-list 'project-switch-commands
(funcall switch-cmd #'project-root-find-file "Browse"))))
;; Projection provides a Projectile-like project management library atop
;; Emacs built-in project.el. It's more lightweight, while still featureful.