(defvar prolog-mode-abbrev-table nil)
(define-abbrev-table 'prolog-mode-abbrev-table ())
+(defun prolog-smie-forward-token ()
+ (forward-comment (point-max))
+ (buffer-substring-no-properties
+ (point)
+ (progn (cond
+ ((looking-at "[!;]") (forward-char 1))
+ ((not (zerop (skip-chars-forward "#&*+-./:<=>?@\\^`~"))))
+ ((not (zerop (skip-syntax-forward "w_'"))))
+ ;; In case of non-ASCII punctuation.
+ ((not (zerop (skip-syntax-forward ".")))))
+ (point))))
+
+(defun prolog-smie-backward-token ()
+ (forward-comment (- (point-max)))
+ (buffer-substring-no-properties
+ (point)
+ (progn (cond
+ ((memq (char-before) '(?! ?\;)) (forward-char -1))
+ ((not (zerop (skip-chars-backward "#&*+-./:<=>?@\\^`~"))))
+ ((not (zerop (skip-syntax-backward "w_'"))))
+ ;; In case of non-ASCII punctuation.
+ ((not (zerop (skip-syntax-backward ".")))))
+ (point))))
+
(defconst prolog-smie-op-levels
;; Rather than construct the operator levels table from the BNF,
;; we directly provide the operator precedences from GNU Prolog's
- ;; manual. The only problem is that GNU Prolog's manual uses
- ;; precedence levels in the opposite sense (higher numbers bind less
- ;; tightly) than SMIE, so we use negative numbers.
+ ;; manual (7.14.10 op/3). The only problem is that GNU Prolog's
+ ;; manual uses precedence levels in the opposite sense (higher
+ ;; numbers bind less tightly) than SMIE, so we use negative numbers.
'(("." -10000 -10000)
(":-" -1200 -1200)
("-->" -1200 -1200)
)
"Precedence levels of infix operators.")
-(defconst prolog-smie-indent-rules
- '((":-")
- ("->"))
- "Prolog indentation rules.")
+(defun prolog-smie-rules (kind token)
+ (pcase (cons kind token)
+ (`(:elem . basic) prolog-indent-width)
+ (`(:after . ".") 0) ;; To work around smie-closer-alist.
+ (`(:after . ,(or `":-" `"->")) prolog-indent-width)))
(defun prolog-mode-variables ()
(make-local-variable 'paragraph-separate)
(setq paragraph-ignore-fill-prefix t)
(make-local-variable 'imenu-generic-expression)
(setq imenu-generic-expression '((nil "^\\sw+" 0)))
- (smie-setup prolog-smie-op-levels prolog-smie-indent-rules)
- (set (make-local-variable 'forward-sexp-function)
- 'smie-forward-sexp-command)
- (set (make-local-variable 'smie-indent-basic) prolog-indent-width)
+
+ ;; Setup SMIE.
+ (smie-setup prolog-smie-op-levels #'prolog-smie-rules
+ :forward-token #'prolog-smie-forward-token
+ :backward-token #'prolog-smie-backward-token)
+ (set (make-local-variable 'smie-blink-matching-triggers) '(?.))
+ (set (make-local-variable 'smie-closer-alist) '((t . ".")))
+ (add-hook 'post-self-insert-hook #'smie-blink-matching-open 'append 'local)
+ ;; There's no real closer in Prolog anyway.
+ (set (make-local-variable 'smie-blink-matching-inners) t)
+
(make-local-variable 'comment-start)
(setq comment-start "%")
(make-local-variable 'comment-start-skip)
(defun end-of-prolog-clause ()
"Go to end of clause in this line."
(beginning-of-line 1)
- (let* ((eolpos (save-excursion (end-of-line) (point))))
+ (let* ((eolpos (line-end-position)))
(if (re-search-forward comment-start-skip eolpos 'move)
(goto-char (match-beginning 0)))
(skip-chars-backward " \t")))
(provide 'prolog)
-;; arch-tag: f3ec6748-1272-4ab6-8826-c50cb1607636
;;; prolog.el ends here