Files
emacs-dotfiles/.config.d/99-my-ediprolog.el
Vladislav Slobodenyuk f99504e8f0 Organisational commit
Modified input method is the main highlight.
2026-01-09 21:40:51 +09:00

87 lines
3.3 KiB
EmacsLisp

;;; 99-my-ediprolog.el --- ediprolog extras -*- no-byte-compile: t; lexical-binding: t; -*-
;;; Commentary:
;; ediprolog is a very minimalist package, and I find myself needing to code
;; some functionality myself. Ergo, this file.
;;; Code:
(defun my-ediprolog-run-in-own-buffer ()
"Copy this query to another buffer and run it there."
(interactive)
;; This is the same logic ediprolog uses to check if the point is on query.
(when (and (not (and transient-mark-mode mark-active))
(save-excursion
(beginning-of-line)
(looking-at "\\([\t ]*%*[\t ]*[:?]- *\\)")))
(let* ((from (goto-char (match-end 0)))
(to (if (re-search-forward "\\.[\t ]*\\(?:%.*\\)?$" nil t)
;; omit trailing whitespace
(+ (point) (skip-chars-backward "\t "))
(error "Missing `.' at the end of this query")))
(query (buffer-substring-no-properties from to))
(buffer (get-buffer-create "*Prolog Query*")))
(pop-to-buffer buffer)
(unless (eq major-mode "prolog-mode")
(prolog-mode))
(goto-char (point-max))
(unless (eq (line-number-at-pos) 1)
(insert "\n\n"))
(insert "/*\n ?- ")
(save-excursion
(insert query "\n*/"))
(ediprolog-dwim))))
(defun my-ediprolog-delete-next-comments ()
"Delete all commented lines after point (excluding the line under point).
Will continue until a line without a comment is encountered. See also
'ediprolog-dwim'."
(interactive)
(save-excursion
(beginning-of-line)
(next-line)
(while (looking-at "[ ]*%")
(delete-line))))
(defun my-ediprolog-return-to-closest-query ()
"Tries to set point to closest query (starts with ?-) preceding it."
(interactive)
(re-search-backward "\\([\t ]*%*[\t ]*[:?]- *\\)" nil t))
(defcustom my-ediprolog-system-types
'(("scryer-prolog" . (scryer . ("systemd-run" "--user" "--scope" "-p" "MemoryMax=2G" "-p" "MemoryHigh=1.9G" "scryer-prolog")))
("swi-prolog" . (swi . ("swipl"))))
"An alist of prolog systems and their respective run commands.
This has the form of form (NAME . TYPE . COMMAND). NAME is the display
name that user will be presented with, TYPE is one of swi or scryer, for
the two supported prolog systems respectively. COMMAND is a list, where
the first element is the command and the rest are arguments. See
'my-ediprolog-select-system'"
:type '(alist
:key-type string
:value-type (cons (choice (const :tag "Scryer Prolog" :value scryer)
(const :tag "SWI Prolog" :value swi))
(repeat string))))
(defun my-ediprolog-select-system (&optional system)
"Prompts the user to select a prolog SYSTEM and configures ediprolog to use it.
The prolog systems are defined in 'my-ediprolog-system-types'."
(interactive (list (completing-read "Select system:" my-ediprolog-system-types)))
(let ((pair (alist-get system my-ediprolog-system-types nil nil #'equal)))
(setq ediprolog-system (car pair))
(setq ediprolog-program (cadr pair))
(setq ediprolog-program-switches (cddr pair))))
(with-eval-after-load 'prolog
(keymap-set prolog-mode-map "C-c C-d" #'my-ediprolog-delete-next-comments)
(keymap-set prolog-mode-map "C-c C-b" #'my-ediprolog-return-to-closest-query))
;;; 99-my-ediprolog.el ends here