|
| 1 | +;;; dix-yas.el --- optional yas-integration with dix.el |
| 2 | + |
| 3 | +;; Copyright (C) 2015-2016 Kevin Brubeck Unhammer |
| 4 | + |
| 5 | +;; Author: Kevin Brubeck Unhammer <unhammer@fsfe.org> |
| 6 | +;; Keywords: languages |
| 7 | + |
| 8 | +;; This file is not part of GNU Emacs. |
| 9 | + |
| 10 | +;; This program is free software; you can redistribute it and/or modify |
| 11 | +;; it under the terms of the GNU General Public License as published by |
| 12 | +;; the Free Software Foundation; either version 2, or (at your option) |
| 13 | +;; any later version. |
| 14 | +;; |
| 15 | +;; This program is distributed in the hope that it will be useful, |
| 16 | +;; but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 17 | +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 18 | +;; GNU General Public License for more details. |
| 19 | +;; |
| 20 | +;; You should have received a copy of the GNU General Public License |
| 21 | +;; along with this program. If not, see <http://www.gnu.org/licenses/>. |
| 22 | + |
| 23 | +;;; Commentary: |
| 24 | + |
| 25 | +;; Extensions to dix.el for using it with Yasnippet. |
| 26 | + |
| 27 | +;; Usage: |
| 28 | + |
| 29 | +;; (require 'dix-yas) |
| 30 | +;; (add-hook 'dix-mode-hook #'dix-maybe-yas-activate) |
| 31 | + |
| 32 | +;;; Code: |
| 33 | + |
| 34 | +(require 'dix) |
| 35 | +(require 'yasnippet) |
| 36 | + |
| 37 | +;;;============================================================================ |
| 38 | +;;; |
| 39 | +;;; Yasnippet helpers |
| 40 | +;;; |
| 41 | + |
| 42 | + |
| 43 | +;;; Note, due to |
| 44 | +;;; https://github.com/AndreaCrotti/yasnippet-snippets/issues/41 you |
| 45 | +;;; should do (remhash 'nxml-mode yas--tables) after (yas-reload-all) |
| 46 | + |
| 47 | +(defun dix-maybe-yas-activate () |
| 48 | + "Turn on `yas-minor-mode' in `dix-mode' if possible." |
| 49 | + (when (fboundp 'yas-activate-extra-mode) |
| 50 | + (yas-activate-extra-mode 'dix-mode))) |
| 51 | + |
| 52 | +;;; In case yasnippet is lazy-loaded after dix-mode, ensure dix-mode |
| 53 | +;;; snippets are used: |
| 54 | +(eval-after-load 'yasnippet |
| 55 | + '(mapc (lambda (buf) |
| 56 | + (when dix-mode (dix-maybe-yas-activate))) |
| 57 | + (buffer-list))) |
| 58 | + |
| 59 | + |
| 60 | + |
| 61 | +(defvar-local dix-yas-key-rex "" |
| 62 | + "Used by `dix-yas-update-key-rex' for caching the regex-opt of |
| 63 | + possible snippet keys.") |
| 64 | +(defvar-local dix-yas-key-rex-tables nil |
| 65 | + "Used by `dix-yas-update-key-rex' for checking if we need to |
| 66 | + update `dix-yas-key-rex'.") |
| 67 | + |
| 68 | +(defun dix-yas-update-key-rex () |
| 69 | + "Update `dix-yas-key-rex', used by `dix-yas-skip-backwards-to-key'." |
| 70 | + (let ((tables (yas--get-snippet-tables))) |
| 71 | + (unless (equal tables dix-yas-key-rex-tables) |
| 72 | + ;; Only update key-rex if tables changed (but is this equal test slow?): |
| 73 | + (setq dix-yas-key-rex-tables tables) |
| 74 | + (setq dix-yas-key-rex |
| 75 | + (let (keys) (mapc |
| 76 | + (lambda (table) |
| 77 | + (let* ((keyhash (yas--table-hash table))) |
| 78 | + (when keyhash |
| 79 | + (maphash (lambda (k v) (push k keys)) keyhash)))) |
| 80 | + dix-yas-key-rex-tables) |
| 81 | + (concat (regexp-opt keys) "$")))))) |
| 82 | + |
| 83 | +(defun dix-yas-skip-backwards-to-key (start-point) |
| 84 | + "Skip backwards to the first possible yasnippet key. |
| 85 | +
|
| 86 | +This is meant to be used in `yas-key-syntaxes' (which see for |
| 87 | +information on START-POINT), since the defaults don't let you |
| 88 | +expand e.g. \"<s>\" without having whitespace before it. To use |
| 89 | +this function, put the following in your init file: |
| 90 | +
|
| 91 | + (eval-after-load 'yasnippet |
| 92 | + '(add-to-list 'yas-key-syntaxes 'dix-yas-skip-backwards-to-key)) |
| 93 | +
|
| 94 | +Only has an effect in `dix-mode' so the above shouldn't change |
| 95 | +how yasnippet expansion works in other modes." |
| 96 | + (when dix-mode |
| 97 | + (dix-yas-update-key-rex) |
| 98 | + (let* ((linebeg (save-excursion (goto-char start-point) |
| 99 | + (line-beginning-position))) |
| 100 | + (haystack (buffer-substring-no-properties linebeg start-point))) |
| 101 | + (when (string-match dix-yas-key-rex haystack) |
| 102 | + (goto-char (+ linebeg (match-beginning 0))))))) |
| 103 | + |
| 104 | + |
| 105 | + |
| 106 | +(defun dix-yas-prev-lemma () |
| 107 | + (dix-yas-prev-thing "lemma" 'dix-lemma-at-point)) |
| 108 | + |
| 109 | +(defun dix-yas-prev-par () |
| 110 | + (dix-yas-prev-thing "lemma__POS" 'dix-par-at-point)) |
| 111 | + |
| 112 | +(defun dix-yas-prev-thing (default thing-at-point-fn) |
| 113 | + (condition-case nil |
| 114 | + (save-excursion |
| 115 | + (dix-up-to "e" "section") |
| 116 | + (condition-case nil |
| 117 | + (progn |
| 118 | + (dix-with-sexp (backward-sexp)) |
| 119 | + (let ((thing (funcall thing-at-point-fn))) |
| 120 | + (if (string-match "^$\\|^\\$" thing) |
| 121 | + default |
| 122 | + thing))) |
| 123 | + (error default))) |
| 124 | + (dix-parse-error default))) |
| 125 | + |
| 126 | +(defun dix-yas-message-pardef (pdname) |
| 127 | + "Just show the full pardef of `PDNAME' at point in *Messages* buffer." |
| 128 | + (save-excursion |
| 129 | + (save-restriction |
| 130 | + (widen) |
| 131 | + (dix-goto-pardef pdname) |
| 132 | + (let* ((beg (point)) |
| 133 | + (end (1+ (nxml-scan-element-forward beg)))) |
| 134 | + (message (buffer-substring-no-properties beg end))))) |
| 135 | + pdname) |
| 136 | + |
| 137 | +(defun dix-yas-pdname-to-pos (string) |
| 138 | + (if (numberp (string-match "__\\([^_]+\\)$" string)) |
| 139 | + (format "<s n=\"%s\"/>" (match-string 1 string)) |
| 140 | + "")) |
| 141 | + |
| 142 | +(defun dix-yas-pdname-to-suffix (string) |
| 143 | + (if (numberp (string-match "/\\([^_]+\\)" string)) |
| 144 | + (match-string-no-properties 1 string) |
| 145 | + "")) |
| 146 | + |
| 147 | +(defun dix-yas-fix-suffix-w/pdname () |
| 148 | + (let* ((suffix (dix-yas-pdname-to-suffix yas-text)) |
| 149 | + (suffix/i-rex (concat (regexp-quote suffix) "</i>"))) |
| 150 | + (when (re-search-backward suffix/i-rex (line-beginning-position) 'noerror) |
| 151 | + (replace-match "</i>" 'fixedcase 'literal)))) |
| 152 | + |
| 153 | +(defun dix-yas-choose-pdname () |
| 154 | + (when yas-moving-away-p |
| 155 | + (dix-yas-fix-suffix-w/pdname)) |
| 156 | + (dix-yas-message-pardef |
| 157 | + (yas-choose-value |
| 158 | + (dix-pardef-suggest-for (dix-lemma-at-point))))) |
| 159 | + |
| 160 | +(defun dix-yas-lm-to-i () |
| 161 | + (replace-regexp-in-string " " "<b/>" yas-text)) |
| 162 | + |
| 163 | +(provide 'dix-yas) |
| 164 | + |
| 165 | +;;;============================================================================ |
| 166 | + |
| 167 | +;;; dix-yas.el ends here |
0 commit comments