monnier pushed a commit to branch master in repository elpa. commit dff4589a6b73a483996f460a0376dd22d2555cd3 Author: Teemu Likonen <tliko...@iki.fi> Date: Sat Feb 5 11:20:57 2011 +0000
Uusi ominaisuus: tarkistusohjelman tulosteen jäsennysfunktio Nyt käyttäjä voi määrittää oman jäsenninfunktionsa tarkistusohjelman tulostetta varten. Omasta jäsenninfunktiosta on hyötyä silloin, kun tarkistusohjelma ei tulostakaan (maalattavaksi tarkoitettuja) merkkijonoja puhtaasti omilla riveillään. Esimerkiksi voikkospell- ohjelmaa varten voisi tehdä seuraavanlaisen kieliasetuksen: ("voikkospell" (program . "/usr/bin/voikkospell") (args "ignore_dot=1") (parser . (lambda () (let (words) (while (re-search-forward "^W: " nil t) (push (buffer-substring-no-properties (point) (line-end-position)) words)) words)))) --- wcheck-mode.el | 198 ++++++++++++++++++++++++++++++++++++++------------------ 1 files changed, 136 insertions(+), 62 deletions(-) diff --git a/wcheck-mode.el b/wcheck-mode.el index f9eaa07..02a0522 100644 --- a/wcheck-mode.el +++ b/wcheck-mode.el @@ -94,6 +94,14 @@ (stringp value))) (string :format "%v"))) + (cons :tag "Output parser function" :format "%v" + (const :tag "Output parser" :format "%t: " parser) + (choice :format "%[Parser%] %v" :value nil + (const :tag "Lines" wcheck-parser-lines) + (const :tag "Whitespace" wcheck-parser-whitespace) + (function :tag "Custom function" + :format "%t:\n\t\t%v"))) + (cons :tag "Connection type" :format "%v" (const :tag "Connection: " :format "%t" connection) (choice :format "%[Type%] %v" :value nil @@ -148,9 +156,9 @@ (const :tag "Suggestion parser" :format "%t: " suggestion-parser) (choice :format "%[Parser%] %v" :value nil - (const :tag "Ispell" wcheck-parse-suggestions-ispell) - (const :tag "Lines" wcheck-parse-suggestions-lines) - (const :tag "Whitespace" wcheck-parse-suggestions-ws) + (const :tag "Ispell" wcheck-parser-ispell-suggestions) + (const :tag "Lines" wcheck-parser-lines) + (const :tag "Whitespace" wcheck-parser-whitespace) (function :tag "Custom function" :format "%t:\n\t\t%v"))) @@ -212,11 +220,10 @@ program `wcheck-mode' collects text strings from the buffer and sends them (each on a separate line) to the external program for - analyzing. The program must output (on separate lines) only - the strings which it thinks should be marked in the Emacs - buffer. Usually the reason is that the word is misspelled. - The program should output nothing if it doesn't think that - the string should be marked in Emacs buffer. + analyzing. The program must output (one way or another) the + strings which it thinks should be marked in the Emacs buffer. + The output of the program is then parsed with `parser' + function (see below). VALUE can also be an Emacs Lisp function (a symbol or a lambda). Then that function is used as the text checker. The @@ -234,6 +241,33 @@ args program. (This option is ignored when the program is a function.) +parser + VALUE of this option is an Emacs Lisp function which is + responsible for parsing the output of `program'. This parser + function is only used when `program' is an external + executable program (not a function). + + The parser function is run without arguments and within the + context of a buffer that contains all the output from the + external program. The point is located at the beginning of + the buffer. From that buffer the `parser' function should + collect all the strings that are meant to be marked in the + buffer that is being checked. The function must return them + as a list of strings or nil if there are none. + + For the most common cases there are two parser functions + already implemented: + + `wcheck-parser-lines' turns each line in program's output + to a separate string. You should use this function as the + output parser if you spell-check with Ispell-like program + with its \"-l\" command-line option. They output each + misspelled word on a separate line. This is the default + output parser. + + `wcheck-parser-whitespace' turns each whitespace- + separated token in the output to a separate string. + connection The VALUE is used to set variable `process-connection-type' when starting the process for LANGUAGE. If the VALUE is nil @@ -326,10 +360,9 @@ suggestion-args When user clicks the right mouse button on marked text, or executes command `wcheck-spelling-suggestions', the marked text will be sent to the `suggestion-program' as standard - input stream. The program should send suggested - substitutes (in one way or another) to the standard output - stream. The output is parsed with `suggestion-parser' - function (see below). + input stream. The program should send suggested substitutes + to the standard output stream. The output is parsed with + `suggestion-parser' function (see below). When `suggestion-program' is an Emacs Lisp function the function is called with one argument: the marked text (a @@ -344,27 +377,25 @@ suggestion-parser is an external executable program (not a function). The parser function is run without arguments and within the - context of a temporary buffer. The buffer contains all the - output from the external program and the point is located at - the beginning of the buffer. `suggestion-parser' function - should collect all the substitute suggestions from the buffer - and return them as a list of strings or nil if there are no - suggestions. + context of a buffer that contains all the output from the + external program. The point is located at the beginning of + the buffer. `suggestion-parser' function should collect all + the substitute suggestions from the buffer and return them as + a list of strings or nil if there are no suggestions. For the most common cases there are three parser functions already implemented: - `wcheck-parse-suggestions-ispell' parses substitute + `wcheck-parser-ispell-suggestions' parses substitute suggestions from the output of Ispell or compatible program, such as Enchant or Aspell. Use this function as the `suggestion-parser' if you get suggestions from an Ispell-like program with its \"-a\" command-line option. - `wcheck-parse-suggestions-lines' function turns each line - in the output of `suggestion-program' to individual - substitute suggestions. + `wcheck-parser-lines' function turns each line in the + output to individual substitute suggestions. - `wcheck-parse-suggestions-ws'. Each whitespace-separated + `wcheck-parser-whitespace'. Each whitespace-separated token in the program's output is a separate suggestion. read-or-skip-faces @@ -434,13 +465,13 @@ Here's an example value for the `wcheck-language-data' variable: (syntax . my-finnish-syntax-table) (suggestion-program . \"/usr/bin/enchant\") (suggestion-args \"-a\" \"-d\" \"fi\") - (suggestion-parser . wcheck-parse-suggestions-ispell)) + (suggestion-parser . wcheck-parser-ispell-suggestions)) (\"British English\" (program . \"/usr/bin/ispell\") (args \"-l\" \"-d\" \"british\") (suggestion-program . \"/usr/bin/ispell\") (suggestion-args \"-a\" \"-d\" \"british\") - (suggestion-parser . wcheck-parse-suggestions-ispell)) + (suggestion-parser . wcheck-parser-ispell-suggestions)) (\"Trailing whitespace\" (program . identity) (suggestion-program . (lambda (string) (list \"\"))) @@ -476,7 +507,8 @@ language-specific option does not exist or is not valid." ;;;###autoload (defconst wcheck-language-data-defaults-hard-coded - '((connection . nil) + '((parser . wcheck-parser-lines) + (connection . nil) (face . wcheck-default-face) (syntax . text-mode-syntax-table) (regexp-start . "\\<'*") @@ -503,7 +535,9 @@ settings. Here's an example value for the variable: - ((connection . nil) + ((parser . wcheck-parser-lines) + (suggestion-parser . wcheck-parser-ispell-suggestions) + (connection . nil) (face . wcheck-default-face) (syntax . text-mode-syntax-table) (regexp-start . \"\\\\=\\<'*\") @@ -583,9 +617,6 @@ slower. A suitable compromise may be 3 or 4.") (defvar wcheck-buffer-data nil) -(defconst wcheck-process-name "wcheck" - "Process name for `wcheck-mode'.") - (defvar wcheck-jump-step 5000) @@ -923,7 +954,14 @@ separate line." (stringp program)) (process-send-string (wcheck-start-get-process buffer) - (concat (mapconcat #'identity strings "\n") "\n"))) + (concat (mapconcat #'identity strings "\n") "\n")) + (condition-case nil + (with-current-buffer + (process-buffer (wcheck-buffer-data-get + :buffer buffer :process)) + (erase-buffer)) + (error nil))) + ((functionp program) (when (buffer-live-p buffer) (with-current-buffer buffer @@ -949,24 +987,43 @@ separate line." (defun wcheck-receive-strings (process string) "`wcheck-mode' process output handler function." - (let ((buffer (wcheck-buffer-data-get :process process :buffer))) + (let ((buffer (wcheck-buffer-data-get :process process :buffer)) + (parser (wcheck-query-language-data + (wcheck-buffer-data-get :process process :language) + 'parser))) (when (buffer-live-p buffer) (with-current-buffer buffer ;; If process is running proceed to collect and paint the ;; strings. - (if (eq 'run (process-status process)) - (progn - (wcheck-buffer-data-set - buffer :strings (append (split-string string "\n+" t) - (wcheck-buffer-data-get :buffer buffer - :strings))) - (wcheck-buffer-data-set buffer :paint-req t)) - - ;; It's not running. Turn off the mode. - (wcheck-mode -1) - (message "Process is not running for buffer \"%s\"" - (buffer-name buffer))))))) + (condition-case error-data + (if (eq 'run (process-status process)) + (with-current-buffer (process-buffer process) + (save-excursion + (goto-char (point-max)) + (insert string) + (let ((parsed-strings + (save-match-data + (save-excursion + (goto-char (point-min)) + (condition-case nil (funcall parser) + (error (signal 'wcheck-funcall-error + nil))))))) + (when (and parsed-strings + (wcheck-list-of-strings-p parsed-strings)) + (wcheck-buffer-data-set buffer :strings parsed-strings) + (wcheck-buffer-data-set buffer :paint-req t))))) + + ;; It's not running. Turn off the mode. + (wcheck-mode -1) + (signal 'wcheck-error "Process is not running for buffer \"%s\"" + (buffer-name buffer))) + + (wcheck-funcall-error + (message "Checker output parser function signaled an error")) + + (wcheck-error + (message "%s" (cdr error-data)))))))) (defun wcheck-timer-paint-event () @@ -1174,12 +1231,14 @@ operation was unsuccessful." (when (wcheck-program-executable-p program) ;; Start the process. - (let ((proc (apply #'start-process wcheck-process-name nil - program args))) + (let ((proc (apply #'start-process "wcheck" nil program args))) ;; Add the process Lisp object to database. (wcheck-buffer-data-set buffer :process proc) - ;; Set the output handler function. + ;; Set the output handler function and the associated buffer. (set-process-filter proc #'wcheck-receive-strings) + (set-process-buffer proc (generate-new-buffer + (concat " *wcheck-process <" + (buffer-name buffer) ">*"))) ;; Prevent Emacs from querying user about running processes ;; when killing Emacs. (set-process-query-on-exit-flag proc nil) @@ -1226,6 +1285,7 @@ BUFFER from the list." ;; Stop those processes which are no longer needed. (dolist (proc old-processes) (unless (memq proc new-processes) + (kill-buffer (process-buffer proc)) (delete-process proc)))))) (wcheck-buffer-data-get :buffer buffer)) @@ -1695,22 +1755,25 @@ or nil." nil)) -(defun wcheck-parse-suggestions-lines () - "Parser for newline-separated suggestions." - (delete-dups (split-string (buffer-substring-no-properties (point-min) - (point-max)) +(defun wcheck-parser-lines () + "Parser for newline-separated output. +Return current buffer's lines as a list of strings." + (delete-dups (split-string (buffer-substring-no-properties + (point-min) (point-max)) "\n+" t))) -(defun wcheck-parse-suggestions-ws () - "Parser for whitespace-separated suggestions." - (delete-dups (split-string (buffer-substring-no-properties (point-min) - (point-max)) +(defun wcheck-parser-whitespace () + "Parser for whitespace-separated output. +Split current buffer's content to whitespace-separated tokens and +return them as a list of strings." + (delete-dups (split-string (buffer-substring-no-properties + (point-min) (point-max)) "[ \f\t\n\r\v]+" t))) -(defun wcheck-parse-suggestions-ispell () - "Parser for Ispell-compatible programs' output." +(defun wcheck-parser-ispell-suggestions () + "Parser for Ispell-compatible programs' spelling suggestions." (let ((search-spaces-regexp nil)) (when (re-search-forward "^& [^ ]+ \\([0-9]+\\) [0-9]+: \\(.+\\)$" nil t) (let ((count (string-to-number (match-string-no-properties 1))) @@ -1718,6 +1781,14 @@ or nil." (delete-dups (nbutlast words (- (length words) count))))))) +(define-obsolete-function-alias 'wcheck-parse-suggestions-lines + 'wcheck-parser-lines "2011.01.23") +(define-obsolete-function-alias 'wcheck-parse-suggestions-ws + 'wcheck-parser-whitespace "2011.01.23") +(define-obsolete-function-alias 'wcheck-parse-suggestions-ispell + 'wcheck-parser-ispell-suggestions "2011.01.23") + + ;;; Face information functions @@ -1788,11 +1859,11 @@ expression will return a boolean." (syntax-table-p (and (boundp value) (eval value))))) ((and (eq key 'face) (facep value))) - ((and (stringp value) - (or (eq key 'regexp-start) + ((and (or (eq key 'regexp-start) (eq key 'regexp-body) (eq key 'regexp-end) - (eq key 'regexp-discard)))) + (eq key 'regexp-discard)) + (stringp value))) ((and (or (eq key 'program) (eq key 'suggestion-program)) (or (stringp value) @@ -1803,7 +1874,8 @@ expression will return a boolean." (stringp value)))) ((and (eq key 'suggestion-args) (wcheck-list-of-strings-p value))) - ((and (eq key 'suggestion-parser) + ((and (or (eq key 'parser) + (eq key 'suggestion-parser)) (functionp value))) ((or (eq key 'connection) (eq key 'case-fold))) @@ -1826,7 +1898,9 @@ or `wcheck-language-data-defaults-hard-coded'." (and (wcheck-list-of-lists-p wcheck-language-data-defaults) (assq key wcheck-language-data-defaults))) (hard-coded - (assq key wcheck-language-data-defaults-hard-coded)) + (and (wcheck-list-of-lists-p + wcheck-language-data-defaults-hard-coded) + (assq key wcheck-language-data-defaults-hard-coded))) (conf (list (when (wcheck-language-data-valid-p key (cdr data)) data)