]> git.eshelyaron.com Git - dotfiles.git/commitdiff
Checkpoint
authorEshel Yaron <me@eshelyaron.com>
Sat, 13 Aug 2022 04:54:47 +0000 (07:54 +0300)
committerEshel Yaron <me@eshelyaron.com>
Sat, 13 Aug 2022 04:54:47 +0000 (07:54 +0300)
.emacs.d/esy.org
.emacs.d/lisp/iprolog.el

index 38293074edfcc808c9e126ebccfbcdc3c8cb1428..c15936d965ed5c5b81212e8aa0e2f78b2defe324 100644 (file)
@@ -782,7 +782,8 @@ refiling directly into deeper headings as well.
     (interactive)
     (pulse-momentary-highlight-one-line))
 
-  (add-to-list 'window-state-change-functions #'esy/pulse-line)
+  ; (add-to-list 'window-state-change-functions #'esy/pulse-line)
+
 #+end_src
 
 ** Misc. keybindings
index f34da5f66323e412c6f6f696ce1818881f54ae43..98dde4b78265a76c400490e1300e98af66889ef7 100644 (file)
   :type 'string
   :group 'iprolog)
 
+(defcustom iprolog-wants-flymake t
+  "Non-nil means `iprolog-mode' should integrate with `flymake-mode'."
+  :package-version '((iprolog . "0.1.0"))
+  :type 'boolean
+  :group 'iprolog)
+
+(defcustom iprolog-wants-eldoc t
+  "Non-nil means `iprolog-mode' should integrate with `eldoc'."
+  :package-version '((iprolog . "0.1.0"))
+  :type 'boolean
+  :group 'iprolog)
+
 (defun iprolog-beginning-of-defun-function (&optional arg)
   "Backend for `beginning-of-defun', which see for the meaning of ARG."
+  (font-lock-ensure)
   (let ((times (or arg 1)))
     (if (< times 0)
         (iprolog-beginning-of-next-defun (- times))
       (while (< 0 times)
         (goto-char (or (previous-single-property-change (point) 'iprolog-beginning-of-term) (point-min)))
         (unless (bobp) (backward-char))
-        (setq times (1- times))))))
+        (setq times (1- times)))))
+  (bobp))
+
 
 (defun iprolog-end-of-defun-function ()
   "Backend for `end-of-defun'."
@@ -56,7 +71,8 @@
     (when (get-text-property (point) 'iprolog-beginning-of-term)
       (forward-char))
     (goto-char (or (next-single-property-change (point) 'iprolog-beginning-of-term) (point-max)))
-    (setq times (1- times))))
+    (setq times (1- times)))
+  (eobp))
 
 (defun iprolog-text-property--find-beg-backward (property value)
   (iprolog-text-property--find-end-backward property value)
   (setq-local comment-start "%")
   (setq-local comment-start-skip "\\(?:/\\*+ *\\|%+ *\\)")
   (setq-local parens-require-spaces nil)
-  (add-hook 'flymake-diagnostic-functions #'iprolog--checker nil t)
-  (setq-local eldoc-documentation-strategy #'eldoc-documentation-default)
-  (add-hook 'eldoc-documentation-functions #'iprolog-predicate-modes-doc nil t)
+  (when iprolog-wants-flymake
+    (add-hook 'flymake-diagnostic-functions #'iprolog--checker nil t))
+  (when iprolog-wants-eldoc
+    (setq-local eldoc-documentation-strategy #'eldoc-documentation-default)
+    (add-hook 'eldoc-documentation-functions #'iprolog-predicate-modes-doc nil t))
   (add-hook 'completion-at-point-functions #'iprolog--atom-completion-at-point-function nil t)
+  ;; (add-hook 'post-self-insert-hook #'iprolog-post-self-insert-function nil t)
+  ;; (add-hook 'xref-backend-functions        ...)
   ;; (setq-local compile-command             ...)
   ;; (setq-local electric-indent-chars       ...)
   ;; (setq-local align-rules-alist           ...)
   ;; (setq-local imenu-create-index-function ...)
   ;; (setq-local indent-line-function        ...)
   ;; (setq-local indent-region-function      ...)
-  ;; (setq jit-lock-chunk-size 8192)
+  (setq-local fill-paragraph-function        #'iprolog-fill-paragraph-function)
+  ;; (setq-local fill-forward-paragraph-function     ...)
+  (setq jit-lock-chunk-size               8192)
   (setq-local beginning-of-defun-function #'iprolog-beginning-of-defun-function)
   (setq-local end-of-defun-function #'iprolog-end-of-defun-function)
   (setq-local font-lock-defaults
                 nil
                 nil
                 (font-lock-fontify-region-function . iprolog-fontify-region)
-                (font-lock-extra-managed-props       (iprolog-beginning-of-term)))))
+                (font-lock-extra-managed-props       iprolog-beginning-of-term
+                                                     ))))
 
 ;;;; project.el integration
 
@@ -248,14 +271,50 @@ value of `iprolog-project-definition-file-name'."
 
 (defun iprolog-project--name ()
   "Return the name of the current Prolog project."
-  (let ((default-directory (project-root (project-current))))
-    (iprolog--execute-to-string "consult(pack), name(N), write(N)")))
+  (let ((default-directory (or (iprolog-project--root)
+                               default-directory)))
+    (if (file-exists-p (expand-file-name "pack.pl" default-directory))
+        (iprolog--execute-to-string "consult(pack), name(N), write(N)")
+      "")))
 
 (defun iprolog-project--version ()
   "Return the version of the current Prolog project, as a string."
-  (let ((default-directory (project-root (project-current))))
-    (iprolog--execute-to-string "consult(pack), version(N), write(N)")))
-
+  (let ((default-directory (or (iprolog-project--root)
+                               default-directory)))
+    (if (file-exists-p (expand-file-name "pack.pl" default-directory))
+        (iprolog--execute-to-string "consult(pack), version(N), write(N)")
+      "")))
+
+
+;;;; autotyping
+
+(defconst iprolog--atom-regexp (rx (seq line-start (or lower "'") (* anychar)))
+  "Regular expression recognizing atoms.")
+
+(defun iprolog-read-term ()
+  (let ((token (iprolog-read-token)))
+    token))
+
+(defun iprolog-read-token ()
+  (let ((string (read-string "?- ")))
+    (cond
+     ((string-match iprolog--atom-regexp string nil t)
+      (list 'atom string)))))
+
+(defun iprolog-post-self-insert-function ()
+  (when (and (not (memq last-command-event '(?\s ?\n)))
+             (not (get-text-property (point) 'iprolog-beginning-of-term))
+             (not (eq 'iprolog-syntax-error-face (get-text-property (1- (point)) 'font-lock-face)))
+             (not (eq 'iprolog-fullstop-face (get-text-property (1- (point)) 'font-lock-face)))
+             (< (save-mark-and-excursion
+                  (iprolog-text-property--find-end-backward 'iprolog-beginning-of-term t)
+                  (point))
+                (save-mark-and-excursion
+                  (iprolog-text-property--find-end-backward 'font-lock-face 'iprolog-fullstop-face)
+                  (point))))
+    (insert ". ")
+    (backward-char 2))
+  (remove-text-properties (1- (point)) (point)  '(font-lock-face iprolog-beginning-of-term)))
 
 ;;;; top-level
 
@@ -504,41 +563,35 @@ Also start a Prolog server listening on UDP port PORT."
   "Flymake backend function for Prolog projects.
 REPORT-FN is the reporting function passed to backend by Flymake,
 as documented in `flymake-diagnostic-functions', ARGS"
-  (let* ((end      (when-let ((pos (plist-get args :changes-end)))
-                     (save-mark-and-excursion
-                       (save-match-data
-                         (goto-char pos)
-                         (end-of-defun)
-                         (point)))))
-         (start    (if-let ((pos (plist-get args :changes-start)))
-                       (save-mark-and-excursion
-                         (save-match-data
-                           (goto-char pos)
-                           (beginning-of-defun-comments)
-                           (point)))
-                     (point-min)))
-         (buffer   (current-buffer))
-         (tempfile (make-temp-file "iprolog--checker")))
-    (with-temp-file tempfile
-      (insert-buffer-substring buffer start end))
-    (iprolog--request-goal-output
-     (concat "'" (buffer-file-name buffer) "' = Path, catch([Path], _, true), diagnose(Path,'"  tempfile "')")
-     (if end
-         (lambda (o)
-           (with-current-buffer buffer
-             (funcall report-fn
-                      (or (delq nil
-                                (seq-map
-                                 (lambda (line)
-                                   (iprolog--parse-diagnostic line start))
-                                 (string-lines o t)))
-                          nil)
-                      :region (cons start end))))
-       (lambda (o)
-         (with-current-buffer buffer
-           (dolist (line (string-lines o t))
-             (when-let ((diag (iprolog--parse-diagnostic line start)))
-               (funcall report-fn (list diag)))))))))
+  (let ((diags nil)
+        (end (save-mark-and-excursion
+               (save-match-data
+                 (goto-char (or (plist-get args :changes-end) (point-min)))
+                 (end-of-defun 2)
+                 (point)))))
+    (save-mark-and-excursion
+      (save-match-data
+        (goto-char (or (plist-get args :changes-start) (point-min)))
+        (beginning-of-defun)
+        (let ((beg (point)))
+          (font-lock-ensure beg end)
+          (while (< (point) end)
+            (when-let ((diag (pcase (get-text-property (point) 'font-lock-face)
+                               ('iprolog-syntax-error-face
+                                (let ((wbeg (point)))
+                                  (goto-char (or (next-single-property-change (point) 'font-lock-face) end))
+                                  (flymake-make-diagnostic (current-buffer) wbeg (point) :error "Syntax error")))
+                               ('iprolog-instantiation-error-face
+                                (let ((wbeg (point)))
+                                  (goto-char (or (next-single-property-change (point) 'font-lock-face) end))
+                                  (flymake-make-diagnostic (current-buffer) wbeg (point) :warning "Instantiation error")))
+                               ('iprolog-singleton-face
+                                (let ((wbeg (point)))
+                                  (goto-char (or (next-single-property-change (point) 'font-lock-face) end))
+                                  (flymake-make-diagnostic (current-buffer) wbeg (point) :warning "Singleton variable"))))))
+              (setq diags (cons diag diags)))
+            (goto-char (or (next-single-property-change (point) 'font-lock-face) end)))
+          (funcall report-fn diags :region (cons beg end))))))
   t)
 
 
@@ -729,6 +782,9 @@ explanation about the argument CALLBACK."
          ((string= type "clause")
           (put-text-property beg (1+ beg) 'iprolog-beginning-of-term t)
           '(nil t))
+         ((string= type "term")
+          (put-text-property beg (1+ beg) 'iprolog-beginning-of-term t)
+          '(nil t))
          ((string= type "directive")
           (put-text-property beg (1+ beg) 'iprolog-beginning-of-term t)
           '(nil t))
@@ -790,8 +846,7 @@ explanation about the argument CALLBACK."
           (list iprolog-foreign-face nil))
          ((string-match (rx (seq line-start
                                  "goal(built_in"
-                                 (+ anychar)
-                                 ")"))
+                                 (+ anychar)))
                         type nil t)
           (list iprolog-built-in-face nil))
          ((string-match (rx (seq line-start
@@ -880,37 +935,82 @@ explanation about the argument CALLBACK."
         (buffer (current-buffer))
         (default-directory (or (iprolog-project--root)
                                default-directory)))
-    (when loudly (message "fontifying %s-%s" beg end))
-    (font-lock-unfontify-region beg end)
+    (message "(re)fontifying from %s to %s %s %s" beg end (point-min) (point-max))
     (iprolog--ensure-top-level)
-    (let* ((tempfile (make-temp-file
-                      "iprolog--fontify"
-                      nil
-                      ".pl")))
-      (with-temp-file tempfile
-        (insert-buffer-substring buffer beg end))
-      (iprolog--request-goal-output
-       (concat "\"" (buffer-file-name buffer) "\"= Orig,"
-               "\"" tempfile "\"= Path,"
-               "ensure_loaded(Orig), xref_source(Orig), (source_file_property(Orig, module(Module)) -> true ; Module = prolog_colour), debug(iprolog, \"fontifying ~w as ~w\", [Path, Module]), setup_call_cleanup(prolog_open_source(Path, Stream), @(prolog_colourise_stream(Stream, Orig, [T, S, L]>>format(\"~w:~w:~w~n\", [S,L,T])), Module), prolog_close_source(Stream))")
-       (lambda (o)
-         (with-current-buffer buffer
-           (with-silent-modifications
-             (dolist (line (string-lines o t))
-               (when-let ((f (iprolog--parse-fontification-line line beg)))
-                 (let ((fs (car f))
-                       (fe (cadr f))
-                       (ff (caddr f))
-                       (fm (cadddr f)))
-                   (if ff
-                       (put-text-property fs fe 'font-lock-face ff)
-                     ;; (remove-text-properties fs fe '(font-lock-face))
-                     )
-                   (when fm
-                     (put-text-property fs fe 'font-lock-multiline t)))))))
-         (delete-file tempfile))))
-    (font-lock-fontify-keywords-region beg end loudly)
+    (if (and (= beg (point-min))
+             (= end (point-max))
+             (not (buffer-modified-p)))
+        (iprolog--request-goal-output
+         (concat "'" (buffer-file-name buffer) "' = Orig,"
+                 "ensure_loaded(Orig), xref_source(Orig), setup_call_cleanup(prolog_open_source(Orig, Stream), prolog_colourise_stream(Stream, Orig, [T, S, L]>>format(\"~w:~w:~w~n\", [S,L,T])), prolog_close_source(Stream))")
+         (lambda (o)
+           (with-current-buffer buffer
+             (with-silent-modifications
+               (save-mark-and-excursion
+                 (font-lock-unfontify-buffer)
+                 (dolist (line (string-lines o t))
+                   (when-let ((f (iprolog--parse-fontification-line line beg)))
+                     (let ((fs (car f))
+                           (fe (cadr f))
+                           (ff (caddr f))
+                           (fm (cadddr f)))
+                       (when ff
+                         (put-text-property fs fe 'font-lock-face ff))
+                       (when fm
+                         (put-text-property fs fe 'font-lock-multiline t)))))
+                 (font-lock-fontify-keywords-region (point-min) (point-max) loudly))))))
+      (let* ((tempfile (make-temp-file
+                        "iprolog--fontify"
+                        nil
+                        ".pl")))
+        (with-temp-file tempfile
+          (insert-buffer-substring buffer beg end))
+        (iprolog--request-goal-output
+         (concat "'" (buffer-file-name buffer) "' = Orig,"
+                 "\"" tempfile "\"= Path,"
+                 "ensure_loaded(Orig), xref_source(Orig), setup_call_cleanup(prolog_open_source(Path, Stream), (repeat, once(prolog_colourise_term(Stream, O, [T, S, L]>>format(\"~w:~w:~w~n\", [S,L,T]), [])), at_end_of_stream(Stream), !), prolog_close_source(Stream))")
+         (lambda (o)
+           (with-current-buffer buffer
+             (font-lock-unfontify-region beg end)
+             (with-silent-modifications
+               (save-mark-and-excursion
+                 (dolist (line (string-lines o t))
+                   (when-let ((f (iprolog--parse-fontification-line line beg)))
+                     (let ((fs (car f))
+                           (fe (cadr f))
+                           (ff (caddr f))
+                           (fm (cadddr f)))
+                       (when ff
+                         (put-text-property fs fe 'font-lock-face ff))
+                       (when fm
+                         (put-text-property fs fe 'font-lock-multiline t)))))
+                 (font-lock-fontify-keywords-region beg end loudly))))
+           (delete-file tempfile)))))
     `(jit-lock-bounds ,beg . ,end)))
 
 
+;;; fill-paragraph
+
+(defun iprolog--portray-term (s)
+  (iprolog--request-goal-sync (concat "term_string(T," (prin1-to-string s) ",[variable_names(VN)]),"
+                                      "portray_clause(current_output, T, [variable_names(VN)])")))
+
+(defun iprolog-portray-and-insert-term (s)
+  (interactive "sTerm: " iprolog-mode)
+  (insert (iprolog--portray-term s)))
+
+(defun iprolog-fill-paragraph-function (&optional _justify)
+  (let* ((start (save-mark-and-excursion
+                  (beginning-of-defun)
+                  (point)))
+         (end (save-mark-and-excursion
+                (end-of-defun)
+                (point)))
+         (term (buffer-substring-no-properties start end))
+         (port (iprolog--portray-term term)))
+    (when port
+      (goto-char start)
+      (delete-region start end)
+      (insert port))))
+
 ;;; iprolog.el ends here