1 ;;; pspp-mode-el -- Major mode for editing PSPP files
3 ;; Copyright (C) 2005 Free Software Foundation
4 ;; Created: 05 March 2005
5 ;; Keywords: PSPP major-mode
9 ;; Based on the example wpdl-mode.el by Scott Borton
10 ;; Author: Scott Andrew Borton <scott@pp.htv.fi>
12 ;; Copyright (C) 2000, 2003 Scott Andrew Borton <scott@pp.htv.fi>
14 ;; This program is free software: you can redistribute it and/or modify
15 ;; it under the terms of the GNU General Public License as published by
16 ;; the Free Software Foundation, either version 3 of the License, or
17 ;; (at your option) any later version.
19 ;; This program is distributed in the hope that it will be useful,
20 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
21 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 ;; GNU General Public License for more details.
24 ;; You should have received a copy of the GNU General Public License
25 ;; along with this program. If not, see <http://www.gnu.org/licenses/>.
28 (defvar pspp-mode-hook nil
)
30 (let ((pspp-mode-map (make-keymap)))
31 (define-key pspp-mode-map
"\C-j" 'newline-and-indent
)
33 "Keymap for PSPP major mode")
35 (add-to-list 'auto-mode-alist
'("\\.sps\\'" . pspp-mode
))
38 (defun pspp-data-block-p ()
39 "Returns t if current line is inside a data block."
42 (pspp-end-of-block-found nil
)
43 (pspp-start-of-block-found nil
)
47 (or (bobp) pspp-end-of-block-found
)
48 pspp-start-of-block-found
51 (set 'pspp-end-of-block-found
(looking-at "^[ \t]*END[\t ]+DATA\."))
52 (set 'pspp-start-of-block-found
(looking-at "^[ \t]*BEGIN[\t ]+DATA"))
56 (and pspp-start-of-block-found
(not pspp-end-of-block-found
))
61 (defconst pspp-indent-width
67 (defconst pspp-indenters
74 "constructs which cause indentation"
78 (defconst pspp-unindenters
79 (concat "^[\t ]*END[\t ]+"
87 ;; Note that "END CASE" and "END FILE" do not unindent.
89 "constructs which cause end of indentation"
94 (defun pspp-indent-line ()
95 "Indent current line as PSPP code."
100 (the-indent 0) ; Default indent to column 0
105 (setq the-indent
0) ; First line is always non-indented
114 ;; If the most recent non blank line ended with a `.' then
115 ;; we're at the start of a new command.
118 (while (and blank-line
(not (bobp)))
121 (if (and (not (pspp-data-block-p)) (not (looking-at "^[ \t]*$")))
123 (setq blank-line nil
)
125 (if (not (looking-at ".*\\.[ \t]*$"))
126 (setq within-command t
)
134 ;; If we're not at the start of a new command, then add an indent.
136 (set 'the-indent
(+ 1 the-indent
))
141 ;; Set the indentation according to the DO - END blocks
146 (if (not (pspp-comment-p))
151 (looking-at pspp-indenters
)
153 (set 'the-indent
(+ the-indent
1) )
156 ( (looking-at pspp-unindenters
)
157 (set 'the-indent
(- the-indent
1) )
167 (if (looking-at "^[\t ]*ELSE")
168 (set 'the-indent
(- the-indent
1)))
171 ;; Stuff in the data-blocks should be untouched
172 (if (not (pspp-data-block-p)) (indent-line-to (* pspp-indent-width the-indent
)))
177 (defun pspp-comment-start-line-p ()
178 "Returns t if the current line is the first line of a comment, nil otherwise"
180 (or (looking-at "^\*")
181 (looking-at "^[\t ]*COMMENT[\t ]")
186 (defun pspp-comment-end-line-p ()
187 "Returns t if the current line is the candidate for the last line of a comment, nil otherwise"
189 (looking-at ".*\\.[\t ]*$")
194 (defun pspp-comment-p ()
195 "Returns t if point is in a comment. Nil otherwise."
196 (if (pspp-data-block-p)
199 (pspp-comment-start-found nil
)
200 (pspp-comment-end-found nil
)
201 (pspp-single-line-comment nil
)
206 (while (and (>= lines
0)
207 (not pspp-comment-start-found
)
208 (not pspp-comment-end-found
)
211 (if (pspp-comment-start-line-p) (set 'pspp-comment-start-found t
))
213 (set 'pspp-comment-end-found nil
)
216 (if (pspp-comment-end-line-p) (set 'pspp-comment-end-found t
))
219 (set 'lines
(forward-line -
1))
224 (set 'pspp-single-line-comment
(and
225 (pspp-comment-start-line-p)
226 (pspp-comment-end-line-p)))
230 (or pspp-single-line-comment
231 (and pspp-comment-start-found
(not pspp-comment-end-found
)))
236 (defvar pspp-mode-syntax-table
238 (x-pspp-mode-syntax-table (make-syntax-table))
241 ;; Special chars allowed in variables
242 (modify-syntax-entry ?
# "w" x-pspp-mode-syntax-table
)
243 (modify-syntax-entry ?
@ "w" x-pspp-mode-syntax-table
)
244 (modify-syntax-entry ?$
"w" x-pspp-mode-syntax-table
)
247 ;; This is incomplete, because:
248 ;; a) Comments can also be given by COMMENT
249 ;; b) The sequence .\n* is interpreted incorrectly.
251 (modify-syntax-entry ?
* ". 2" x-pspp-mode-syntax-table
)
252 (modify-syntax-entry ?.
". 3" x-pspp-mode-syntax-table
)
253 (modify-syntax-entry ?
\n "- 41" x-pspp-mode-syntax-table
)
257 (modify-syntax-entry ?
' "\"" x-pspp-mode-syntax-table
)
258 (modify-syntax-entry ?
" "\"" x-pspp-mode-syntax-table)
260 x-pspp-mode-syntax-table)
262 "Syntax table for pspp-mode
")
265 (defconst pspp-font-lock-keywords
285 "CLEAR TRANSFORMATIONS
"
353 "LOGISITIC REGRESSION
"
377 "PEARSON CORRELATIONS
"
442 'font-lock-builtin-face)
445 (concat "\\<" (regexp-opt '(
446 "ALL
" "AND
" "BY
" "EQ
" "GE
" "GT
" "LE
" "LT
"
447 "NE
" "NOT
" "OR
" "TO
" "WITH
"
448 ) t ) "\\>") 'font-lock-keyword-face)
669 t) "\\>" ) 'font-lock-function-name-face)
671 '( "\\<[#$
@a-zA-Z
][a-zA-Z0-9_
]*\\>" . font-lock-variable-name-face)
676 "Highlighting expressions for PSPP mode.
")
681 (kill-all-local-variables)
682 (use-local-map pspp-mode-map)
683 (set-syntax-table pspp-mode-syntax-table)
685 (set (make-local-variable 'font-lock-keywords-case-fold-search) t)
686 (set (make-local-variable 'font-lock-defaults) '(pspp-font-lock-keywords))
688 (set (make-local-variable 'indent-line-function) 'pspp-indent-line)
689 (set (make-local-variable 'comment-start ) "* ")
690 (set (make-local-variable 'compile-command)
695 (setq major-mode 'pspp-mode)
696 (setq mode-name "PSPP
")
697 (run-hooks 'pspp-mode-hook))
701 ;;; pspp-mode.el ends here