1
;;; essl-sas.el --- SAS customization
3
;; Copyright (C) 1997--2009 A.J. Rossini, Rich M. Heiberger, Martin
4
;; Maechler, Kurt Hornik, Rodney Sparapani, and Stephen Eglen.
6
;; Original Authors: Richard M. Heiberger,
9
;; Created: 20 Aug 1997
10
;; Maintainers: ESS-core <ESS-core@stat.math.ethz.ch>
12
;; Keywords: start up, configuration.
14
;; This file is part of ESS (Emacs Speaks Statistics).
16
;; This file is free software; you can redistribute it and/or modify
17
;; it under the terms of the GNU General Public License as published by
18
;; the Free Software Foundation; either version 2, or (at your option)
21
;; This file is distributed in the hope that it will be useful,
22
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
23
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24
;; GNU General Public License for more details.
26
;; You should have received a copy of the GNU General Public License
27
;; along with GNU Emacs; see the file COPYING. If not, write to
28
;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
31
;;; This is based upon Version 1.4 of SAS mode:
34
;;; sas-mode: indent, run etc, SAS programs.
35
;;; Copyright (C) 1994--1997 Tom Cook
37
;;; Dept. of Biostatistics
38
;;; University of Wisconsin - Madison
40
;;; cook@biostat.wisc.edu
43
;;; Menu code for XEmacs/Lucid emacs and startup mods
44
;;; contributed by arossini@biostats.hmc.psu.edu
46
;;; Last change: 2/1/95
47
;;; Last change: 01/15/02
49
(ess-message "[essl-sas:] (require 'ess) ...")
51
(ess-message "[essl-sas:] (require 'ess-mode) ...")
55
(ess-message "[essl-sas:] (autoload ..) (def** ..) etc ...")
57
(autoload 'ess-transcript-mode "ess-trns" "ESS source eval mode." t)
59
(put 'ess-transcript-minor-mode 'permanent-local t)
60
(or (assq 'ess-transcript-minor-mode minor-mode-alist)
61
(setq minor-mode-alist
62
(append minor-mode-alist
63
(list '(ess-transcript-minor-mode " ESStr")))))
65
(put 'ess-listing-minor-mode 'permanent-local t)
66
(or (assq 'ess-listing-minor-mode minor-mode-alist)
67
(setq minor-mode-alist
68
(append minor-mode-alist
69
(list '(ess-listing-minor-mode " ESSlst")))))
71
(defun ess-transcript-minor-mode (&optional arg)
72
"Toggle Ess-Transcript minor mode.
73
With arg, turn Ess-Transcript minor mode on if arg is positive, off
74
otherwise. See the command `ess-transcript-mode' for more information
77
(setq ess-transcript-minor-mode
78
(if (null arg) (not ess-transcript-minor-mode)
79
(> (prefix-numeric-value arg) 0)))
80
(force-mode-line-update)
81
(setq mode-line-process
82
'(" [" ess-local-process-name "]")))
84
(defun ess-listing-minor-mode (&optional arg)
85
"Toggle Ess-Listing minor mode.
86
With arg, turn Ess-Listing minor mode on if arg is positive, off
87
otherwise. Ess-Listing mode is used solely to place an indicator on
90
(setq ess-listing-minor-mode
91
(if (null arg) (not ess-listing-minor-mode)
92
(> (prefix-numeric-value arg) 0)))
93
(force-mode-line-update)
94
(setq mode-line-process
95
'(" [" ess-local-process-name "]")))
97
(defun SAS-log-mode ()
98
"`ess-transcript-mode' for SAS."
101
(ess-transcript-minor-mode 1)
102
(toggle-read-only t)) ;; to protect the buffer.
104
(defun SAS-listing-mode()
105
"Fundamental mode with `ess-listing-minor-mode' and read-only."
108
(ess-listing-minor-mode 1)
109
(use-local-map sas-mode-local-map)
110
(toggle-read-only t)) ;; to protect the buffer.
112
(fset 'sas-log-mode 'SAS-log-mode)
113
(fset 'SAS-transcript-mode 'SAS-log-mode)
114
(fset 'sas-transcript-mode 'SAS-log-mode)
115
(fset 'sas-mode 'SAS-mode)
116
(fset 'sas-listing-mode 'SAS-listing-mode)
118
(defcustom sas-indent-width 4
119
"*Amount to indent sas statements."
123
(defcustom sas-indent-ignore-comment "*"
124
"*Comments that start with this string are ignored in indentation."
128
(defcustom sas-require-confirmation t
129
"*Require confirmation when revisiting a modified sas-output file."
133
;; user can specify the sas program name
134
(defcustom sas-program
135
(if (equal system-type 'Apple-Macintosh) "invoke SAS using program file" "sas")
136
"*Command to invoke SAS, default for buffer-local `ess-sas-submit-command'."
140
(defcustom sas-pre-run-hook nil
141
"Hook to execute prior to running SAS via `submit-sas'."
145
;never used--see ess-sas-submit-command-options in essa-sas.el
146
;(defcustom sas-options-string ""
147
; "*Options to be passed to sas as if typed on the command line."
151
(defcustom sas-notify t
152
"*Beep and display message when job is done."
156
(defcustom sas-error-notify t
157
"*If `sas-notify' t, indicate errors in log file upon completion."
161
(defcustom sas-get-options nil
162
"Options to be passed to SAS in sas-get-dataset."
164
:type '(choice (const nil) string))
166
(defcustom sas-get-options-history nil
167
"History list of Options passed to SAS in sas-get-dataset."
170
(defcustom sas-page-number-max-line 3
171
"*Number of lines from the page break, to search for the page
176
(defcustom sas-notify-popup nil
177
"*If this and sas-notify are t), popup a window when SAS job ends."
181
(defcustom sas-tmp-libname "_tmp_"
182
"*Libname to use for sas-get-dataset."
186
(defcustom sas-file-name nil
187
"*The name of the current sas file."
189
:type '(choice (const nil) file))
191
;; The next two are ``the inside of [...] in a regexp'' to be used in
192
;; (skip-chars-(for|back)ward SAS-..-chars)
193
(defcustom sas-white-chars " \t\n\f"
194
"This does NOT escape blanks (RMH, 2000/03/20)."
198
(defcustom sas-comment-chars (concat sas-white-chars ";")
203
(defcustom ess-sas-run-regexp-opt t
204
"If you do not want to run regexp-opt, then set to nil."
206
:type '(choice (const nil) string))
210
(defvar sas-buffer-name nil)
211
(defvar sas-file-root nil)
212
(defvar sas-submitable nil)
213
(defvar sas-dataset nil)
214
(defvar SAS-syntax-table nil "Syntax table for SAS code.")
216
(if SAS-syntax-table nil
217
(setq SAS-syntax-table (make-syntax-table))
219
;; (if (equal system-type 'windows-nt)
220
;; ;; backslash is punctuation (used in MS file names)
221
;; (modify-syntax-entry ?\\ "." SAS-syntax-table)
222
;; ;; backslash is an escape character
223
;; (modify-syntax-entry ?\\ "\\" SAS-syntax-table))
224
(modify-syntax-entry ?\\ "." SAS-syntax-table) ;; backslash is punctuation
225
(modify-syntax-entry ?+ "." SAS-syntax-table)
226
(modify-syntax-entry ?- "." SAS-syntax-table)
227
(modify-syntax-entry ?= "." SAS-syntax-table)
228
(modify-syntax-entry ?% "w" SAS-syntax-table)
229
(modify-syntax-entry ?< "." SAS-syntax-table)
230
(modify-syntax-entry ?> "." SAS-syntax-table)
231
(modify-syntax-entry ?& "w" SAS-syntax-table)
232
(modify-syntax-entry ?| "." SAS-syntax-table)
233
(modify-syntax-entry ?\' "\"" SAS-syntax-table)
234
(modify-syntax-entry ?* ". 23" SAS-syntax-table) ; comment character
235
(modify-syntax-entry ?\; "." SAS-syntax-table)
236
(modify-syntax-entry ?_ "w" SAS-syntax-table)
237
(modify-syntax-entry ?< "." SAS-syntax-table)
238
(modify-syntax-entry ?> "." SAS-syntax-table)
239
(modify-syntax-entry ?/ ". 14" SAS-syntax-table) ; comment character
240
(modify-syntax-entry ?. "w" SAS-syntax-table))
242
(require 'font-lock); fontification also works in terminals!
243
;; (if (or window-system
244
;; noninteractive) ; compilation!
248
(defvar SAS-mode-font-lock-keywords
249
(if ess-sas-run-regexp-opt
251
;; .log NOTE: messages
252
(cons "^NOTE: .*$" font-lock-comment-face)
253
(cons "^ [^ ].*[.]$" font-lock-comment-face)
254
(cons "^ [a-z].*[a-z][ ]?$" font-lock-comment-face)
255
(cons "^ Engine:[ ]+V.+$" font-lock-comment-face)
256
(cons "^ Physical Name:[ ]+.+$" font-lock-comment-face)
257
(cons "^ \\(cpu\\|real\\) time[ ]+[0-9].*$"
258
font-lock-comment-face)
259
(cons "^ decimal may be shifted by the"
260
font-lock-comment-face)
261
(cons "^NOTE: The infile " font-lock-comment-face)
262
(cons "^NOTE: 1 record was read from the infile "
263
font-lock-comment-face)
264
(cons "^NOTE: [1-9][0-9]* records were read from the infile "
265
font-lock-comment-face)
266
(cons "^ Filename=.*,$" font-lock-comment-face)
267
(cons "^ File Name=.*,$" font-lock-comment-face)
268
(cons "^ File $" font-lock-comment-face)
269
(cons "^ Name=.*,$" font-lock-comment-face)
270
(cons "^ File List=(" font-lock-comment-face)
271
(cons "^ List=(" font-lock-comment-face)
272
(cons "^ Owner Name=.*,$" font-lock-comment-face)
273
(cons "^ Access Permission=.*,$" font-lock-comment-face)
274
(cons "^ Last Modified=.*,?$" font-lock-comment-face)
275
(cons "^ File Size (bytes)=[0-9]+$" font-lock-comment-face)
276
(cons "^ Pipe command=" font-lock-comment-face)
277
(cons "^NOTE: The file " font-lock-comment-face)
278
(cons "^NOTE: 1 record was written to the file "
279
font-lock-comment-face)
280
(cons "^NOTE: [1-9][0-9]* records were written to the file "
281
font-lock-comment-face)
282
(cons "^NOTE: PROC LOGISTIC is modeling the probability that"
283
font-lock-comment-face)
284
(cons "^NOTE: PROC GENMOD is modeling the probability that"
285
font-lock-comment-face)
286
(cons "^1[ ]+The SAS System.*$" font-lock-comment-face)
287
(cons "^\014.*$" font-lock-comment-face)
288
(cons "[*][*][*] ANNOTATE macros are now available [*][*][*]"
289
font-lock-comment-face)
290
(cons "For further information on ANNOTATE macros, enter,"
291
font-lock-comment-face)
292
(cons "\\(or \\)?%HELPANO.*$"
293
font-lock-comment-face)
294
(cons "^Local Variables:$" font-lock-comment-face)
295
(cons "^End:$" font-lock-comment-face)
296
(cons "^MPRINT([_A-Z0-9]+)" font-lock-comment-face)
298
;; .log ERROR: messages
299
(cons "^ERROR\\( [0-9]+-[1-9][0-9][0-9]\\)?: .*$"
300
font-lock-keyword-face)
302
(cons "^ [^ ].*\\([.][ ]?\\|[,a-z][ ]\\)$"
303
font-lock-keyword-face)
305
(cons "^ [^ ].*\\([.][ ]?\\|[,a-z][ ]\\)$"
306
font-lock-keyword-face)
308
(cons "^ [^ ].*\\([.][ ]?\\|[,a-z][ ]\\)$"
309
font-lock-keyword-face)
311
(cons "^ [^ ].*\\([.][ ]?\\|[,a-z][ ]\\)$"
312
font-lock-keyword-face)
313
(cons "^ a format name." font-lock-keyword-face)
314
(cons "^ where a numeric operand is required. The condition was: "
315
font-lock-keyword-face)
316
(cons "[ ][_]+$" font-lock-keyword-face)
318
;; .log WARNING: messages
319
(cons "^WARNING\\( [0-9]+-[1-9][0-9][0-9]\\)?: .*$"
320
font-lock-function-name-face)
322
(cons "^ [^ ].*\\([.][ ]?\\|[,a-z][ ]\\)$"
323
font-lock-function-name-face)
325
(cons "^ [^ ].*\\([.][ ]?\\|[,a-z][ ]\\)$"
326
font-lock-function-name-face)
328
(cons "^ [^ ].*\\([.][ ]?\\|[,a-z][ ]\\)$"
329
font-lock-function-name-face)
331
(cons "^ [^ ].*\\([.][ ]?\\|[,a-z][ ]\\)$"
332
font-lock-function-name-face)
335
;; /* */ style handled by grammar above
336
(cons "\\(^[0-9]*\\|[:;!]\\)[ \t]*%?\\*[^;/][^;]*;"
337
font-lock-comment-face)
339
; these over-rides need to come before the more general declarations
340
(cons "\\<and(" font-lock-function-name-face)
341
(cons "\\<data=" font-lock-keyword-face)
342
(cons "\\<in:(" font-lock-function-name-face)
343
(cons "\\<index(" font-lock-function-name-face)
344
(cons "\\<input(" font-lock-function-name-face)
345
(cons "\\<libname(" font-lock-function-name-face)
346
(cons "\\<not(" font-lock-function-name-face)
347
(cons "\\<or(" font-lock-function-name-face)
348
(cons "\\<put(" font-lock-function-name-face)
349
(cons "\\<sum(" font-lock-function-name-face)
351
; other idiosyncratic keywords
352
;(cons "key=" font-lock-keyword-face)
353
;(cons "/unique" font-lock-keyword-face)
355
;; SAS execution blocks: DATA, %MACRO/%MEND, %DO/%END, etc.
359
"%do" "%to" "%by" "%end"
361
"%if" "%then" "%else"
362
"%global" "%inc" "%include" "%input" "%local" "%let" "%put" "%sysexec"
363
) 'words) font-lock-constant-face)
365
;; SAS execution blocks that must be followed by a semi-colon
369
"run;" "quit;" "endsas;"
370
"cards;" "cards4;" "datalines;" "datalines4;" "lines;" "lines4;"
372
font-lock-constant-face)
374
;; SAS statements that must be followed by a semi-colon
378
"end;" "list;" "lostcard;" "page;" "return;" "stop;"
380
font-lock-keyword-face)
382
;; SAS statements that must be followed by an equal sign
386
"compress=" "in=" "out=" "sortedby="
388
font-lock-keyword-face)
390
;;; ;; SAS procedure names
391
(cons (concat "\\<proc[ ]+"
393
;; SAS base and SAS/Graph
395
"calendar" "catalog" "chart" "cimport" "cport" "compare" "contents" "copy" "corr"
396
"datasets" "dbcstab" "display"
398
"format" "forms" "freq" "fsbrowse" "fsedit" "fsletter" "fslist" "fsview"
399
"ganno" "gchart" "gcontour" "gdevice" "geocode" "gfont" "gimport" "ginside"
400
"gkeymap" "gmap" "goptions" "gplot" "gprint" "gproject" "greduce" "gremove"
401
"greplay" "gslide" "gtestit" "g3d" "g3grid"
402
"iml" "import" "insight"
405
"plot" "pmenu" "print" "printto"
406
"rank" "registry" "report"
407
"sort" "sql" "standard" "summary"
408
"tabulate" "template" "timeplot" "transpose" "trantab"
411
;;SAS/Stat and SAS/ETS
412
"aceclus" "anova" "arima" "autoreg"
413
"bgenmod" "blifereg" "boxplot" "bphreg"
414
"calis" "cancorr" "candisc" "catmod" "citibase" "cluster" "computab" "corresp"
417
"factor" "fastclus" "forecast"
418
"gam" "genmod" "glimmix" "glm" "glmmod" "glmpower" "glmselect"
421
"lattice" "lifereg" "lifetest" "loess" "logistic"
422
"mds" "mixed" "modeclus" "model" "mortgage" "multtest"
423
"nested" "nlin" "nlmixed" "npar1way"
425
"pdlreg" "phreg" "plan" "pls" "power" "princomp" "prinqual" "probit"
427
"score" "sim2d" "simlin" "spectra" "statespace" "stdize" "stepdisc"
428
"surveymeans" "surveyreg" "surveyselect" "syslin"
429
"tphreg" "tpspline" "transreg" "tree" "ttest"
430
"varclus" "varcomp" "variogram"
432
) 'words)) font-lock-constant-face)
436
; "do[ \t]*" (regexp-opt '("over" "until" "while") t) "?"
438
; font-lock-keyword-face)
444
"do" "to" "by" "go" "goto"
445
"abort" "and" "array" "attrib"
447
"change" "class" "contains"
448
"delete" "display" "dm" "drop"
449
"else" "error" "exchange" "exclude"
450
"file" "filename" "format" "freq"
451
"footnote" "footnote1" "footnote2" "footnote3" "footnote4" "footnote5"
452
"footnote6" "footnote7" "footnote8" "footnote9" "footnote10"
455
"id" "if" "index" "infile" "informat" "input" ; "is" rarely used, but common false pos.
457
"label" "le" "length" "libname" "like" "link" "lsmeans" "lt"
458
"manova" "means" "merge" "missing" "model" "modify"
459
"ne" "not" "note" "null"
460
"ods" "options" "or" "output" "otherwise"
461
"pageby" "plot" "put"
462
"random" "rename" "repeated" "retain"
463
"same" "save" "select" "set" "skip" "sum" "sumby"
464
"table" "tables" "then"
465
"title" "title1" "title2" "title3" "title4" "title5"
466
"title6" "title7" "title8" "title9" "title10"
469
"weight" "where" "window" "with"
472
font-lock-keyword-face)
474
;; SAS/GRAPH statements not handled above
477
'("axis" "legend" "pattern" "symbol")) "\\([1-9][0-9]?\\)?"
479
font-lock-keyword-face)
481
;; SAS functions and SAS macro functions
482
(cons "%[a-z_][a-z_0-9]*[(;]" font-lock-function-name-face)
483
;(cons "\\<call[ \t]+[a-z]+(" font-lock-function-name-face)
488
"abs" "arcos" "arsin" "atan"
490
"call execute" "call label" "call module" "call modulei"
491
"call poke" "call ranbin" "call rancau" "call ranexp"
492
"call rangam" "call rannor" "call ranpoi" "call rantbl"
493
"call rantri" "call ranuni" "call rxchange" "call rxfree"
494
"call rxsubstr" "call set" "call symput" "call system"
495
"cdf" "ceil" "cinv" "collate" "compress" "convx" "convxp" "cos" "cosh" "css" "cv"
496
"daccdb" "daccdbsl" "daccsl" "daccsyd" "dacctab"
497
"depdb" "depdbsl" "depsl" "depsyd" "deptab"
498
"date" "datejul" "datepart" "datetime" "day" "dhms" "dif" "digamma" "dim"
500
"finv" "fipname" "fipnamel" "fipstate" "floor" "fuzz"
502
"hbound" "hms" "hour"
503
"in" "index" "indexc" "input" "int" "intck" "intnx" "intrr" "irr"
506
"lag" "lbound" "left" "length" "lgamma" "log" "log10" "log2"
507
"max" "mdy" "mean" "min" "minute" "mod" "month" "mort"
508
"n" "netpv" "nmiss" "normal" "npv"
510
"probbeta" "probbnml" "probchi" "probf" "probgam" "probhypr" "probit" "probnegb" "probnorm" "probt"
513
"range" "rank" "repeat" "reverse" "right" "round" "rxmatch" "rxparse"
514
"ranbin" "rancau" "ranexp" "rangam" "rannor" "ranpoi" "rantbl" "rantri" "ranuni"
515
"saving" "scan" "second" "sign" "sin" "sinh" "sqrt"
516
"std" "stderr" "stfips" "stname" "stnamel" "substr" "sum" "symget"
517
"tan" "tanh" "time" "timepart" "tinv" "today" "translate" "trigamma" "trim" "trunc"
518
"uniform" "until" "upcase" "uss"
520
"weekday" "when" "while"
522
"zipfips" "zipname" "zipnamel" "zipstate"
524
;;; ;; SAS functions introduced in Technical Report P-222
526
"band" "blshift" "brshift" "bnot" "bor" "bxor"
530
"ibessel" "indexw" "inputc" "inputn"
537
"tnonct" "tranwrd" "trimn"
539
;;; ;; SCL functions that are known to work with SAS macro function %sysfunc
542
"dclose" "dnum" "dopen" "dread"
544
"fclose" "fetchobs" "fileexist" "finfo" "fopen" "fput" "fwrite"
545
"getoption" "getvarc" "getvarn"
547
"open" "optgetn" "optsetn"
550
"varfmt" "varlabel" "varnum" "vartype"
553
font-lock-function-name-face)
556
;; .log NOTE: messages
557
(cons "^NOTE: .*$" font-lock-constant-face)
559
;; .log ERROR: messages
560
(cons "^ERROR: .*$" font-lock-keyword-face)
562
;; .log WARNING: messages
563
(cons "^WARNING: .*$" font-lock-function-name-face)
566
;; /* */ handled by grammar above
567
;; (list "/\\*.*\\*/" 0 font-lock-comment-face t)
568
(cons "\\(^[0-9]*\\|;\\)[ \t]*\\(%?\\*\\|comment\\).*\\(;\\|$\\)" font-lock-comment-face)
570
;; SAS execution blocks, DATA/RUN, PROC/RUN, SAS Macro Statements
571
(cons "\\<%do[ \t]*\\(%until\\|%while\\)?\\>"
572
font-lock-constant-face)
573
;;(cons (concat "\\(^[0-9]*\\|;\\)[ \t]*"
574
;;"%\\(end\\|global\\|local\\|m\\(acro\\|end\\)\\)"
575
;;"\\>") font-lock-constant-face)
576
(cons "\\<%\\(end\\|global\\|local\\|m\\(acro\\|end\\)\\)\\>"
577
font-lock-constant-face)
579
(cons (concat "\\(^[0-9]*\\|;\\|):\\|%then\\|%else\\)[ \t]*"
580
"\\(data\\|endsas\\|finish\\|quit\\|run\\|start\\)[ \t\n;]")
581
font-lock-constant-face)
582
(cons (concat "\\(^[0-9]*\\|;\\|):\\|%then\\|%else\\)[ \t]*"
583
;;"proc[ \t]+[a-z][a-z_0-9]+") font-lock-constant-face)
585
;;SAS/Base, SAS/Graph, SAS/FSP and common add-ons
587
"\\|b\\(genmod\\|lifereg\\|phreg\\)"
588
"\\|c\\(a\\(lendar\\|talog\\)\\|port\\|o\\(mpare\\|ntents\\|py\\|rr\\)\\)"
589
"\\|d\\(atasets\\|bcstab\\|isplay\\)\\|ex\\(plode\\|port\\)"
590
"\\|f\\(orm\\(at\\|s\\)\\|req\\|s\\(browse\\|edit\\|l\\(etter\\|ist\\)\\|view\\)\\)"
591
"\\|g?\\(chart\\|p\\(lot\\|rint\\)\\)"
592
"\\|g\\(anno\\|contour\\|device\\|font\\|\\(key\\)?map\\|options\\|project"
593
"\\|re\\(duce\\|move\\|play\\)\\|slide\\|testit\\|3\\(d\\|grid\\)\\)"
594
"\\|\\(map\\|[cg]\\)?import\\|i\\(ml\\|nsight\\)"
595
"\\|means\\|options\\|p\\(menu\\|rintto\\)"
596
"\\|r\\(ank\\|e\\(gistry\\|port\\)\\)"
597
"\\|s\\(ort\\|ql\\|tandard\\|ummary\\)"
598
"\\|t\\(abulate\\|emplate\\|imeplot\\|ran\\(spose\\|tab\\)\\)\\|univariate"
599
;;SAS/Stat and SAS/ETS
600
"\\|a\\(ceclus\\|nova\\|rima\\|utoreg\\)\\|boxplot"
601
"\\|c\\(a\\(lis\\|n\\(corr\\|disc\\)\\|tmod\\)\\|itibase\\|luster\\|o\\(mputab\\|rresp\\)\\)"
602
"\\|discrim\\|expand\\|f\\(a\\(ctor\\|stclus\\)\\|orecast\\|req\\)"
603
"\\|g\\(enmod\\|l\\(immix\\|m\\(mod\\|power\\|select\\)?\\)\\)\\|inbreed\\|k\\(de\\|rige2d\\)"
604
"\\|l\\(attice\\|ife\\(reg\\|test\\)\\|o\\(ess\\|gistic\\)\\)"
605
"\\|m\\(ds\\|ixed\\|o\\(de\\(clus\\|l\\)\\|rtgage\\)\\|ulttest\\)"
606
"\\|n\\(ested\\|l\\(in\\|mixed\\)\\|par1way\\)\\|orthoreg"
607
"\\|p\\(dlreg\\|hreg\\|l\\(an\\|s\\)\\|ower\\|r\\(in\\(comp\\|qual\\)\\|obit\\)\\)\\|r\\(sr\\)?eg"
608
"\\|s\\(core\\|im\\(2d\\|lin\\)\\|pectra\\|t\\(atespace\\|dize\\|epdisc\\)\\|urvey\\(means\\|reg\\|select\\)\\|yslin\\)"
609
"\\|t\\(phreg\\|pspline\\|r\\(ansreg\\|ee\\)\\|test\\)"
610
"\\|var\\(clus\\|comp\\|iogram\\)\\|x11"
611
"\\)") font-lock-constant-face)
613
;;(cons (concat "\\(^[0-9]*\\|;\\|%then\\|%else\\)[ \t]*"
614
;;"\\(%\\(go[ \t]*to\\|i\\(f\\|n\\(clude\\|put\\)\\)\\|let\\|put\\|sysexec\\)\\)"
615
;;"\\>") font-lock-constant-face)
616
(cons "\\<%\\(go[ \t]*to\\|i\\(f\\|n\\(clude\\|put\\)\\)\\|let\\|put\\|sysexec\\)\\>"
617
font-lock-constant-face)
619
(cons "\\<%\\(by\\|else\\|t\\(o\\|hen\\)\\)\\>"
620
font-lock-constant-face)
622
;; SAS dataset options/PROC statements followed by an equal sign/left parentheses
626
"\\(attrib\\|by\\|compress\\|d\\(ata\\|rop\\)\\|f\\(irstobs\\|ormat\\)"
627
"\\|i\\(d\\|f\\|n\\)\\|ke\\(ep\\|y\\)\\|l\\(abel\\|ength\\)"
628
"\\|o\\(bs\\|rder\\|ut\\)\\|rename\\|s\\(ortedby\\|plit\\)"
631
font-lock-keyword-face)
632
(cons "\\<\\(in\\(:\\|dex[ \t]*=\\)?\\|until\\|wh\\(en\\|ile\\)\\)[ \t]*("
633
font-lock-keyword-face)
637
"\\(^[0-9]*\\|):\\|[;,]\\|then\\|else\\)[ \t]*"
638
"\\(a\\(bort\\|rray\\|ttrib\\)\\|b\\(ayes\\|y\\)"
639
"\\|c\\(hange\\|lass\\|ontrast\\)"
640
"\\|d\\(elete\\|isplay\\|m\\|o\\([ \t]+\\(data\\|over\\)\\)?\\|rop\\)"
641
"\\|e\\(rror\\|stimate\\|xc\\(hange\\|lude\\)\\)"
642
"\\|f\\(ile\\(name\\)?\\|o\\(otnote\\(10?\\|[2-9]\\)?\\|rmat\\)\\|req\\)"
643
"\\|go\\([ \t]*to\\|ptions\\)"
644
"\\|hazardratio\\|[hv]bar\\(3d\\)?"
645
"\\|i\\(d\\|f\\|n\\(dex\\|f\\(ile\\|ormat\\)\\|put\\|value\\)\\)"
646
"\\|keep\\|l\\(abel\\|ength\\|i\\(bname\\|nk\\|st\\)\\|smeans\\)"
647
"\\|m\\(anova\\|e\\(ans\\|rge\\)\\|issing\\|od\\(el\\|ify\\)\\)\\|note"
648
"\\|o\\(ds\\|ptions\\|therwise\\|utput\\)\\|p\\(arms\\|lot2?\\|ut\\)"
649
"\\|r\\(andom\\|e\\(name\\|peated\\|tain\\)\\)"
650
"\\|s\\(ave\\|e\\(lect\\|t\\)\\|kip\\|trata\\|um\\(by\\)?\\)"
651
"\\|t\\(ables?\\|i\\(me\\|tle\\(10?\\|[2-9]\\)?\\)\\)\\|update"
652
"\\|va\\(lue\\|r\\)\\|w\\(eight\\|here\\|i\\(ndow\\|th\\)\\)"
654
;; IML statements that are not also SAS statements
655
"\\|append\\|c\\(lose\\(file\\)?\\|reate\\)\\|edit\\|f\\(ind\\|orce\\|ree\\)"
656
"\\|insert\\|load\\|mattrib\\|p\\(a[ru]se\\|rint\\|urge\\)"
657
"\\|re\\(move\\|peat\\|place\\|set\\|sume\\)"
658
"\\|s\\(et\\(in\\|out\\)\\|how\\|ort\\|tore\\|ummary\\)\\|use\\)?"
660
"\\>") font-lock-keyword-face)
664
;; (cons "\\<\\(\\(then\\|else\\)[ \t]*\\)?\\(do\\([ \t]*over\\)?\\|else\\)\\>"
665
;; font-lock-keyword-face)
667
;; SAS statements that must be followed by a semi-colon
669
"\\(^[0-9]*\\|):\\|[;,]\\|then\\|else\\)[ \t]*"
670
"\\(cards4?\\|datalines\\|end\\|l\\(ostcard\\)\\|page\\|return\\|stop\\)?"
671
"[ \t]*;") font-lock-keyword-face)
673
;; SAS/GRAPH statements not handled above
675
"\\(^[0-9]*\\|):\\|[;,]\\)[ \t]*"
676
"\\(axis\\|legend\\|pattern\\|symbol\\)"
677
"\\([1-9][0-9]?\\)?\\>") font-lock-keyword-face)
679
;; SAS Datastep functions and SAS macro functions
680
;(cons "%[a-z_][a-z_0-9]*[ \t]*[(;]"
681
;; SAS macro functions occasionally defined with no arguments
682
;; which means they can be followed by any character that can
683
;; separate tokens, however, they are most likely to be followed
684
;; by operat-ions/ors
685
(cons "%[a-z_][a-z_0-9]*[- \t();,+*/=<>]"
686
font-lock-function-name-face)
687
(cons "\\<call[ \t]+[a-z_][a-z_0-9]*[ \t]*("
688
font-lock-function-name-face)
692
"\\(a\\(bs\\|r\\(cos\\|sin\\)\\|tan\\)\\|b\\(etainv\\|yte\\)"
693
"\\|c\\(eil\\|inv\\|o\\(llate\\|mpress\\|sh?\\)\\|ss\\|v\\)"
694
"\\|dacc\\(db\\(\\|sl\\)\\|s\\(l\\|yd\\)\\|tab\\)"
695
"\\|dep\\(db\\(\\|sl\\)\\|s\\(l\\|yd\\)\\|tab\\)"
696
"\\|d\\(a\\(te\\(\\|jul\\|part\\|time\\)\\|y\\)\\|hms\\|i\\(f[0-9]*\\|m\\|gamma\\)\\)"
697
"\\|e\\(rfc?\\|xp\\)"
698
"\\|f\\(i\\(nv\\|p\\(namel?\\|state\\)\\)\\|loor\\|uzz\\)\\|gam\\(inv\\|ma\\)"
699
"\\|h\\(bound\\|ms\\|our\\)\\|i\\(n\\(dexc?\\|put\\|t\\(\\|ck\\|nx\\|rr\\)\\)\\|rr\\)"
700
"\\|juldate\\|kurtosis\\|l\\(ag[0-9]*\\|bound\\|e\\(ft\\|ngth\\)\\|gamma\\|og\\(\\|10\\|2\\)\\)"
701
"\\|m\\(ax\\|dy\\|ean\\|in\\(\\|ute\\)\\|o\\(d\\|nth\\|rt\\)\\)"
702
"\\|n\\(\\|etpv\\|miss\\|o\\(rmal\\|t\\)\\|pv\\)"
703
"\\|prob\\([ft]\\|b\\(eta\\|nml\\)\\|chi\\|gam\\|hypr\\|it\\|n\\(egb\\|orm\\)\\)"
704
"\\|ordinal\\|p\\(oisson\\|ut\\)\\|qtr\\|r\\(e\\(peat\\|verse\\)\\|ight\\|ound\\)"
705
"\\|ran\\(bin\\|cau\\|exp\\|g\\(am\\|e\\)\\|k\\|nor\\|poi\\|t\\(bl\\|ri\\)\\|uni\\)"
706
"\\|s\\(aving\\|can\\|econd\\|i\\(gn\\|nh?\\)\\|qrt\\|t\\(d\\(\\|err\\)\\|fips\\|namel?\\)\\|u\\(bstr\\|m\\)\\|ymget\\)"
707
"\\|t\\(anh?\\|i\\(me\\(\\|part\\)\\|nv\\)\\|oday\\|r\\(anslate\\|i\\(gamma\\|m\\)\\|unc\\)\\)"
708
"\\|u\\(niform\\|pcase\\|ss\\)\\|v\\(ar\\|erify\\)"
709
"\\|weekday\\|y\\(ear\\|yq\\)\\|zip\\(fips\\|namel?\\|state\\)"
711
;;; ;; SAS functions introduced in Technical Report P-222
713
"\\|airy\\|b\\(and\\|lshift\\|not\\|or\\|rshift\\|xor\\)"
714
"\\|c\\(nonct\\|ompbl\\)\\|d\\(airy\\|equote\\)\\|fnonct\\|tnonct"
715
"\\|i\\(bessel\\|n\\(dexw\\|put[cn]\\)\\)\\|jbessel\\|put[cn]"
716
"\\|lowcase\\|quote\\|resolve\\|s\\(oundex\\|ysprod\\)\\|tr\\(anwrd\\|imn\\)"
718
;;; ;; IML functions that are not also Datastep functions
719
"\\|a\\(ll\\|ny\\|pply\\|rmasim\\)\\|b\\(lock\\|ranks\\|tran\\)"
720
"\\|c\\(har\\|hoose\\|on\\(cat\\|tents\\|vexit\\|vmod\\)\\|ovlag\\|shape\\|usum\\|vexhull\\)"
721
"\\|d\\(atasets\\|esignf?\\|et\\|iag\\|o\\|uration\\)"
722
"\\|e\\(chelon\\|igv\\(al\\|ec\\)\\)\\|f\\(ft\\|orward\\)\\|ginv"
723
"\\|h\\(alf\\|ankel\\|dir\\|ermite\\|omogen\\)"
724
"\\|i\\(\\|fft\\|nsert\\|nv\\(updt\\)?\\)\\|j\\(\\|root\\)\\|loc\\|mad"
725
"\\|n\\(ame\\|col\\|leng\\|row\\|um\\)\\|o\\(pscal\\|rpol\\)"
726
"\\|p\\(olyroot\\|roduct\\|v\\)\\|r\\(anktie\\|ates\\|atio\\|emove\\|eturn\\|oot\\|owcatc?\\)"
727
"\\|s\\(etdif\\|hape\\|olve\\|plinev\\|pot\\|qrsym\\|ssq\\|torage\\|weep\\|ymsqr\\)"
728
"\\|t\\(\\|eigv\\(al\\|ec\\)\\|oeplitz\\|race\\|risolv\\|ype\\)"
729
"\\|uni\\(on\\|que\\)\\|v\\(alue\\|ecdiag\\)\\|x\\(mult\\|sect\\)\\|yield"
731
;;; ;; SCL functions that are known to work with SAS macro function %sysfunc
733
"\\|attr[cn]\\|c\\(exist\\|lose\\)\\|d\\(close\\|num\\|open\\|read\\)"
734
"\\|exist\\|f\\(close\\|etchobs\\|i\\(leexist\\|nfo\\)\\|open\\|put\\|write\\)"
735
"\\|get\\(option\\|var[cn]\\)\\|lib\\(name\\|ref\\)\\|op\\(en\\|t\\(getn\\|setn\\)\\)"
736
"\\|pathname\\|sysmsg\\|var\\(fmt\\|l\\(abel\\|en\\)\\|n\\(ame\\|um\\)\\|type\\)\\)"
737
"[ \t]*(") font-lock-function-name-face)
739
"Font Lock regexs for SAS.")
742
(defvar SAS-editing-alist
743
'((sentence-end . ";[\t\n */]*")
744
(paragraph-start . "^[ \t]*$")
745
(paragraph-separate . "^[ \t]*$")
746
(paragraph-ignore-fill-prefix . t)
747
;;(fill-paragraph-function . 'lisp-fill-paragraph)
748
(adaptive-fill-mode . nil)
749
(indent-line-function . 'sas-indent-line)
750
;;(indent-region-function . 'sas-indent-region)
751
(require-final-newline . t)
752
(comment-start . "/*")
753
(comment-start-skip . "/[*]")
755
(comment-end-skip . "[*]/")
756
(comment-column . 40)
757
;;(comment-indent-function . 'lisp-comment-indent)
758
(parse-sexp-ignore-comments . t)
759
(ess-style . ess-default-style)
760
(ess-local-process-name . nil)
761
;;(ess-keep-dump-files . 'ask)
762
(tab-stop-list . ess-sas-tab-stop-list)
763
(ess-mode-syntax-table . SAS-syntax-table)
764
(font-lock-keywords-case-fold-search . t)
765
(font-lock-defaults . '(SAS-mode-font-lock-keywords)))
766
"General options for editing SAS source files.")
768
(defun beginning-of-sas-statement (arg &optional comment-start)
769
"Move point to beginning of current sas statement."
773
(if (search-forward ";" nil 1) (forward-char -1))
774
(re-search-backward ";[ \n*/]*$" (point-min) 1 arg)
775
(skip-chars-forward sas-comment-chars)
776
(if comment-start nil
777
(if (looking-at "\\*/")
778
(progn (forward-char 2)
779
(skip-chars-forward sas-comment-chars)))
780
(while (looking-at "/\\*")
781
(if (not (search-forward "*/" pos t 1)) ;;(;; (point-max) 1 1)
783
(skip-chars-forward sas-white-chars)))))
785
(defun sas-indent-line ()
786
"Indent function for SAS mode."
788
(let (indent prev-end
789
(pos (- (point-max) (point)))
791
(cur-ind (current-indentation))
792
(comment-col (sas-comment-start-col))) ;; 2/1/95 TDC
795
(back-to-indentation)
798
"data[ ;]\\|proc[ ;]\\|run[ ;]\\|endsas[ ;]\\|g?options[ ;]\\|%macro[ ;]\\|%mend[ ;]")))
799
;; Case where current statement is DATA, PROC, etc...
800
(setq prev-end (point))
801
(goto-char (point-min))
803
;; May get fooled if %MACRO, %DO, etc embedded in comments
805
(+ (* (- (sas-how-many "^[ \t]*%macro\\|[ \t]+%do"
807
(sas-how-many "^[ \t]*%mend\\|%end" prev-end))
808
sas-indent-width) comment-col))) ;; 2/1/95 TDC
809
;; Case where current line begins with sas-indent-ignore-comment
810
;; added 6/27/94 to leave "* ;" comments alone.
812
(back-to-indentation)
813
(and (not (looking-at "*/"))
814
(looking-at (concat sas-indent-ignore-comment "\\|/\\*"))))
815
(setq indent (current-indentation)))
816
;; Case where current statement not DATA, PROC etc...
817
(t (beginning-of-line 1)
818
(skip-chars-backward sas-white-chars)
822
((looking-at ";") ; modified 1/31/95
823
(setq indent (sas-next-statement-indentation)))
824
((save-excursion;; added 4/28/94 to properly check
825
(if (bobp) () (backward-char 1));; for end of comment
826
(setq prev-end (point))
827
(looking-at "*/"));; improved 1/31/95
829
(search-backward "*/"
830
(point-min) 1 1); comment start is first /*
832
prev-end 1 1) ; after previous */
833
(backward-char 2) ; 2/1/95 TDC
834
(skip-chars-backward sas-white-chars)
838
(sas-next-statement-indentation)
839
(+ (current-indentation) sas-indent-width))))))
841
;; added 6/27/94 to leave "* ;" comments alone
844
(beginning-of-sas-statement 1 t)
845
(and (not (looking-at "*/"))
846
(looking-at sas-indent-ignore-comment))))
847
(setq indent cur-ind))
849
(beginning-of-sas-statement 1)
850
(bobp));; added 4/13/94
851
(setq indent sas-indent-width));; so the first line works
855
(beginning-of-line 1)
856
(skip-chars-backward sas-white-chars)
857
(if (bobp) nil (backward-char 1))
859
(bobp) (backward-char 1) (looking-at "\\*/"))))
860
(setq indent (+ (current-indentation) sas-indent-width))
861
(setq indent (current-indentation))))))))
864
(back-to-indentation)
866
(beginning-of-line 1)
868
(delete-region beg end)
870
(if (> (- (point-max) pos) (point))
871
(goto-char (- (point-max) pos)))))
874
;;(defun sas-indent-region (start end)
875
;; "Indent a region of SAS code."
878
;; (let ((endmark (copy-marker end)))
880
;; (and (bolp) (not (eolp))
881
;; (sas-indent-line))
882
;; (indent-sexp endmark)
883
;; (set-marker endmark nil))))
886
(defun indent-sas-statement (arg)
887
"Indent all continuation lines sas-indent-width spaces from first
893
(while (and (> arg 0) (search-forward ";" (point-max) 1 1))
895
(if (bobp) nil (backward-char 1))
896
(beginning-of-sas-statement 1)
898
(indent-region (point)
900
(+ (current-column) (1- sas-indent-width)))
901
(search-forward ";" (point-max) 1 1)
902
(setq arg (1- arg)))))))
905
(defun sas-next-statement-indentation ()
906
"Returns the correct indentation of the next sas statement.
907
The current version assumes that point is at the end of the statement.
908
This will (hopefully) be fixed in later versions."
911
(let ((prev-end (point)))
912
(beginning-of-sas-statement 1)
913
(while (and (not (bobp))
914
(not (looking-at "*/"))
915
(looking-at sas-indent-ignore-comment))
916
(skip-chars-backward sas-white-chars)
919
(setq prev-end (point))
920
(beginning-of-sas-statement 1 t))
923
"data[ \n\t;]\\|proc[ \n\t]\\|%?do[ \n\t;]\\|%macro[ \n\t]\\|/\\*")
926
"\\b%?then\\>[ \n\t]*\\b%?do\\>\\|\\b%?else\\>[ \n\t]*\\b%?do\\>"
927
prev-end 1 1))) ; fixed 1/30/95 to avoid being fooled by
928
; variable names starting with "do"
929
(+ (current-indentation) sas-indent-width)
930
(if (looking-at "%?end[ ;\n]\\|%mend[ ;\n]\\|\\*/")
931
(max (- (current-indentation) sas-indent-width) 0)
932
(current-indentation)))))))
935
(defun sas-comment-start-col ()
936
"If the current line is inside a /* */ comment, returns column in which the
937
opening /* appears. returns 0 otherwise."
940
(if (and (search-backward "*/" (point-min) 1 1)
941
(search-forward "/*" pos 1 1))
942
(current-indentation)
946
;; Created 6/27/94 to verify that RUN; statements match PROC and DATA
947
;; statements. Useful since indentation my be goofy w/o "RUN;"
948
(defun sas-check-run-statements ()
949
"Check to see that \"run\" statements are matched with proc, data statements."
957
(if (re-search-forward
958
"\\(^[ \t]*run[ ;]\\)\\|\\(^[ \t]*proc \\|^[ \t]*data[ ;]\\)"
960
(if (match-beginning 2)
961
(if (re-search-forward
962
"\\(^[ \t]*run[ ;]\\)\\|\\(^[ \t]*proc \\|^[ \t]*data[ ;]\\)"
964
(progn (setq pos (point))
965
(setq ok (match-beginning 1)))
966
(setq eob-ok nil pos (point-max))))
969
(if (and ok eob-ok) (message "Run statements match")
972
(message "Missing Run Statement."))))
975
(defun sas-fix-life-tables (start end)
976
"Remove censored and duplicate observations from life tables generated by
977
Proc Lifetest. Operates on current region. A major space saver if there is
981
(shell-command-on-region
983
"sed \"\\? *\\. *\\. *\\. ?d\"" t)))
985
;;(setq ex-g-flag nil
987
;;(vip-ex "1,$g/ \\. \\. \\. /d")))
989
(defun sas-fix-page-numbers (offset &optional page-num)
990
"Fix number of current page in sas output files after editing. Add
991
OFFSET to actual page number."
993
(if (not offset) (setq offset 0))
994
(if (not page-num) (setq page-num (sas-page-number)))
996
(if (/= (preceding-char) ?\C-l) (backward-page 1))
997
(let (end len mstart mend)
999
(forward-line sas-page-number-max-line)
1001
(if (re-search-forward
1002
"\\(^[0-9]+[ ]\\)\\|\\([ ][0-9]+$\\)"
1004
(progn (setq len (- (match-end 0) (match-beginning 0))
1005
mstart (match-beginning 0)
1007
(delete-region mstart mend)
1010
(concat "%" len "d") (+ page-num offset)))
1012
(concat (+ (sas-page-number) offset) " ")
1015
(defun sas-page-fix (start)
1016
"Fix page numbers in sas output from point to end of file.
1017
If START is given this will be the number for the current page."
1019
(let (offset (pnum (sas-page-number)))
1020
(if (not start) (setq offset 0)
1021
(setq offset (- start pnum)))
1023
(sas-fix-page-numbers offset pnum)
1024
(setq pnum (1+ pnum))
1027
(defun fix-page-breaks ()
1028
"Fix page breaks in SAS 6 print files."
1031
(goto-char (point-min))
1032
(if (looking-at "\f") (delete-char 1))
1033
(replace-regexp "^\\(.+\\)\f" "\\1\n\f\n")
1034
(goto-char (point-min))
1035
(replace-regexp "^\f\\(.+\\)" "\f\n\\1")
1036
(goto-char (point-min))
1039
(goto-char (point-min))
1043
(goto-char (point-max))
1045
(progn (backward-char 1)
1046
(if (not (looking-at "\n"))
1047
(progn (forward-char 1) (open-line 1)))))))
1049
(defun sas-page-number ()
1050
;; like what-page except it returns an integer page number
1051
"Return page number of point in current buffer."
1052
(let ((opoint (point))) (save-excursion
1053
(goto-char (point-min))
1054
(1+ (sas-how-many page-delimiter opoint)))))
1056
(defun sas-how-many (regexp &optional end)
1057
;; a copy of `how-many' which returns an integer
1058
;; rather than a message
1059
"Return number of matches for REGEXP following point."
1060
(let ((count 0) opoint)
1062
(while (and (not (eobp))
1063
(progn (setq opoint (point))
1064
(re-search-forward regexp end t)))
1065
(if (= opoint (point))
1067
(setq count (1+ count))))
1070
(defun beginning-of-sas-proc ()
1071
"Move point to beginning of sas proc, macro or data step."
1073
(let ((case-fold-search t))
1075
(while (not (or (looking-at "data\\|proc\\|%macro")
1077
(re-search-backward "proc\\|data\\|%macro" (point-min) 1)
1078
(beginning-of-sas-statement 1))))
1080
(defun next-sas-proc (arg)
1081
"Move point to beginning of next sas proc."
1083
(let ((case-fold-search t))
1085
(if (re-search-forward
1086
"^[ \t]*\\(data[ ;]\\|proc[ ;]\\|endsas[ ;]\\|g?options[ ;]\\|%macro[ ;]\\)"
1088
(beginning-of-sas-statement 1)
1089
(forward-char -1))))
1091
(defun set-sas-file-name ()
1092
"Stores the name of the current sas file."
1093
(let ((name (buffer-file-name)))
1095
((string-match (substring name -4 nil)
1096
"\\.sas\\|\\.lst\\|\\.log")
1098
(setq sas-file-name (substring name 0 (- (length name) 4)))
1099
(setq sas-buffer-name (buffer-name))
1100
(setq sas-file-root (substring sas-buffer-name 0
1101
(- (length sas-buffer-name) 4))))
1102
(t (message "This file does not have a standard suffix")))))
1105
(defun sas-set-alternate-file-name (name)
1106
"Stores the NAME of an alternate sas file.
1107
When this file is submitted with `submit-sas', the alternate file will
1108
be submitted instead. `sas-submitable' is automatically sets to t."
1110
(cond ((string-match (substring name -4 nil)
1111
"\\.sas\\|\\.lst\\|\\.log")
1112
(setq sas-file-name (substring name 0 (- (length name) 4)))
1113
(setq sas-submitable t))
1114
(t (message "This file does not have a standard suffix"))))
1116
(defun switch-to-sas-source ()
1117
"Switches to sas source file associated with the current file."
1119
(switch-to-sas-file "sas"))
1121
(defun switch-to-sas-lst ()
1122
"Switches to sas source file associated with the current file."
1124
(switch-to-sas-file "lst"))
1126
(defun switch-to-sas-log ()
1127
"Switches to sas source file associated with the current file."
1129
(switch-to-sas-file "log"))
1131
(defun switch-to-sas-source-other-window ()
1132
"Switches to sas source file associated with the current file."
1134
(switch-to-sas-file-other-window "sas"))
1136
(defun switch-to-sas-lst-other-window ()
1137
"Switches to sas source file associated with the current file."
1139
(switch-to-sas-file-other-window "lst"))
1141
(defun switch-to-sas-log-other-window ()
1142
"Switches to sas source file associated with the current file."
1144
(switch-to-sas-file-other-window "log"))
1146
;;(defun switch-to-sas-file (suff &optional revert silent)
1147
;; "Switches to sas \"SUFF\" file associated with the current file"
1148
;; (let* ((sfile sas-file-name)
1149
;; (buf (get-file-buffer (concat sfile "." suff)))
1150
;; (sas-require-confirmation
1151
;; (and sas-require-confirmation (not revert))))
1152
;; (if (or sas-require-confirmation (string-equal suff "sas") (not buf))
1153
;; (find-file (concat sfile "." suff))
1154
;; (progn (switch-to-buffer buf)
1155
;; (if (not (verify-visited-file-modtime (current-buffer)))
1156
;; (progn (revert-buffer t t)
1158
;; (message "File has changed on disk. Buffer automatically updated."))))))
1159
;; (setq sas-file-name sfile))
1160
;; (if (string-equal suff "sas")
1161
;; (if (not (string-equal major-mode "sas-mode"))
1163
;; (if (not (string-equal major-mode "sasl-mode"))
1166
;;(defun switch-to-sas-file-other-window (suff)
1167
;; "Switches to sas \"SUFF\" file associated with the current file"
1168
;; (let* ((sfile sas-file-name)
1169
;; (buf (get-file-buffer (concat sfile "." suff))))
1170
;; (if (or sas-require-confirmation (string-equal suff "sas") (not buf))
1171
;; (find-file-other-window (concat sfile "." suff))
1172
;; (progn (switch-to-buffer-other-window buf)
1173
;; (if (not (verify-visited-file-modtime (current-buffer)))
1174
;; (progn (revert-buffer t t)
1175
;; (message "File has changed on disk. Buffer automatically updated.")))))
1176
;; (setq sas-file-name sfile))
1177
;; (if (string-equal suff "sas")
1178
;; (if (not (string-equal major-mode "sas-mode"))
1181
;; (if (not (string-equal major-mode "sasl-mode"))
1185
(defun switch-to-sas-file (suff)
1186
"Switches to sas \"SUFF\" file associated with the current file."
1187
(switch-to-buffer (set-sas-file-buffer suff)))
1189
(defun switch-to-sas-file-other-window (suff)
1190
"Switches to sas \"SUFF\" file associated with the current file."
1191
(switch-to-buffer-other-window (set-sas-file-buffer suff)))
1193
;; The following was created 6/7/94 to handle buffers without messing up
1196
(defun set-sas-file-buffer (suff &optional revert silent)
1197
"Sets current buffer to sas \"SUFF\" file associated with the current file."
1198
(let* ((sfile sas-file-name)
1199
(buf (get-file-buffer (concat sfile "." suff)))
1200
(sas-require-confirmation
1201
(and sas-require-confirmation (not revert))))
1202
(if (or sas-require-confirmation (string-equal suff "sas") (not buf))
1203
(set-buffer (find-file-noselect (concat sfile "." suff)))
1204
(progn (set-buffer buf)
1205
(if (not (verify-visited-file-modtime (current-buffer)))
1206
(progn (revert-buffer t t)
1208
(message "File has changed on disk. Buffer automatically updated."))))))
1209
(setq sas-file-name sfile))
1210
;;(if (string-equal suff "sas")
1211
;; (if (not (string-equal major-mode "sas-mode")) (sas-mode))
1212
;; (if (not (string-equal major-mode "sasl-mode"))(sasl-mode))
1215
(defun switch-to-sas-process-buffer ()
1216
"Switch to sas-process-buffer."
1218
(let (buf proc-name)
1219
(setq proc-name (concat "SAS" sas-file-name)
1220
buf (concat "*" proc-name "*"))
1221
(switch-to-buffer-other-window buf)))
1223
(defun submit-sas ()
1224
;; 6/17/94 added sas-submitable local variable.
1225
"Submit SAS file as shell command."
1227
(if ;; can file be run, or is it only for inclusion?
1233
"Submission is disabled for this file. Submit it anyway? "))))
1235
;; if buffer name has changed, tell user
1237
(string-equal sas-buffer-name (buffer-name))
1241
"The name of this buffer has changed. Submit the new file? "))))
1242
(setq sas-buffer-name (buffer-name))
1243
(set-sas-file-name))
1244
(let ((sas-file sas-file-name)
1245
(sas-root sas-file-root)
1246
;;(sas-buf sas-buffer-name)
1250
;; Save buffer to SAS the right file :-).
1251
(if (buffer-modified-p)
1252
(if (y-or-n-p (format "Buffer %s is modified. Save it? "
1255
(setq proc-name (concat "SAS" sas-file)
1256
buf (concat "*" proc-name "*"))
1257
(if (get-buffer buf)
1258
(save-window-excursion (switch-to-buffer buf)
1260
(setq default-directory
1261
(file-name-directory sas-file))))
1263
(run-hooks 'sas-pre-run-hook) ;; added 8/24/94
1264
(message "---- Submitting SAS job ----")
1265
;; (switch-to-buffer buf)
1266
(make-comint proc-name
1267
sas-program ;added sas-program 4/29/94
1270
(save-window-excursion
1271
(switch-to-buffer buf)
1272
(setq sas-file-name sas-file)
1275
(message "---- SAS job submitted ---- ")
1277
(if sas-notify;; added 4/7/94
1278
(set-process-sentinel (get-process proc-name) 'sas-sentinel)
1279
(display-buffer buf t))))
1280
(message "---- File not submitted ----")))
1282
;; 5/2/94 Modified sas-sentinel to check for errors in log file upon
1284
(defun sas-sentinel (proc arg);; created 4/7/94
1285
"Notify user that SAS run is done."
1287
;;(if (string-equal arg "finished\n")
1289
(let (msg buf win (sbuf (concat "*" (process-name proc) "*")))
1292
(substring arg 0 -1)
1293
(if sas-error-notify
1294
;;(save-window-excursion
1297
(setq buf (set-sas-file-buffer "log" t t))
1298
(goto-char (point-min))
1299
(setq win (get-buffer-window buf))
1300
(save-window-excursion
1304
(if (re-search-forward "^ERROR" nil t)
1305
" (See .log file for errors)"
1307
(switch-to-buffer buf)
1308
(if (re-search-forward "^ERROR" nil t)
1309
" (See .log file for errors)"
1313
(goto-char (point-max))
1315
(bury-buffer (get-buffer sbuf))
1316
;;(if (and sas-notify-popup window-system)
1317
;; (x-popup-dialog t
1318
;; (list "SAS Menu" (cons msg nil) )))
1319
;;(if (not (minibuffer-window-active-p)) (princ msg))
1322
;; 5/2/94 Modified run-sas-on-region to separate log and output buffers.
1324
;;(defun run-sas-on-region (start end append &optional buffer)
1325
;; "Submit region to SAS"
1326
;; (interactive "r\nP")
1327
;; (message "---- Running SAS ----")
1328
;; (let ((sfile sas-file-name)
1329
;; (shell-file-name "/bin/sh")
1331
;; (setq buffer (or buffer "*SAS output*"))
1333
;; (shell-command-on-region
1334
;; start end;; added sas-program
1335
;; (concat sas-program " -nonews -stdio 2> /tmp/_temp_.log" nil))
1336
;; (get-buffer-create "*SAS Log*")
1337
;; (save-window-excursion
1338
;; (switch-to-buffer "*SAS Log*")
1340
;; (insert-file-contents "/tmp/_temp_.log")
1341
;; (delete-file "/tmp/_temp_.log")
1342
;; (setq serror (re-search-forward "^ERROR" nil t))
1343
;; (if serror () (bury-buffer)))
1344
;; (setq buff (get-buffer-create buffer))
1345
;; (save-window-excursion
1346
;; (switch-to-buffer buff)
1347
;; (setq sas-file-name sfile)
1353
;; (if (get-buffer "*Shell Command Output*")
1354
;; (progn (insert-buffer "*Shell Command Output*")
1355
;; (kill-buffer "*Shell Command Output*"))
1356
;; (insert "SAS completed with no output."))
1357
;; (if append () (sasl-mode))
1358
;; (message "---- SAS Complete ----")))
1360
;; (switch-to-buffer-other-window buff)
1361
;; (switch-to-buffer-other-window "*SAS Log*")
1362
;; (goto-char serror)
1364
;; (message "Error found in log file.")
1367
(defun switch-to-dataset-log-buffer ()
1368
"Switch to log buffer for run-sas-on-region."
1370
(switch-to-buffer-other-window "*SAS Log*"))
1372
(defun switch-to-dataset-source-buffer ()
1373
"Switch to source buffer for run-sas-on-region."
1375
(switch-to-buffer-other-window (format " *sas-tmp-%s*" sas-dataset)))
1377
;;(defun sas-get-dataset (filename &optional arg opts-p append buffer vars)
1378
;; "Run proc contents and proc print on SAS dataset. Automatically prompts
1379
;;for SAS options to use. Default options are defined by the variable
1380
;;`sas-get-options'. Output may be updated from within output buffer with
1381
;;C-cr if dataset changes. Also, the source code which generates the output
1382
;;may be edited with C-cs. Typing C-cr within the output buffer reexecutes
1383
;;the (modified) source code."
1384
;; (interactive "fName of SAS dataset (file name):")
1385
;; (let ((file (file-name-nondirectory filename))
1386
;; (dir (file-name-directory filename))
1387
;; (opts sas-get-options)
1388
;; (minibuffer-history sas-get-options-history)
1390
;; (setq buffer (or buffer (concat "*" file "*")))
1391
;; (setq opts (if opts-p opts (read-string "SAS options: " opts)))
1392
;; (setq sas-get-options-history minibuffer-history)
1393
;; (cond ((string-match (substring file -6 nil) "\\.ssd01")
1394
;; (setq file (substring file 0 (- (length file) 6))))
1395
;; (t (error "This file is not a SAS dataset.")))
1396
;; (setq buf (format " *sas-tmp-%s*" file))
1397
;; (get-buffer-create buf)
1398
;; (save-window-excursion
1399
;; (switch-to-buffer buf)
1401
;; (setq default-directory dir)
1403
;; (insert (format "options %s ;\n" opts)))
1404
;; (insert (format "title \"Contents of SAS dataset `%s'\" ;\n" file))
1405
;; (insert (format "libname %s '%s' ;\n" sas-tmp-libname dir))
1406
;; (if (not (equal arg 1))
1407
;; (insert (format "proc contents data = %s.%s ;\n" sas-tmp-libname file)))
1408
;; (if (equal arg 2) ()
1409
;; (insert (format "proc print data = %s.%s ;\n" sas-tmp-libname file))
1410
;; (if vars (insert (format " var %s ;\n" vars))))
1411
;; (run-sas-on-region (point-min) (point-max) append
1413
;; (get-buffer buffer)
1414
;; (if append () (sasd-mode)) ;; added 5/5/94
1415
;; (setq sas-dataset file))
1416
;; (if (get-buffer-window buffer t)
1417
;; (raise-frame (window-frame (get-buffer-window buffer t)))
1418
;; (display-buffer buffer (not append)))
1421
;;(defun revert-sas-dataset ()
1422
;; "Revert current sas dataset from disk version"
1424
;; (let* ((file sas-dataset)
1425
;; (buf (format " *sas-tmp-%s*" file))
1427
;; (save-window-excursion
1428
;; (switch-to-buffer buf)
1429
;; (run-sas-on-region (point-min) (point-max) nil
1430
;; (concat "*" file ".ssd01*"))
1432
;; (goto-char pos) ;; added 6/9/94
1433
;; (sasd-mode) ;; added 5/5/94
1434
;; (setq sas-dataset file)))
1436
(defun sas-insert-local-variables () ;; created 6/17/94
1437
"Add local variables code to end of sas source file."
1440
(if (re-search-forward "* *Local Variables: *;" nil t)
1442
(goto-char (point-max))
1445
** Local Variables: ;
1453
;;; file name: sas-data.el
1457
;;; sas-data-mode: manage sas datasets
1458
;;; Copyright (C) 1994 Tom Cook
1460
;;; This program is free software; you can redistribute it and/or modify
1461
;;; it under the terms of the GNU General Public License as published by
1462
;;; the Free Software Foundation; either version 2 of the License, or
1463
;;; (at your option) any later version.
1465
;;; This program is distributed in the hope that it will be useful,
1466
;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
1467
;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1468
;;; GNU General Public License for more details.
1470
;;; You should have received a copy of the GNU General Public License
1471
;;; along with this program; if not, write to the Free Software
1472
;;; Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
1474
;;; Author: Tom Cook
1475
;;; Dept. of Biostatistics
1476
;;; University of Wisconsin - Madison
1477
;;; Madison, WI 53706
1478
;;; cook@biostat.wisc.edu
1481
;; variables section
1482
(defvar sas-dir-mode-map nil)
1483
(defvar sas-directory-name nil
1484
"Name of directory associated with this buffer.")
1485
(make-variable-buffer-local 'sas-directory-name)
1486
(defvar sas-dir-buf-end nil)
1487
(make-variable-buffer-local 'sas-dir-buf-end)
1488
(defvar sas-sorted-by-num nil)
1489
(make-variable-buffer-local 'sas-sorted-by-num)
1494
(if sas-dir-mode-map ()
1495
(setq sas-dir-mode-map (make-sparse-keymap))
1496
;;(define-key sas-dir-mode-map "c" 'sas-contents)
1497
(define-key sas-dir-mode-map "p" 'sas-print)
1498
(define-key sas-dir-mode-map "m" 'sas-mark-item)
1499
(define-key sas-dir-mode-map "u" 'sas-unmark-item)
1500
(define-key sas-dir-mode-map " " 'sas-next-line)
1501
(define-key sas-dir-mode-map "\C-n" 'sas-next-line)
1502
(define-key sas-dir-mode-map "\C-p" 'sas-prev-line)
1503
(define-key sas-dir-mode-map "\177" 'sas-prev-line-undo)
1504
(define-key sas-dir-mode-map "\C-b" 'sas-backward-page-narrow)
1505
(define-key sas-dir-mode-map "\C-v" 'sas-forward-page-narrow)
1506
(define-key sas-dir-mode-map "\C-m" 'sas-goto-dataset)
1507
(define-key sas-dir-mode-map [mouse-2] 'sas-mouse-goto-dataset)
1508
(define-key sas-dir-mode-map "t" 'sas-dir-goto-page)
1509
(define-key sas-dir-mode-map "q" 'bury-buffer)
1510
(define-key sas-dir-mode-map "g" 'sas-revert-library)
1511
(define-key sas-dir-mode-map "1" 'digit-argument)
1512
(define-key sas-dir-mode-map "2" 'digit-argument)
1513
(define-key sas-dir-mode-map "3" 'digit-argument)
1514
(define-key sas-dir-mode-map "4" 'digit-argument)
1515
(define-key sas-dir-mode-map "5" 'digit-argument)
1516
(define-key sas-dir-mode-map "6" 'digit-argument)
1517
(define-key sas-dir-mode-map "7" 'digit-argument)
1518
(define-key sas-dir-mode-map "8" 'digit-argument)
1519
(define-key sas-dir-mode-map "9" 'digit-argument)
1520
(define-key sas-dir-mode-map [menu-bar sas run]
1521
'("Submit File " . submit-sas))
1526
(defun sas-dir-mode ()
1527
"Major mode for managing sas files."
1529
(kill-all-local-variables)
1530
(use-local-map sas-dir-mode-map)
1531
(setq major-mode 'sas-dir-mode)
1532
(setq mode-name "SAS")
1533
(setq sas-directory-name (expand-file-name default-directory))
1534
(toggle-read-only 1))
1537
;;(defun sas-make-library (directory &optional update)
1538
;; "Create a buffer with the names of all sas datasets from DIRECTORY."
1539
;; (interactive "DDirectory Name: ")
1540
;; (let ((dir (expand-file-name directory)) buf out cont pos)
1541
;; (setq buf (format " *sas-tmp-%s*" dir))
1542
;; (setq out (concat "*SAS-dir-" dir))
1543
;; (setq cont (concat "*SAS-cont-" dir))
1544
;; (get-buffer-create buf)
1545
;; (if (get-buffer out)
1549
;; (setq buffer-read-only nil)))
1551
;; (pop-to-buffer out)
1552
;; (setq default-directory dir)
1553
;; (setq pos (point))
1556
;; (save-window-excursion
1559
;; (setq default-directory dir)
1560
;; (insert "options linesize=70 pagesize=1000 ;\n")
1561
;; (insert (format "title \"Contents of SAS directory `%s'\" ;\n"
1563
;; (insert (format "libname %s '%s' ;\n" sas-tmp-libname dir))
1564
;; (insert (format "proc contents data = %s._all_ directory details memtype=data ;\n" sas-tmp-libname))
1565
;; (run-sas-on-region (point-min) (point-max) nil
1568
;; (goto-char (point-min))
1569
;; (if (= (sas-how-many page-delimiter (point-max)) 0)
1570
;; (let ((buffer-read-only nil))
1572
;; (insert "There are no SAS datasets in this directory")
1573
;; (pop-to-buffer out))
1575
;; (set-buffer (get-buffer-create cont))
1576
;; (setq buffer-read-only t)
1577
;; (let ((buffer-read-only nil))
1579
;; (insert-buffer out)
1580
;; (delete-region (point-min)
1581
;; (or (re-search-forward page-delimiter nil t)
1584
;; (goto-char (point-min))
1586
;; (sas-narrow-to-page)))
1587
;; (if (re-search-forward page-delimiter nil t)
1588
;; (delete-region (progn (beginning-of-line) (point))
1590
;; (sas-insert-set-properties (point-min) (point-max))
1592
;; (switch-to-buffer out t)
1593
;; (goto-char (point-min))
1595
;; (setq sas-dir-buf-end (point-max)))
1597
;; (sas-move-to-filename (point-max))))))
1600
(defun sas-move-to-filename (&optional eol)
1601
(or eol (setq eol (progn (end-of-line) (point))))
1603
(if (re-search-forward "\\(^ *[0-9]+ *<*\\)[^:0-9\n]" eol t)
1604
(goto-char (match-end 1))))
1606
(defun sas-next-line (arg)
1607
"Move down one line."
1610
(sas-move-to-filename (point-max)))
1611
;;(and (< (point) sas-dir-buf-end)
1612
;;(forward-line arg)
1613
;;(sas-move-to-filename sas-dir-buf-end)))
1615
(defun sas-prev-line (arg)
1619
(re-search-backward "^ *[0-9]+ *<*[^:0-9\n]" (point-min) t)
1620
(sas-move-to-filename sas-dir-buf-end))
1622
(defun sas-insert-set-properties (beg end)
1625
(while (< (point) end)
1626
(if (sas-move-to-filename)
1627
(put-text-property (point)
1629
'mouse-face 'highlight))
1632
(defun sas-get-filename ()
1633
"Return name of dataset on current line."
1636
(if (string-equal "*SAS-dir" (substring (buffer-name) 0 8))
1637
(sas-move-to-filename)
1638
(goto-char (point-min))
1639
(re-search-forward "Data Set Name: [^.]*\\."))
1641
(downcase (concat sas-directory-name
1645
(skip-chars-forward "A-Z0-9_")
1646
(point))) ".ssd01")))))
1648
(defun sas-get-file-number ()
1649
"Return name of dataset on current line."
1651
(if (sas-move-to-filename)
1652
(progn (forward-word -1)
1653
(re-search-forward "[0-9]*")
1655
(buffer-substring (match-beginning 0)
1658
;;(defun sas-contents ()
1659
;; "Run proc contents on current file."
1661
;; (let ((buffer-read-only nil) (sas-get-options "linesize=70"))
1662
;; (sas-get-dataset (sas-get-filename) 2 t t (buffer-name))
1664
;; (backward-page-top-of-window 1)))
1666
;;(defun sas-print ()
1667
;; "Run proc contents on current file."
1669
;; (sas-get-dataset (sas-get-filename) 1 nil nil nil
1670
;; (sas-create-var-string)))
1672
(defun sas-goto-page (arg)
1673
"Goto top of page ARG. If no ARG, then goto top of file."
1679
(re-search-forward page-delimiter (point-max) 1 (1- arg)))))
1680
(skip-chars-forward sas-white-chars); was " \f\n" till 5.1.13
1683
(defun forward-page-top-of-window (arg)
1684
"Move forward to page boundary and leave first line at top of window.
1685
With arg, repeat, or go back if negative. A page boundary is any line
1686
whose beginning matches the regexp `page-delimiter'."
1691
(defun backward-page-top-of-window (arg)
1692
"Move backward to page boundary and leave first line at top of window.
1693
With arg, repeat, or go back if negative. A page boundary is any line
1694
whose beginning matches the regexp `page-delimiter'."
1696
(forward-page (- arg))
1699
(defun sas-narrow-to-page ()
1701
(let* ((min (point-min))
1703
;;(omin (point-min))
1704
;;(omax (point-max)))
1705
(if (or (bolp) (beginning-of-line)
1706
(looking-at page-delimiter))
1713
(narrow-to-region min max))))
1715
(defun sas-forward-page-narrow (arg)
1716
"Move forward to page boundary and narrow to page.
1717
With arg, repeat, or go back if negative. A page boundary is any line
1718
whose beginning matches the regexp `page-delimiter'."
1722
(sas-narrow-to-page)
1723
(goto-char (point-min)))
1725
(defun sas-backward-page-narrow (arg)
1726
"Move backward to page boundary and narrow to page.
1727
With arg, repeat, or go back if negative. A page boundary is any line
1728
whose beginning matches the regexp `page-delimiter'."
1730
(goto-char (point-min))
1732
(forward-page (- arg))
1733
(sas-narrow-to-page))
1735
(defun sas-goto-dataset (&optional page)
1737
(and sas-directory-name
1738
(let ((page (or page (sas-get-file-number))))
1739
;;(dir sas-directory-name))
1742
(switch-to-buffer-other-window
1743
(concat "*SAS-cont-" sas-directory-name))
1745
(sas-goto-page page)
1746
(sas-narrow-to-page)
1747
(goto-char (point-min)))))))
1749
;;(defun sas-mouse-goto-dataset (event)
1750
;; (interactive "e")
1752
;; (save-window-excursion
1754
;; (set-buffer (window-buffer (posn-window (event-end event))))
1756
;; (goto-char (posn-point (event-end event)))
1757
;; (setq page (sas-get-file-number)))
1758
;; (sas-goto-dataset page)
1759
;; (setq buf (buffer-name))))
1761
;; (goto-char (point-min))
1762
;; (display-buffer buf)))
1765
(defun sas-dir-goto-page (page)
1768
(sas-goto-page page)
1769
(sas-narrow-to-page))
1771
(defun sas-mark-item (&optional next)
1773
(sas-move-to-filename)
1775
(let ((buffer-read-only nil))
1776
(if (re-search-forward "^\\( *[0-9]+ *\\) \\([A-Z][A-Z_0-9]*\\) "
1777
(save-excursion (end-of-line) (point)) t)
1778
(replace-match "\\1<\\2>")))
1779
(or next (sas-next-line 1)))
1781
(defun sas-unmark-item ()
1785
(let ((buffer-read-only nil))
1786
(if (re-search-forward "^\\( *[0-9]+ *\\)<\\([A-Z][A-Z_0-9]*\\)>"
1787
(save-excursion (end-of-line) (point)) t)
1788
(replace-match "\\1 \\2 ")))))
1790
(defun sas-prev-line-undo (arg)
1794
(sas-move-to-filename))
1796
(defun sas-create-var-string ()
1797
(and (string-equal "*SAS-cont" (substring (buffer-name) 0 9))
1799
(goto-char (point-min))
1801
(re-search-forward "^\\( *[0-9]+ *\\)<\\([A-Z][A-Z_0-9]*\\)>"
1803
(setq str (concat str " " (buffer-substring (match-beginning 2)
1807
;;(defun sas-revert-library ()
1808
;; "Update current library."
1810
;; (if sas-directory-name
1811
;; (sas-make-library sas-directory-name t)))
1815
; Local variables section
1817
;;; This file is automatically placed in Outline minor mode.
1818
;;; The file is structured as follows:
1821
;;; Subsections: ;;;*;;;
1822
;;; Components: defuns, defvars, defconsts
1823
;;; Random code beginning with a ;;;;* comment
1824
;;; Local variables:
1825
;;; mode: emacs-lisp
1826
;;; mode: outline-minor
1827
;;; outline-regexp: "\^L\\|\\`;\\|;;\\*\\|;;;\\*\\|(def[cvu]\\|(setq\\|;;;;\\*"
1830
;;; essl-sas.el ends here