Use -Wdeclaration-after-statement if available.
[pspp-builds.git] / pspp-mode.el
1 ;;; pspp-mode-el -- Major mode for editing PSPP files
2
3 ;; Copyright (C) 2005 Free Software Foundation
4 ;; Author: John Darrington <john@darrington.wattle.id.au>
5 ;; Created: 05 March 2005
6 ;; Keywords: PSPP major-mode
7
8
9
10 ;; Based on the example wpdl-mode.el by Scott Borton
11 ;; Author: Scott Andrew Borton <scott@pp.htv.fi>
12
13 ;; Copyright (C) 2000, 2003 Scott Andrew Borton <scott@pp.htv.fi>
14
15 ;; This program is free software; you can redistribute it and/or
16 ;; modify it under the terms of the GNU General Public License as
17 ;; published by the Free Software Foundation; either version 2 of
18 ;; the License, or (at your option) any later version.
19
20 ;; This program is distributed in the hope that it will be
21 ;; useful, but WITHOUT ANY WARRANTY; without even the implied
22 ;; warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
23 ;; PURPOSE.  See the GNU General Public License for more details.
24
25 ;; You should have received a copy of the GNU General Public
26 ;; License along with this program; if not, write to the Free
27 ;; Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
28 ;; MA 02110-1301 USA
29
30 ;;; Code:
31 (defvar pspp-mode-hook nil)
32 (defvar pspp-mode-map
33   (let ((pspp-mode-map (make-keymap)))
34     (define-key pspp-mode-map "\C-j" 'newline-and-indent)
35     pspp-mode-map)
36   "Keymap for PSPP major mode")
37
38 (add-to-list 'auto-mode-alist '("\\.sps\\'" . pspp-mode))
39
40
41 (defun pspp-data-block-p ()
42   "Returns t if current line is inside a data block."
43   (save-excursion
44     (let (
45           (pspp-end-of-block-found nil)
46           (pspp-start-of-block-found nil)
47           )
48       (beginning-of-line)
49       (while (not (or 
50                    (or (bobp) pspp-end-of-block-found ) 
51                    pspp-start-of-block-found 
52                    )
53                   )
54         (set 'pspp-end-of-block-found (looking-at "^[ \t]*END[\t ]+DATA\."))
55         (set 'pspp-start-of-block-found (looking-at "^[ \t]*BEGIN[\t ]+DATA"))
56         (forward-line -1)
57         )
58       
59       (and pspp-start-of-block-found (not pspp-end-of-block-found))
60       )
61     )
62   )
63
64 (defconst pspp-indent-width
65   2
66   "size of indent"
67 )
68
69
70 (defconst pspp-indenters
71   (concat "^[\t ]*"
72           (regexp-opt '("DO"
73                         "BEGIN"
74                         "LOOP"
75                         "INPUT") t)
76           "[\t ]+")
77   "constructs which cause indentation"
78 )
79
80
81 (defconst pspp-unindenters
82   (concat "^[\t ]*END[\t ]+"
83           (regexp-opt '("IF"
84                         "DATA"
85                         "LOOP"
86                         "REPEAT"
87                         "INPUT") t)
88           "[\t ]*")
89
90   ;; Note that "END CASE" and "END FILE" do not unindent.
91
92   "constructs which cause end of indentation"
93 )
94
95
96  
97 (defun pspp-indent-line ()
98   "Indent current line as PSPP code."
99
100   (beginning-of-line)
101   (let (
102         (verbatim nil)
103         (the-indent 0)          ; Default indent to column 0
104         (case-fold-search t)
105         )
106
107     (if (bobp)
108         (setq the-indent 0)     ; First line is always non-indented
109       )
110   
111
112     (let (
113           (within-command nil)
114           (blank-line t)
115           )
116
117       ;; If the most recent non blank line ended with a `.' then
118       ;; we're at the start of a new command.
119
120       (save-excursion 
121         (while (and blank-line  (not (bobp)))
122           (forward-line -1)
123         
124           (if (and (not (pspp-data-block-p)) (not (looking-at "^[ \t]*$")))
125               (progn 
126                 (setq blank-line nil)
127             
128                 (if (not (looking-at ".*\\.[ \t]*$"))
129                     (setq within-command t)
130                   )
131                 )
132             )
133           )
134         )
135
136
137       ;; If we're not at the start of a new command, then add an indent.
138       (if within-command 
139           (set 'the-indent (+ 1 the-indent))
140         )
141       )
142
143
144     ;; Set the indentation according to the DO - END blocks
145     (save-excursion
146       (beginning-of-line)
147       (while (not (bobp))
148         (beginning-of-line)
149         (if  (not (pspp-comment-p))
150             (cond 
151              (
152               (save-excursion 
153                 (forward-line -1)
154                 (looking-at pspp-indenters)
155                 )
156               (set 'the-indent (+ the-indent 1) )
157               )
158                
159              ( (looking-at pspp-unindenters)
160                (set 'the-indent (- the-indent 1) )
161                )
162              )
163           )
164         (forward-line -1)
165         )
166       )
167
168     (save-excursion
169       (beginning-of-line)
170       (if (looking-at "^[\t ]*ELSE")
171           (set 'the-indent (- the-indent 1)))
172       )
173
174     ;; Stuff in the data-blocks should be untouched
175     (if (not (pspp-data-block-p))  (indent-line-to (* pspp-indent-width the-indent)))
176     )
177 )
178
179
180 (defun pspp-comment-start-line-p ()
181   "Returns t if the current line is the first line of a comment, nil otherwise"
182   (beginning-of-line)
183   (or (looking-at "^\*")
184       (looking-at "^[\t ]*COMMENT[\t ]")
185       )
186   )
187
188
189 (defun pspp-comment-end-line-p ()
190   "Returns t if the current line is the candidate for the last line of a comment, nil otherwise"
191   (beginning-of-line)
192   (looking-at ".*\\.[\t ]*$")
193   )
194
195
196
197 (defun pspp-comment-p ()
198   "Returns t if point is in a comment.  Nil otherwise."
199   (if (pspp-data-block-p)
200       nil
201     (let (
202           (pspp-comment-start-found nil)
203           (pspp-comment-end-found nil)
204           (pspp-single-line-comment nil)
205           (lines 1)
206           )
207       (save-excursion
208         (end-of-line)
209         (while   (and (>= lines 0)
210                       (not pspp-comment-start-found)
211                       (not pspp-comment-end-found)
212                       )
213           (beginning-of-line)
214           (if (pspp-comment-start-line-p) (set 'pspp-comment-start-found t))
215           (if (bobp) 
216               (set 'pspp-comment-end-found nil)
217             (save-excursion 
218               (forward-line -1)
219               (if (pspp-comment-end-line-p) (set 'pspp-comment-end-found t))
220               )
221             )
222           (set 'lines (forward-line -1))
223           )
224         )
225
226       (save-excursion 
227         (set 'pspp-single-line-comment (and
228                                         (pspp-comment-start-line-p)
229                                         (pspp-comment-end-line-p)))
230         )
231       
232
233       (or pspp-single-line-comment
234           (and pspp-comment-start-found (not pspp-comment-end-found)))
235       )
236     )
237   )
238
239 (defvar pspp-mode-syntax-table
240   (let (
241         (x-pspp-mode-syntax-table (make-syntax-table))
242         )
243         
244     ;; Special chars allowed in variables
245       (modify-syntax-entry ?#  "w" x-pspp-mode-syntax-table)
246       (modify-syntax-entry ?@  "w" x-pspp-mode-syntax-table)
247       (modify-syntax-entry ?$  "w" x-pspp-mode-syntax-table)
248
249     ;; Comment syntax
250     ;;  This is incomplete, because:
251     ;;  a) Comments can also be given by COMMENT
252     ;;  b) The sequence .\n* is interpreted incorrectly.
253     
254       (modify-syntax-entry ?*  ". 2" x-pspp-mode-syntax-table)
255       (modify-syntax-entry ?.  ". 3" x-pspp-mode-syntax-table)
256       (modify-syntax-entry ?\n  "- 41" x-pspp-mode-syntax-table)
257
258
259     ;; String delimiters
260       (modify-syntax-entry ?'  "\"" x-pspp-mode-syntax-table)
261       (modify-syntax-entry ?"  "\"" x-pspp-mode-syntax-table)
262       
263     x-pspp-mode-syntax-table)
264   
265     "Syntax table for pspp-mode")
266   
267
268 (defconst pspp-font-lock-keywords
269   (list
270
271    (cons  (concat "\\<"
272                   (regexp-opt '(
273                                 "END DATA"
274                                 "ACF"                    
275                                 "ADD FILES"              
276                                 "ADD VALUE LABELS"       
277                                 "AGGREGATE"              
278                                 "ANOVA"                  
279                                 "APPLY DICTIONARY"       
280                                 "AREG"                   
281                                 "ARIMA"                  
282                                 "AUTORECODE"             
283                                 "BEGIN DATA"             
284                                 "BREAK"                  
285                                 "CASEPLOT"               
286                                 "CASESTOVARS"             
287                                 "CCF"                    
288                                 "CLEAR TRANSFORMATIONS"  
289                                 "CLUSTER"                
290                                 "COMPUTE"                
291                                 "CONJOINT"               
292                                 "CORRELATIONS"            
293                                 "COXREG"                 
294                                 "COUNT"                  
295                                 "CREATE"                 
296                                 "CROSSTABS"              
297                                 "CURVEFIT"               
298                                 "DATA LIST"              
299                                 "DATE"                   
300                                 "DEBUG CASEFILE"          
301                                 "DEBUG EVALUATE"          
302                                 "DEBUG MOMENTS"   
303                                 "DEBUG POOL"              
304                                 "DELETE VARIABLES"       
305                                 "DESCRIPTIVES"           
306                                 "DISCRIMINANT"           
307                                 "DISPLAY"                
308                                 "DOCUMENT"               
309                                 "DO IF"                  
310                                 "DO REPEAT"              
311                                 "DROP DOCUMENTS"         
312                                 "ECHO"                   
313                                 "EDIT"                   
314                                 "ELSE"                   
315                                 "ELSE IF"                
316                                 "END CASE"               
317                                 "END FILE"               
318                                 "END FILE TYPE"          
319                                 "END IF"                 
320                                 "END INPUT PROGRAM"      
321                                 "END LOOP"               
322                                 "END REPEAT"             
323                                 "ERASE"                  
324                                 "EXAMINE"                
325                                 "EXECUTE"                
326                                 "EXIT"                   
327                                 "EXPORT"                 
328                                 "FACTOR"                 
329                                 "FILE HANDLE"            
330                                 "FILE LABEL"             
331                                 "FILE TYPE"              
332                                 "FILTER"                 
333                                 "FINISH"                 
334                                 "FIT"                    
335                                 "FLIP"                    
336                                 "FORMATS"                
337                                 "FREQUENCIES"            
338                                 "GENLOG"                 
339                                 "GET"                    
340                                 "GET TRANSLATE"          
341                                 "GLM"                    
342                                 "GRAPH"                  
343                                 "HILOGLINEAR"            
344                                 "HOST"                   
345                                 "IF"                     
346                                 "IGRAPH"                 
347                                 "IMPORT"                 
348                                 "INCLUDE"                
349                                 "INFO"                   
350                                 "INPUT MATRIX"           
351                                 "INPUT PROGRAM"          
352                                 "KEYED DATA LIST"        
353                                 "LEAVE"                  
354                                 "LIST"                   
355                                 "LOGLINEAR"              
356                                 "LOGISITIC REGRESSION"   
357                                 "LOOP"                   
358                                 "MATCH FILES"            
359                                 "MATRIX DATA"            
360                                 "MCONVERT"               
361                                 "MEANS"                  
362                                 "MISSING VALUES"         
363                                 "MODIFY VARS"            
364                                 "MULT RESPONSE"          
365                                 "MVA"                    
366                                 "NEW FILE"               
367                                 "N"                      
368                                 "N OF CASES"             
369                                 "NLR"                    
370                                 "NONPAR CORR"            
371                                 "NPAR TESTS"             
372                                 "NUMBERED"               
373                                 "NUMERIC"                
374                                 "OLAP CUBES"             
375                                 "OMS"                    
376                                 "ONEWAY"                 
377                                 "ORTHOPLAN"              
378                                 "PACF"                   
379                                 "PARTIAL CORR"           
380                                 "PEARSON CORRELATIONS"    
381                                 "PERMISSIONS"            
382                                 "PLOT"                   
383                                 "POINT"                  
384                                 "PPLOT"                  
385                                 "PREDICT"                
386                                 "PRESERVE"                
387                                 "PRINT EJECT"            
388                                 "PRINT"                  
389                                 "PRINT FORMATS"          
390                                 "PRINT SPACE"            
391                                 "PROCEDURE OUTPUT"       
392                                 "PROCESS IF"             
393                                 "PROXIMITIES"            
394                                 "Q"                      
395                                 "QUICK CLUSTER"          
396                                 "QUIT"                   
397                                 "RANK"                   
398                                 "RECODE"                 
399                                 "RECORD TYPE"            
400                                 "REFORMAT"               
401                                 "REGRESSION"             
402                                 "RENAME VARIABLES"       
403                                 "REPEATING DATA"         
404                                 "REPORT"                 
405                                 "REREAD"                 
406                                 "RESTORE"                 
407                                 "RMV"                    
408                                 "SAMPLE"                 
409                                 "SAVE"                   
410                                 "SAVE TRANSLATE"         
411                                 "SCRIPT"                 
412                                 "SELECT IF"              
413                                 "SET"                    
414                                 "SHOW"                   
415                                 "SORT CASES"             
416                                 "SORT"                   
417                                 "SPCHART"                
418                                 "SPLIT FILE"             
419                                 "STRING"                 
420                                 "SUBTITLE"               
421                                 "SUMMARIZE"              
422                                 "SURVIVAL"               
423                                 "SYSFILE INFO"           
424                                 "TEMPORARY"              
425                                 "TITLE"                  
426                                 "TSET"                   
427                                 "TSHOW"                  
428                                 "TSPLOT"                 
429                                 "T-TEST"                 
430                                 "UNIANOVA"               
431                                 "UNNUMBERED"             
432                                 "UPDATE"                 
433                                 "USE"                     
434                                 "VALUE LABELS"           
435                                 "VARIABLE ALIGNMENT"     
436                                 "VARIABLE LABELS"        
437                                 "VARIABLE LEVEL"         
438                                 "VARIABLE WIDTH"         
439                                 "VARSTOCASES"             
440                                 "VECTOR"                 
441                                 "VERIFY"                 
442                                 "WEIGHT"                 
443                                 "WRITE"                  
444                                 "WRITE FORMATS"          
445                                 "XSAVE") t) "\\>" )
446           'font-lock-builtin-face)
447
448    (cons 
449     (concat "\\<" (regexp-opt '(
450                                 "ALL" "AND" "BY" "EQ" "GE" "GT" "LE" "LT"
451                                 "NE" "NOT" "OR" "TO" "WITH"
452                                 ) t ) "\\>") 'font-lock-keyword-face)
453
454
455    (cons 
456     (concat "\\<"
457             (regexp-opt '(
458                           "ABS"
459                           "ACOS"
460                           "ANY"
461                           "ANY"
462                           "ARCOS"
463                           "ARSIN"
464                           "ARTAN"
465                           "ASIN"
466                           "ATAN"
467                           "CDF.BERNOULLI"
468                           "CDF.BETA"
469                           "CDF.BINOM"
470                           "CDF.BVNOR"
471                           "CDF.CAUCHY"
472                           "CDF.CHISQ"
473                           "CDF.EXP"
474                           "CDF.F"
475                           "CDF.GAMMA"
476                           "CDF.GEOM"
477                           "CDF.HALFNRM"
478                           "CDF.HYPER"
479                           "CDF.IGAUSS"
480                           "CDF.LAPLACE"
481                           "CDF.LNORMAL"
482                           "CDF.LOGISTIC"
483                           "CDF.NEGBIN"
484                           "CDF.NORMAL"
485                           "CDF.PARETO"
486                           "CDF.POISSON"
487                           "CDF.RAYLEIGH"
488                           "CDF.SMOD"
489                           "CDF.SRANGE"
490                           "CDF.T"
491                           "CDF.T1G"
492                           "CDF.T2G"
493                           "CDF.UNIFORM"
494                           "CDF.WEIBULL"
495                           "CDFNORM"
496                           "CFVAR"
497                           "CONCAT"
498                           "COS"
499                           "CTIME.DAYS"
500                           "CTIME.HOURS"
501                           "CTIME.MINUTES"
502                           "CTIME.SECONDS"
503                           "DATE.DMY"
504                           "DATE.MDY"
505                           "DATE.MOYR"
506                           "DATE.QYR"
507                           "DATE.WKYR"
508                           "DATE.YRDAY"
509                           "EXP"
510                           "IDF.BETA"
511                           "IDF.CAUCHY"
512                           "IDF.CHISQ"
513                           "IDF.EXP"
514                           "IDF.F"
515                           "IDF.GAMMA"
516                           "IDF.HALFNRM"
517                           "IDF.IGAUSS"
518                           "IDF.LAPLACE"
519                           "IDF.LNORMAL"
520                           "IDF.LOGISTIC"
521                           "IDF.NORMAL"
522                           "IDF.PARETO"
523                           "IDF.RAYLEIGH"
524                           "IDF.SMOD"
525                           "IDF.SRANGE"
526                           "IDF.T"
527                           "IDF.T1G"
528                           "IDF.T2G"
529                           "IDF.UNIFORM"
530                           "IDF.WEIBULL"
531                           "INDEX"
532                           "INDEX"
533                           "LAG"
534                           "LAG"
535                           "LAG"
536                           "LAG"
537                           "LENGTH"
538                           "LG10"
539                           "LN"
540                           "LNGAMMA"
541                           "LOWER"
542                           "LPAD"
543                           "LPAD"
544                           "LTRIM"
545                           "LTRIM"
546                           "MAX"
547                           "MAX"
548                           "MBLEN.BYTE"
549                           "MEAN"
550                           "MIN"
551                           "MIN"
552                           "MISSING"
553                           "MOD"
554                           "MOD10"
555                           "NCDF.BETA"
556                           "NCDF.CHISQ"
557                           "NCDF.F"
558                           "NCDF.T"
559                           "NMISS"
560                           "NORMAL"
561                           "NPDF.BETA"
562                           "NPDF.CHISQ"
563                           "NPDF.F"
564                           "NPDF.T"
565                           "NUMBER"
566                           "NVALID"
567                           "PDF.BERNOULLI"
568                           "PDF.BETA"
569                           "PDF.BINOM"
570                           "PDF.BVNOR"
571                           "PDF.CAUCHY"
572                           "PDF.CHISQ"
573                           "PDF.EXP"
574                           "PDF.F"
575                           "PDF.GAMMA"
576                           "PDF.GEOM"
577                           "PDF.HALFNRM"
578                           "PDF.HYPER"
579                           "PDF.IGAUSS"
580                           "PDF.LANDAU"
581                           "PDF.LAPLACE"
582                           "PDF.LNORMAL"
583                           "PDF.LOG"
584                           "PDF.LOGISTIC"
585                           "PDF.NEGBIN"
586                           "PDF.NORMAL"
587                           "PDF.NTAIL"
588                           "PDF.PARETO"
589                           "PDF.POISSON"
590                           "PDF.RAYLEIGH"
591                           "PDF.RTAIL"
592                           "PDF.T"
593                           "PDF.T1G"
594                           "PDF.T2G"
595                           "PDF.UNIFORM"
596                           "PDF.WEIBULL"
597                           "PDF.XPOWER"
598                           "PROBIT"
599                           "RANGE"
600                           "RANGE"
601                           "RINDEX"
602                           "RINDEX"
603                           "RND"
604                           "RPAD"
605                           "RPAD"
606                           "RTRIM"
607                           "RTRIM"
608                           "RV.BERNOULLI"
609                           "RV.BETA"
610                           "RV.BINOM"
611                           "RV.CAUCHY"
612                           "RV.CHISQ"
613                           "RV.EXP"
614                           "RV.F"
615                           "RV.GAMMA"
616                           "RV.GEOM"
617                           "RV.HALFNRM"
618                           "RV.HYPER"
619                           "RV.IGAUSS"
620                           "RV.LANDAU"
621                           "RV.LAPLACE"
622                           "RV.LEVY"
623                           "RV.LNORMAL"
624                           "RV.LOG"
625                           "RV.LOGISTIC"
626                           "RV.LVSKEW"
627                           "RV.NEGBIN"
628                           "RV.NORMAL"
629                           "RV.NTAIL"
630                           "RV.PARETO"
631                           "RV.POISSON"
632                           "RV.RAYLEIGH"
633                           "RV.RTAIL"
634                           "RV.T"
635                           "RV.T1G"
636                           "RV.T2G"
637                           "RV.UNIFORM"
638                           "RV.WEIBULL"
639                           "RV.XPOWER"
640                           "SD"
641                           "SIG.CHISQ"
642                           "SIG.F"
643                           "SIN"
644                           "SQRT"
645                           "STRING"
646                           "SUBSTR"
647                           "SUBSTR"
648                           "SUM"
649                           "SYSMIS"
650                           "SYSMIS"
651                           "TAN"
652                           "TIME.DAYS"
653                           "TIME.HMS"
654                           "TRUNC"
655                           "UNIFORM"
656                           "UPCASE"
657                           "VALUE"
658                           "VARIANCE"
659                           "XDATE.DATE"
660                           "XDATE.HOUR"
661                           "XDATE.JDAY"
662                           "XDATE.MDAY"
663                           "XDATE.MINUTE"
664                           "XDATE.MONTH"
665                           "XDATE.QUARTER"
666                           "XDATE.SECOND"
667                           "XDATE.TDAY"
668                           "XDATE.TIME"
669                           "XDATE.WEEK"
670                           "XDATE.WKDAY"
671                           "XDATE.YEAR"
672                           "YRMODA" )
673                         t) "\\>" )  'font-lock-function-name-face)
674
675   '( "\\<[#$@a-zA-Z][a-zA-Z0-9_]*\\>" . font-lock-variable-name-face)
676
677
678
679   )
680 "Highlighting expressions for PSPP mode.")
681
682
683 (defun pspp-mode ()
684   (interactive)
685   (kill-all-local-variables)
686   (use-local-map pspp-mode-map)
687   (set-syntax-table pspp-mode-syntax-table)
688
689   (set (make-local-variable 'font-lock-keywords-case-fold-search) t)
690   (set (make-local-variable 'font-lock-defaults) '(pspp-font-lock-keywords))
691
692   (set (make-local-variable 'indent-line-function) 'pspp-indent-line)  
693   (set (make-local-variable 'comment-start ) "* ")
694   (set (make-local-variable 'compile-command)
695        (concat "pspp "
696                buffer-file-name
697                ))
698
699   (setq major-mode 'pspp-mode)
700   (setq mode-name "PSPP")
701   (run-hooks 'pspp-mode-hook))
702
703 (provide 'pspp-mode)
704
705 ;;; pspp-mode.el ends here
706