-
Notifications
You must be signed in to change notification settings - Fork 5
/
gramadoir.el
280 lines (243 loc) · 9.35 KB
/
gramadoir.el
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
;;; gramadoir.el --- Interface to An Gramadóir
;; Copyright (C) 2003 Free Software Foundation, Inc.
;; Author: Martin Gregory <Martin.Gregory@eur.sas.com>
;; Keywords: hypermedia, unix
;; This file is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation; either version 2, or (at your option)
;; any later version.
;; This file is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
;; along with GNU Emacs; see the file COPYING. If not, write to
;; the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
;; Boston, MA 02110-1301, USA.
;;; Commentary:
;; This package provides an interface to the Irish language grammar
;; checking program An Gramadóir
;;; Code:
(defvar gramadoir-program-path "/usr/bin/gram-ga.pl"
"Location of the executable for An Gramadóir"
)
(defvar gramadoir-highlight-text t
"Whether to highlight the words in error in the checked text. A
value of t highlights, nil prevents not. The words in error in the
Gramadoir output buffer are always highlighted")
(defvar gramadoir-program-options "--html --aschod=ISO-8859-1"
"options for the executable for An Gramadóir")
(defvar gramadoir-display-buffer "*Gramadoir Output*"
"Name of buffer containing human readable output of An Gramadóir")
(defvar gramadoir-current-file ""
"File containing the current error")
(defvar gramadoir-current-line 0
"Line in the current file on which the current error occurs")
(defvar gramadoir-check-file-msgid "^Currently checking %s"
"gettext message id for determining the translation of the message which
identifies the file currently being checked."
)
(defun gramadoir-set-check-file-msg ()
"Set gramadoir-check-file-msg according to locale."
(setq gramadoir-check-file-msg
(format
(concat "^"
(shell-command-to-string
"gettext gramadoir \"Currently checking %s\"")) ""))
)
(defvar gramadoir-check-file-msg (gramadoir-set-check-file-msg)
"Regular expression used to determine which file a message relates to. The
initial value is taken from the translation of the English version of the
message.")
(defun gramadoir-check-region (start end)
"This function runs the grammar checking program An Gramadóir on the current
region, if there is one. The function can also be called using
(gramadoir-check-region (point) (mark))
from within a lisp program. The xml output from An Gramadóir is sent to a
temporary buffer whence it can be parsed.
"
(interactive "r") ; default to region for start and end if interactive
(call-process-region (point) (mark) ; the region
gramadoir-program-path
nil ; keep output
buffer ; write to buffer
nil ; dont show it until finished
,@(split-string gramadoir-program-options " "))
;; might want to call (setq output (shell-command-to-string command))
;; calls:
;gramadoir-parse-results (buffer)
)
(defun gramadoir-check-files (gramadoir-file-spec)
"This function runs the grammar checking program An Gramadóir on a list of
files.
"
(interactive "sFiles: ")
(if (get-buffer gramadoir-display-buffer)
(progn
(set-buffer gramadoir-display-buffer)
(erase-buffer)
))
(setq gr-cmd `(call-process gramadoir-program-path
nil ; no standard input
gramadoir-display-buffer ; write to buffer
nil ; dont show it until finished
,@(split-string gramadoir-program-options " ")
,@(split-string gramadoir-file-spec " ")))
(eval gr-cmd)
;; calls:
;;gramadoir-parse-results (buffer)
;; display the results in the lower window.
(with-current-buffer gramadoir-display-buffer
(goto-char (point-min))
(gramadoir-highlight)
;(goto-char (point-min))
(display-buffer gramadoir-display-buffer t)
))
(defun gramadoir-format-message (text)
"convert an error message code (xml tag) into a human-readable form")
(defun gramadoir-get-location (text)
"determine the exact location of the erroneous text so that it can be
highlighted in the display")
(defun gramadoir-get-substitution (text)
"If An Gramadóir suggests an alternative, save it keyed on the error location
so it can be presented to the user for possible substitution")
(defun gramadoir-parse-results (buffer)
"Parse the results of the call to An Gramadóir"
;; calls:
; (gramadoir-format-message)
; (gramadoir-get-location)
; (gramadoir-get-substitution)
)
(defun gramadoir-next-message ()
"Jump to next message"
(interactive)
(set-buffer gramadoir-display-buffer)
(if (get-buffer-window gramadoir-display-buffer)
(delete-window (get-buffer-window gramadoir-display-buffer)))
;; determine line number of next message
;(message "Before re-search: in %s at %d" (current-buffer) (point))
(if (re-search-forward "^\\([0-9]*\\):" nil t)
(progn
(setq gramadoir-current-line (string-to-number (match-string 1)))
;;(message "Before excursion: in %s at %d" (current-buffer) (point))
;; determine which file is the message in
(setq gramadoir-current-file
(save-excursion
(end-of-line) ; in case we are located on a file name line
(re-search-backward gramadoir-check-file-msg)
(forward-word 2)
(buffer-substring (+ 1 (point))
(save-excursion (end-of-line) (point)))))
(gramadoir-goto-message gramadoir-current-file gramadoir-current-line))
(message "No more errors."))
)
(defun gramadoir-goto-message (gramadoir-current-file gramadoir-current-line)
"Jump to selected message"
(interactive)
;; load the file if it is not already loaded
;(message "ggm: %s %s %s" gramadoir-current-file gramadoir-current-line
; (get-file-buffer gramadoir-current-file))
(if (get-file-buffer gramadoir-current-file)
nil
(find-file-other-window gramadoir-current-file)
)
(set-buffer (get-file-buffer gramadoir-current-file))
(goto-line gramadoir-current-line)
;; now find the words to highlight. Since setting text properties
;; marks the buffer as modified, but we want to preserve modified
;; state, save the current setting to use as argument to
;; set-buffer-modified-p after we highlight.
(if gramadoir-highlight-text
(let (the-word
(eol (save-excursion (end-of-line) (point)))
(was-modified (buffer-modified-p)))
(while (setq the-word (with-current-buffer gramadoir-display-buffer
(gramadoir-get-word)))
;; search to end of line for the word and highlight
(if (re-search-forward the-word eol t)
(put-text-property (match-beginning 0) (match-end 0)
'face 'font-lock-comment-face)
))
(set-buffer-modified-p was-modified)
))
;(message "ggm: %s %d " gramadoir-current-file (point))
(switch-to-buffer (get-file-buffer gramadoir-current-file))
(display-buffer gramadoir-display-buffer)
)
(defun gramadoir-highlight ()
"Function to highlight messages from An Gramadóir"
(interactive)
(save-excursion
(let ((start-re "<b class=gramadoir>")
(end-re "</b>")
(start-error 0))
(goto-char (point-min))
(while (re-search-forward start-re (point-max) t)
(put-text-property (match-beginning 0) (point) 'invisible t)
(setq start-error (point))
(if (re-search-forward end-re (point-max) t)
(progn
(put-text-property start-error (match-beginning 0)
'face 'font-lock-comment-face)
(put-text-property (match-beginning 0) (point) 'invisible t)
)))))
;; remove the <br> tags
(save-excursion
(while (re-search-forward "<br>" nil t)
(replace-match "" nil t)))
(message "end of gramadoir-highlight, point=%d" (point))
)
(defun gramadoir-get-word ()
"Function to retrieve word to which a message refers. This function searches
for the invisible text surrounding the word in error and returns either the
word or an empty string. If a word is found, the pointer is placed after the
invisible closing tag so that the next call will search ahead. The function
only searches within the current line"
(interactive)
(let ((open-b 0)
(start-word 0)
(end-word 0)
(close-b 0)
(eol (save-excursion (end-of-line) (point)))
(word ""))
(setq open-b (text-property-any (point) eol 'invisible t))
(setq word
(if open-b
(progn
(setq start-word (text-property-any open-b eol 'invisible nil))
(if start-word
(progn
(setq end-word (text-property-any start-word eol 'invisible t))
(buffer-substring-no-properties start-word end-word)
))
))
)
(if (stringp word)
(progn
(goto-char end-word)
(goto-char (or (text-property-any (point) eol 'invisible nil) eol))
;;(message "word is: %s, %d" word close-b)
word
)
nil)
)
)
(defun gramadoir-dired ()
"Run gramadoir on files in a dired buffer. If no files are marked, the
file on the current line is checked, otherwise all marked files are checked.
This command should only be used in a dired buffer."
(interactive)
(if (equal major-mode 'dired-mode)
(let* ((file-list (dired-get-marked-files))
(list-len (length file-list))
(this-string "")
(i 0))
(while (<= i list-len)
(setq this-string (concat this-string (nth i file-list) " "))
(setq i (1+ i)))
(gramadoir-check-files this-string))
(message "gramadoir-dired: current buffer is not a dired buffer.")
)
)
(provide 'gramadoir)
;;; gramadoir.el ends here