source: git/emacs/singular.el @ 213e96

spielwiese
Last change on this file since 213e96 was 213e96, checked in by Jens Schmidt <schmidt@…>, 26 years ago
* singular.el (singular-extended-prompt-regexp, singular-string-start-anchored-prompt-regexp, singular-prompt-sequence-regexp): new constants (singular-strip-white-space, singular-strip-prompts, singular-skip-prompt-forward): new functions * singular.el (singular-emacs-simple-sec-end-at): bug fix (singular-fold-internal, singular-demo-show-next-chunk): do not save buffer-modified flag and do not switch off read only state (singular-output-filter): does not switch off read only state (singular-input-section-to-string): new function (singular-strip-white-space, singular-strip-prompts): new functions * singular.el (singular-send-input): sends old input sections (singular-send-input): renamed to `singular-send-or-copy-input'. All references changed. (singular-get-old-input): new function * singular.el (singular-demo-end): new variable (singular-demo-mode-init, singular-interactive-mode): new function. Call added in mode initialization. (singular-demo-load): sets `singular-demo-end' (singular-demo-show-next-chunk): is smarter concerning end of demo file git-svn-id: file:///usr/local/Singular/svn/trunk@2392 2c84dea3-7e68-4137-9b89-c4e89433aadc
  • Property mode set to 100644
File size: 46.1 KB
Line 
1;;; singular.el --- Emacs support for Computer Algebra System Singular
2
3;; $Id: singular.el,v 1.11 1998-07-29 16:57:32 schmidt Exp $
4
5;;; Commentary:
6
7
8;;; Code:
9
10;;{{{ Style and coding conventions
11
12;; Style and coding conventions:
13;;
14;; - "Singular" is written with an upper-case `S' in comments, doc
15;;   strings, and messages.  As part of symbols, it is written with
16;;   a lower-case `s'.
17;; - use a `fill-column' of 70 for doc strings and comments
18;; - use foldings to structure the source code but try not to exceed a
19;;   maximal depth of two folding (one folding in another folding which is
20;;   on top-level)
21;; - use lowercase folding titles except for first word
22;; - folding-marks are `;;{{{' and `;;}}}' resp., for sake of standard
23;;   conformity
24;; - mark incomplete doc strings or code with `NOT READY' (optionally
25;;   followed by an explanation what exactly is missing)
26;;
27;; - use `singular' as prefix for all global symbols
28;; - use `singular-debug' as prefix for all global symbols concerning
29;;   debugging.
30;;
31;; - mark dependencies on Emacs flavor/version with a comment of the form
32;;   `;; Emacs[ <version>]'     resp.
33;;   `;; XEmacs[ <version>][ <nasty comment>]' (in that order, if
34;;   possible)
35;; - use a `cond' statement to execute Emacs flavor/version-dependent code,
36;;   not `if'.  This is to make such checks more extensible.
37;; - try to define different functions for different flavors/version
38;;   and use `singular-fset' at library-loading time to set the function
39;;   you really need.  If the function is named `singular-<basename>', the
40;;   flavor/version-dependent functions should be named
41;;   `singular-<flavor>[-<version>]-<basename>'.
42
43;; - use `singular-debug' for debugging output/actions
44;; - to switch between buffer and process names, use the functions
45;;   `singular-process-name-to-buffer-name' and
46;;   `singular-buffer-name-to-process-name'
47;; - we assume that the buffer is *not* read-only
48
49;;}}}
50
51(require 'comint)
52
53;;{{{ Code common to both modes
54;;{{{ Debugging stuff
55(defvar singular-debug nil
56  "*List of modes to debug or `all' to debug all modes.
57Currently, only the mode `interactive' is supported.")
58
59(defun singular-debug-format (string)
60  "Return STRING in a nicer format."
61  (save-match-data
62    (while (string-match "\n" string)
63      (setq string (replace-match "^J" nil nil string)))
64
65    (if (> (length string) 16)
66        (concat "<" (substring string 0 7) ">...<" (substring string -8) ">")
67      (concat "<" string ">"))))
68
69(defmacro singular-debug (mode form &optional else-form)
70  "Major debugging hook for singular.el.
71Evaluates FORM if `singular-debug' equals `all' or if MODE is an
72element of `singular-debug', othwerwise ELSE-FORM"
73  `(if (or (eq singular-debug 'all)
74           (memq ,mode singular-debug))
75       ,form
76     ,else-form))
77;;}}}
78
79;;{{{ Determining version
80(defvar singular-emacs-flavor nil
81  "A symbol describing the current Emacs.
82Currently, only Emacs \(`emacs') and XEmacs are supported \(`xemacs').")
83
84(defvar singular-emacs-major-version nil
85  "An integer describing the major version of the current emacs.")
86
87(defvar singular-emacs-minor-version nil
88  "An integer describing the major version of the current emacs.")
89
90(defun singular-fset (real-function emacs-function xemacs-function
91                                    &optional emacs-19-function)
92  "Set REAL-FUNCTION to one of the functions, in dependency on Emacs flavor and version.
93Sets REAL-FUNCTION to XEMACS-FUNCTION if `singular-emacs-flavor' is
94`xemacs'.  Sets REAL-FUNCTION to EMACS-FUNCTION if `singular-emacs-flavor'
95is `emacs' and `singular-emacs-major-version' is 20.  Otherwise, sets
96REAL-FUNCTION to EMACS-19-FUNCTION which defaults to EMACS-FUNCTION.
97
98This is not as common as would be desirable.  But it is sufficient so far."
99  (cond
100   ;; XEmacs
101   ((eq singular-emacs-flavor 'xemacs)
102    (fset real-function xemacs-function))
103   ;; Emacs 20
104   ((eq singular-emacs-major-version 20)
105    (fset real-function emacs-function))
106   ;; Emacs 19
107   (t
108    (fset real-function (or emacs-19-function emacs-function)))))
109
110(defun singular-set-version ()
111  "Determine flavor, major version, and minor version of current emacs.
112singular.el is guaranteed to run on Emacs 19.34, Emacs 20.2, and XEmacs
11320.2.  It should run on newer version and on slightly older ones, too."
114
115  ;; get major and minor versions first
116  (if (and (boundp 'emacs-major-version)
117           (boundp 'emacs-minor-version))
118      (setq singular-emacs-major-version emacs-major-version
119            singular-emacs-minor-version emacs-minor-version)
120    (with-output-to-temp-buffer "*singular warnings*"
121      (princ
122"You seem to have quite an old Emacs or XEmacs version.  Some of the
123features from singular.el will not work properly.  Consider upgrading to a
124more recent version of Emacs or XEmacs.  singular.el is guaranteed to run
125on Emacs 19.34, Emacs 20.2, and XEmacs 20.2."))
126    ;; assume the oldest version we support
127    (setq singular-emacs-major-version 19
128          singular-emacs-minor-version 34))
129
130  ;; get flavor
131  (if (string-match "XEmacs\\|Lucid" emacs-version)
132      (setq singular-emacs-flavor 'xemacs)
133    (setq singular-emacs-flavor 'emacs)))
134
135(singular-set-version)
136;;}}}
137
138;;{{{ Faces
139(make-face 'singular-input-face)
140(set-face-background 'singular-input-face "peach puff")
141(defvar singular-input-face 'singular-input-face
142  "Face for user input.
143This face should have set background only.")
144
145(make-face 'singular-output-face)
146(set-face-background 'singular-output-face "blanched almond")
147(defvar singular-output-face 'singular-output-face
148  "Face for Singular output.
149This face should have set background only.")
150
151(defun singular-lookup-face (face-type)
152  "Return face belonging to FACE-TYPE.
153NOT READY [should be rewritten completely.  Interface should stay the same.]!"
154  (cond ((eq face-type 'input) singular-input-face)
155        ((eq face-type 'output) singular-output-face)))
156;;}}}
157;;}}}
158
159;;{{{ Singular interactive mode
160;;{{{ Key map
161(defvar singular-interactive-mode-map ()
162  "Key map to use in Singular interactive mode.")
163
164(if singular-interactive-mode-map
165    ()
166  (cond
167   ;; Emacs
168   ((eq singular-emacs-flavor 'emacs)
169    (setq singular-interactive-mode-map
170          (nconc (make-sparse-keymap) comint-mode-map)))
171   ;; XEmacs
172   (t
173    (setq singular-interactive-mode-map (make-keymap))
174    (set-keymap-parents singular-interactive-mode-map (list comint-mode-map))
175    (set-keymap-name singular-interactive-mode-map
176                     'singular-interactive-mode-map)))
177  (define-key singular-interactive-mode-map "\C-m" 'singular-send-or-copy-input))
178;;}}}
179
180;;{{{ Miscellaneous
181
182;; Note:
183;;
184;; We assume a one-to-one correspondance between Singular buffers
185;; and Singular processes.  We always have
186;; (equal buffer-name (concat "*" process-name "*")).
187
188(defun singular-buffer-name-to-process-name (buffer-name)
189  "Create the process name for BUFFER-NAME.
190The process name is the buffer name with surrounding `*' stripped
191off."
192  (substring buffer-name 1 -1))
193
194(defun singular-process-name-to-buffer-name (process-name)
195  "Create the buffer name for PROCESS-NAME.
196The buffer name is the process name with surrounding `*'."
197  (concat "*" process-name "*"))
198
199(defmacro singular-process-mark ()
200  "Return process mark of current buffer."
201  (process-mark (get-buffer-process (current-buffer))))
202;;}}}
203
204;;{{{ Customizing variables of comint
205
206;; Note:
207;;
208;; In contrast to the variables from comint.el, all the variables
209;; below are global variables.  It would not make any sense to make
210;; them buffer-local since
211;; o they are read only when Singular interactive mode comes up;
212;; o since they are Singular-dependent and not user-dependent, i.e.,
213;;   the user would not mind to change them.
214;;
215;; For the same reasons these variables are not marked as
216;; "customizable" by a leading `*'.
217
218(defvar singular-prompt-regexp "^> "
219  "Regexp to match prompt patterns in Singular.
220Should not match the continuation prompt \(`.'), only the regular
221prompt \(`>').
222
223This variable is used to initialize `comint-prompt-regexp' when
224Singular interactive mode starts up.")
225
226(defvar singular-delimiter-argument-list '(?= ?\( ?\) ?, ?;)
227  "List of characters to recognize as separate arguments.
228
229This variable is used to initialize `comint-delimiter-argument-list'
230when Singular interactive mode starts up.")
231
232(defvar singular-input-ignoredups t
233  "If non-nil, don't add input matching the last on the input ring.
234
235This variable is used to initialize `comint-input-ignoredups' when
236Singular interactive mode starts up.")
237
238(defvar singular-buffer-maximum-size 2048
239  "The maximum size in lines for Singular buffers.
240
241This variable is used to initialize `comint-buffer-maximum-size' when
242Singular interactive mode starts up.")
243
244(defvar singular-input-ring-size 64
245  "Size of input history ring.
246
247This variable is used to initialize `comint-input-ring-size' when
248Singular interactive mode starts up.")
249
250(defvar singular-history-filter-regexp "\\`\\(..?\\|\\s *\\)\\'"
251  "Regular expression to filter strings *not* to insert in the history.
252By default, input consisting of less than three characters and input
253consisting of white-space only is not added to the history.")
254
255(defvar singular-history-filter
256  (function (lambda (string)
257              (not (string-match singular-history-filter-regexp string))))
258  "Predicate for filtering additions to input history.
259
260This variable is used to initialize `comint-input-filter' when
261Singular interactive mode starts up.")
262;;}}}
263
264;;{{{ Skipping and stripping prompts and newlines and other things
265
266;; Note:
267;;
268;; All of these functions modify the match data!
269
270(defconst singular-extended-prompt-regexp "\\([>.] \\)"
271  "Matches one Singular prompt.
272Should not be anchored neither to start nor to end!")
273
274(defconst singular-string-start-anchored-prompt-regexp
275  (concat "\\`" singular-extended-prompt-regexp "+")
276  "Matches Singular prompt anchored to string start.")
277
278(defconst singular-prompt-sequence-regexp
279  (concat singular-extended-prompt-regexp "*")
280  "Matches an arbitary sequence of Singular prompts.")
281
282(defun singular-strip-white-space (string &optional trailing leading)
283  "Strip off trailing or leading white-space from STRING.
284Strips off trailing white-space if optional argument TRAILING is
285non-nil.
286Strips off leading white-space if optional argument LEADING is
287non-nil."
288  (let ((beg 0)
289        (end (length string)))
290    (and leading
291         (string-match "\\`\\s-*" string)
292         (setq beg (match-end 0)))
293    (and trailing
294         (string-match "\\s-*\\'" string beg)
295         (setq end (match-beginning 0)))
296    (substring string beg end)))
297
298(defun singular-strip-prompts (string where)
299  "NOT READY!"
300  (cond
301   ((eq where 'trailing) string)
302   ((eq where 'all) string)
303   (t
304    ;; default is to remove leading prompts
305    (if (string-match singular-string-start-anchored-prompt-regexp string)
306        (substring string (match-end 0))
307      string))))
308
309(defun singular-skip-prompt-forward ()
310  "Skip forward over prompts."
311  (looking-at singular-prompt-sequence-regexp)
312  (goto-char (match-end 0)))
313;;}}}
314
315;;{{{ Simple section stuff for both Emacs and XEmacs
316
317;; Note:
318;;
319;; Sections and simple sections are used to mark Singular's input and
320;; output for further access.  Here are some general notes on simple
321;; sections.  Sections are explained in the respective folding.
322;;
323;; In general, simple sections are more or less Emacs' overlays or XEmacs
324;; extents, resp.  But they are more than simply an interface to overlays
325;; or sections.
326;;
327;; - Simple sections are non-empty portions of text.  They are interpreted
328;;   as left-closed, right-opened intervals, i.e., the start point of a
329;;   simple sections belongs to it whereas the end point does not.
330;; - Simple sections start and end at line borders only.
331;; - Simple sections do not overlap.  Thus, any point in the buffer may be
332;;   covered by at most one simple section.
333;; - Besides from their start and their end, simple sections have some type
334;;   associated.
335;; - Simple sections are realized using overlays (extents for XEmacs)
336;;   which define the start and, end, and type (via properties) of the
337;;   simple section.  Actually, as a lisp object a simple section is
338;;   nothing else but the underlying overlay.
339;; - There may be so-called clear simple sections.  Clear simple sections
340;;   have not an underlying overlay.  Instead, they start at the end of the
341;;   preceding non-clear simple section, end at the beginning of the next
342;;   non-clear simple section, and have the type defined by
343;;   `singular-simple-sec-clear-type'.  Clear simple sections are
344;;   represented by nil.
345;; - Buffer narrowing does not restrict the extent of completely or
346;;   partially inaccessible simple sections.  But one should note that
347;;   some of the functions assume that there is no narrowing in
348;;   effect.
349;; - After creation, simple sections are not modified any further.
350;;
351;; - In `singular-interactive-mode', the whole buffer is covered with
352;;   simple sections from the very beginning of the file up to the
353;;   beginning of the line containing the last input or output.  The
354;;   remaining text up to `(point-max)' may be interpreted as covered by
355;;   one clear simple section.  Thus, it is most reasonable to define
356;;   `input' to be the type of clear simple sections.
357
358(defvar singular-simple-sec-clear-type 'input
359  "Type of clear simple sections.
360If nil no clear simple sections are used.")
361
362(defvar singular-simple-sec-last-end nil
363  "Marker at the end of the last simple section.
364Should be initialized by `singular-simple-sec-init' before any calls to
365`singular-simple-sec-create' are done.
366
367This variable is buffer-local.")
368
369(defun singular-simple-sec-init (pos)
370  "Initialize global variables belonging to simple section management.
371Creates the buffer-local marker `singular-simple-sec-last-end' and
372initializes it to POS."
373  (make-local-variable 'singular-simple-sec-last-end)
374  (if (not (and (boundp 'singular-simple-sec-last-end)
375                singular-simple-sec-last-end))
376      (setq singular-simple-sec-last-end (make-marker)))
377  (set-marker singular-simple-sec-last-end pos))
378
379;; Note:
380;;
381;; The rest of the folding is either marked as
382;; Emacs
383;; or
384;; XEmacs
385
386(singular-fset 'singular-simple-sec-create
387               'singular-emacs-simple-sec-create
388               'singular-xemacs-simple-sec-create)
389
390(singular-fset 'singular-simple-sec-reset-last
391               'singular-emacs-simple-sec-reset-last
392               'singular-xemacs-simple-sec-reset-last)
393
394(singular-fset 'singular-simple-sec-start
395               'singular-emacs-simple-sec-start
396               'singular-xemacs-simple-sec-start)
397
398(singular-fset 'singular-simple-sec-end
399               'singular-emacs-simple-sec-end
400               'singular-xemacs-simple-sec-end)
401
402(singular-fset 'singular-simple-sec-start-at
403               'singular-emacs-simple-sec-start-at
404               'singular-xemacs-simple-sec-start-at)
405
406(singular-fset 'singular-simple-sec-end-at
407               'singular-emacs-simple-sec-end-at
408               'singular-xemacs-simple-sec-end-at)
409
410(singular-fset 'singular-simple-sec-type
411               'singular-emacs-simple-sec-type
412               'singular-xemacs-simple-sec-type)
413
414(singular-fset 'singular-simple-sec-at
415               'singular-emacs-simple-sec-at
416               'singular-xemacs-simple-sec-at)
417
418(singular-fset 'singular-simple-sec-before
419               'singular-emacs-simple-sec-before
420               'singular-xemacs-simple-sec-before)
421
422(singular-fset 'singular-simple-sec-in
423               'singular-emacs-simple-sec-in
424               'singular-xemacs-simple-sec-in)
425;;}}}
426
427;;{{{ Simple section stuff for Emacs
428(defun singular-emacs-simple-sec-create (type end)
429  "Create a new simple section of type TYPE.
430Creates the section from end of previous simple section up to END.
431END should be larger than `singular-simple-sec-last-end'.
432Returns the new simple section or `empty' if no simple section has
433been created.
434Assumes that no narrowing is in effect.
435Updates `singular-simple-sec-last-end'."
436  (let ((last-end (marker-position singular-simple-sec-last-end))
437        ;; `simple-sec' is the new simple section or `empty'
438        simple-sec)
439
440    ;; get beginning of line before END.  At this point we need that there
441    ;; are no restrictions.
442    (setq end (let ((old-point (point)))
443                (goto-char end) (beginning-of-line)
444                (prog1 (point) (goto-char old-point))))
445
446    (cond
447     ;; do not create empty sections
448     ((eq end last-end) (setq simple-sec 'empty))
449     ;; create only non-clear simple sections
450     ((not (eq type singular-simple-sec-clear-type))
451      ;; if type has not changed we only have to extend the previous
452      ;; simple section
453      (setq simple-sec (singular-emacs-simple-sec-before last-end))
454      (if (eq type (singular-emacs-simple-sec-type simple-sec))
455          ;; move existing overlay
456          (setq simple-sec (move-overlay simple-sec (overlay-start simple-sec) end))
457        ;; create new overlay
458        (setq simple-sec (make-overlay last-end end))
459        ;; set type property
460        (overlay-put simple-sec 'singular-type type)
461        ;; set face
462        (overlay-put simple-sec 'face (singular-lookup-face type))
463        ;; evaporate empty sections
464        (overlay-put simple-sec 'evaporate t))))
465           
466    ;; update end of last simple section
467    (set-marker singular-simple-sec-last-end end)
468    simple-sec))
469
470(defun singular-emacs-simple-sec-reset-last (pos)
471  "Reset end of last simple section to POS after accidental extension.
472Updates `singular-simple-sec-last-end', too."
473  (let ((simple-sec (singular-emacs-simple-sec-at pos)))
474    (if simple-sec (move-overlay simple-sec (overlay-start simple-sec) pos))
475    (set-marker singular-simple-sec-last-end pos)))
476
477(defun singular-emacs-simple-sec-start (simple-sec)
478  "Return start of non-clear simple section SIMPLE-SEC."
479  (overlay-start simple-sec))
480
481(defun singular-emacs-simple-sec-end (simple-sec)
482  "Return end of non-clear simple section SIMPLE-SEC."
483  (overlay-end simple-sec))
484
485(defun singular-emacs-simple-sec-start-at (pos)
486  "Return start of clear section at position POS.
487Assumes that no narrowing is in effect."
488  (let ((previous-overlay-change (1+ (point))))
489    ;; this `while' loop at last will run into the end of the next
490    ;; non-clear overlay or stop at bob.  Since POS may be right at the end
491    ;; of a previous non-clear location, we have to search at least one
492    ;; time from POS+1 backwards.
493    (while (not (or (singular-emacs-simple-sec-before previous-overlay-change)
494                    (eq previous-overlay-change (point-min))))
495      (setq previous-overlay-change
496            (previous-overlay-change previous-overlay-change)))
497    previous-overlay-change))
498
499(defun singular-emacs-simple-sec-end-at (pos)
500  "Return end of clear section at position POS.
501Assumes that no narrowing is in effect."
502  (let ((next-overlay-change (next-overlay-change (point))))
503    ;; this `while' loop at last will run into the beginning of the next
504    ;; non-clear overlay or stop at eob.  Since POS may not be at the
505    ;; beginning of a non-clear simple section we may start searching
506    ;; immediately.
507    (while (not (or (singular-emacs-simple-sec-at next-overlay-change)
508                    (eq next-overlay-change (point-max))))
509      (setq next-overlay-change
510            (next-overlay-change next-overlay-change)))
511    next-overlay-change))
512
513(defun singular-emacs-simple-sec-type (simple-sec)
514  "Return type of SIMPLE-SEC."
515  (if simple-sec
516      (overlay-get simple-sec 'singular-type)
517    singular-simple-sec-clear-type))
518
519(defun singular-emacs-simple-sec-at (pos)
520  "Return simple section at position POS."
521  (let ((overlays (overlays-at pos)) simple-sec)
522    ;; be careful, there may be other overlays!
523    (while (and overlays (not simple-sec))
524      (if (singular-emacs-simple-sec-type (car overlays))
525          (setq simple-sec (car overlays)))
526      (setq overlays (cdr overlays)))
527    simple-sec))
528
529(defun singular-emacs-simple-sec-before (pos)
530  "Return simple section before position POS.
531This is the same as `singular-simple-section-at' except if POS falls
532on a section border.  In this case `singular-simple-section-before'
533returns the previous simple section instead of the current one."
534  (singular-emacs-simple-sec-at (max 1 (1- pos))))
535
536(defun singular-emacs-simple-sec-in (beg end)
537  "Return a list of all simple sections intersecting with the region from BEG to END.
538A simple section intersects the region if the section and the region
539have at least one character in common.
540The result contains both clear and non-clear simple sections in the
541order in that the appear in the region."
542  ;; NOT READY
543  nil)
544;;}}}
545
546;;{{{ Section stuff
547
548;; Note:
549;;
550;; Sections are built on simple sections.  Their purpose is to cover the
551;; difference between clear and non-clear simple sections.
552;;
553;; - Sections consist of a simple section, its type, and its start and end
554;;   points.  This is redundant information only in the case of non-clear
555;;   simple section.
556;; - Sections are read-only objects, neither are they modified nor are they
557;;   created.
558;; - Buffer narrowing does not restrict the extent of completely or
559;;   partially inaccessible sections.  In contrast to simple sections
560;;   the functions concerning sections do not assume that there is no
561;;   narrowing in effect.
562;; - Sections are independent from implementation dependencies.  There are
563;;   no different versions of the functions for Emacs and XEmacs.
564
565(defun singular-section-at (pos &optional restricted)
566  "Return section at position POS.
567Returns section intersected with current restriction if RESTRICTED is
568non-nil."
569  (let* ((simple-sec (singular-simple-sec-at pos))
570         (type (singular-simple-sec-type simple-sec))
571         start end)
572    (if simple-sec
573        (setq start (singular-simple-sec-start simple-sec)
574              end  (singular-simple-sec-end simple-sec))
575      (save-restriction
576        (widen)
577        (setq start (singular-simple-sec-start-at pos)
578              end (singular-simple-sec-end-at pos))))
579    (if restricted
580        (vector simple-sec type
581                (max start (point-min)) (min end (point-max)))
582      (vector simple-sec type start end))))
583
584(defun singular-section-before (pos &optional restricted)
585  "Return section before position POS.
586This is the same as `singular-section-at' except if POS falls on a
587section border.  In this case `singular-section-before' returns the
588previous section instead of the current one.
589Returns section intersected with current restriction if RESTRICTED is
590non-nil."
591  (singular-section-at (max 1 (1- pos)) restricted))
592
593(defmacro singular-section-simple-sec (section)
594  "Return underlying simple section of SECTION."
595  `(aref ,section 0))
596
597(defmacro singular-section-type (section)
598  "Return type of SECTION."
599  `(aref ,section 1))
600
601(defmacro singular-section-start (section)
602  "Return start of SECTION."
603  `(aref ,section 2))
604
605(defmacro singular-section-end (section)
606  "Return end of SECTION."
607  `(aref ,section 3))
608;;}}}
609
610;;{{{ Getting section contents
611(defun singular-input-section-to-string (section &optional end raw)
612  "Get content of SECTION as string.
613Returns text between start of SECTION and END if optional argument END
614is non-nil.  END should be a position inside SECTION.
615Strips leading prompts and trailing white space unless optional argument
616RAW is non-nil."
617  (save-restriction
618    (widen)
619    (let ((string (if end
620                      (buffer-substring (singular-section-start section) end)
621                    (buffer-substring (singular-section-start section)
622                                      (singular-section-end section)))))
623      (if raw string
624        (singular-strip-prompts
625         (singular-strip-trailing-white-space string t)
626         'leading)))))
627;;}}}
628
629;;{{{ Folding sections
630(defvar singular-folding-ellipsis "Singular I/O ..."
631  "Ellipsis to show for folded input or output.")
632
633(defun singular-fold-internal (start end fold)
634  "(Un)fold region from START to END.
635Folds if FOLD is non-nil, otherwise unfolds.
636Folds without affecting undo information, but changes buffer-modified
637flag.
638Assumes that there is no narrowing in effect."
639  (save-excursion
640    (let ((buffer-undo-list t))
641      (if fold
642          (progn
643            (goto-char start) (insert ?\r)
644            (subst-char-in-region start end ?\n ?\r t))
645        (subst-char-in-region start end ?\r ?\n t)
646        (goto-char start) (delete-char 1)))))
647
648(defun singular-section-foldedp (section)
649  "Return t iff SECTION is folded.
650Assumes that there is no narrowing in effect."
651  (eq (char-after (singular-section-start section)) ?\r))
652
653(defun singular-fold-section (section)
654  "Fold SECTION.
655Folds section at point and goes to beginning of section if called
656interactively."
657  (interactive (list (singular-section-at (point))))
658  (let ((start (singular-section-start section))
659        ;; we have to save restrictions this way since we change text
660        ;; outside the restriction.  Note that we do not use a marker for
661        ;; `old-point-min'.  This way, even partial narrowed sections are
662        ;; folded properly if they have been narrowed at bol.  Nice but
663        ;; dirty trick: The insertion of a `?\r' at beginning of section
664        ;; advances the beginning of the restriction such that it displays
665        ;; the `?\r' immediately before bol.  Seems worth it.
666        (old-point-min (point-min))
667        (old-point-max (point-max-marker)))
668    (unwind-protect
669        (progn
670          (widen)
671          (singular-fold-internal start (singular-section-end section)
672                                  (not (singular-section-foldedp section))))
673      (narrow-to-region old-point-min old-point-max)
674      (set-marker old-point-max nil))
675    (if (interactive-p) (goto-char (max start (point-min))))))
676;;}}}
677
678;;{{{ Debugging input and output filters
679(defun singular-debug-input-filter (string)
680  "Echo STRING in mini-buffer."
681  (singular-debug 'interactive-filter
682                  (message "Input filter: %s"
683                           (singular-debug-format string))))
684
685(defun singular-debug-output-filter (string)
686  "Echo STRING in mini-buffer."
687  (singular-debug 'interactive-filter
688                  (message "Output filter: %s"
689                           (singular-debug-format string))))
690;;}}}
691
692;;{{{ Demo mode
693(defvar singular-demo-chunk-regexp "\\(\n\n\\)"
694  "Regular expressions to recognize chunks of a demo file.
695If there is a subexpression specified its content is removed when the
696chunk is displayed.")
697
698(defvar singular-demo-mode nil
699  "Non-nil if Singular demo mode is on.
700
701This variable is buffer-local.")
702
703(defvar singular-demo-old-mode-name nil
704  "Used to store previous `mode-name' before switching to demo mode.
705
706This variable is buffer-local.")
707
708(defvar singular-demo-end nil
709  "Marker pointing to end of demo file.
710
711This variable is buffer-local.")
712
713(defun singular-demo-mode-init ()
714  "Initialize local variables and markers beloging to demo mode."
715  (make-local-variable 'singular-demo-mode)
716  (make-local-variable 'singular-demo-mode-old-name)
717  (make-local-variable 'singular-demo-mode-end)
718  (if (not (and (boundp 'singular-demo-end)
719                singular-demo-end))
720      (setq singular-demo-end (make-marker))))
721
722(defun singular-demo-mode (on)
723  "Turn Singular demo mode on if ON is non-nil, otherwise off.
724Modifies `singular-demo-mode' and buffer's mode line."
725  (cond
726   ;; test on logical equality off ON and `singular-demo-mode'
727   ((eq (not on) (not singular-demo-mode)) nil)
728   ;; switch on
729   (on
730    (setq singular-demo-old-mode-name mode-name
731          mode-name "Singular Demo"
732          singular-demo-mode t)
733    (force-mode-line-update))
734   (;; switch off
735    t
736    (setq mode-name singular-demo-old-mode-name
737          singular-demo-mode nil)
738    (force-mode-line-update))))
739
740(defun singular-demo-show-next-chunk ()
741  "Show next chunk of demo file at input prompt.
742Moves point to end of buffer and widenes the buffer such that the next
743chunk of the demo file becomes visible.
744Finds and removes chunk separators as specified by
745`singular-demo-chunk-regexp'.
746Removing chunk separators works without affecting undo information,
747but may change buffer-modified flag.
748Returns non-nil if there is still demo text to show."
749  (let ((buffer-undo-list t)
750        (old-point-min (point-min)))
751    (unwind-protect
752        (progn
753          (goto-char (point-max))
754          (widen)
755          (progn
756            (if (re-search-forward singular-demo-chunk-regexp singular-demo-end 'limit)
757                (progn
758                  (and (match-beginning 1)
759                       (delete-region (match-beginning 1) (match-end 1)))
760                  t)
761              ;; remove trailing white-space
762              (skip-syntax-backward "-")
763              (delete-region (point) singular-demo-end)
764              nil)))
765
766      ;; this is unwind-protected
767      (narrow-to-region old-point-min (point)))))
768
769(defun singular-demo-load (demo-file)
770  "Load demo file DEMO-FILE and switch to Singular demo mode.
771For a description of Singular demo mode one should refer to the
772doc-string of `singular-send-input'.
773Moves point to end of buffer, inserts contents of DEMO-FILE there, and
774makes the first chunk of the demo file visible."
775  (interactive "fLoad demo file: ")
776  (let ((old-point-min (point-min)))
777    (unwind-protect
778        (progn
779          (goto-char (point-max))
780          (widen)
781          ;; load file and remember its end
782          (set-marker singular-demo-end
783                      (+ (point) (nth 1 (insert-file-contents demo-file)))))
784
785      ;; completely hide demo file.
786      ;; This is unwide protected.
787      (narrow-to-region old-point-min (point)))
788
789    ;; show first chunk of demo file
790    (singular-demo-mode (singular-demo-show-next-chunk))))
791;;}}}
792     
793;;{{{ Sending input and receiving output
794
795;;{{{ Some lengthy notes on filters
796
797;; Note:
798;;
799;; The filters and other functions have access to four important markers,
800;; `comint-last-input-start', `comint-last-input-end',
801;; `comint-last-output-start', and the buffers process mark.  They are
802;; initialized to nil (except process mark, which is initialized to
803;; `(point-max)') when Singular is called in `singular'.  These markers are
804;; modified by `comint-send-input' and `comint-output-filter' but not in a
805;; quite reliable way.  Here are some valid invariants and pre-/post-
806;; conditions.
807;;
808;; Output filters:
809;; ---------------
810;; The output filters may be sure that they are run in the process buffer
811;; and that the process buffer is still alive.  `comint-output-filter'
812;; ensures this.  But `comint-output-filter' does neither catch changes in
813;; match data done by the filters nor does it protect against non-local
814;; exits of itself or of one of the filters.  As a result, the current
815;; buffer may be changed in `comint-output-filter'!
816;;
817;; `comint-output-filter' is called also from `comint-send-input' (dunno
818;; why).  The following holds only for executions of `comint-output-filter'
819;; as a result of Singular output being processed.
820;;
821;; We have the following preconditions for any output filters (up to
822;; changes through other filter functions):
823;; - The argument STRING is what has been inserted in the buffer.  Not
824;;   really reliable.
825;; - `comint-last-input-end' <= `comint-last-output-start' <= process mark
826;;   if all of them are defined
827;; - The text between `comint-last-output-start' and process mark is the
828;;   one which has been inserted immediately before.
829;; - The text between `comint-last-input-end' (if it is defined) and
830;;   process mark is the one which has been inserted into buffer since last
831;;   user input.
832;; - It seems to be a reasonable assumption that the text between process
833;;   mark and `(point-max)' is user input.
834;;
835;; The standard filters which come with comint.el do not change the markers
836;; in the preconditions described above.  But they may change the text
837;; (e.g., `comint-strip-ctrl-m').
838;;
839;; Post-conditions for `comint-output-filter':
840;; - `comint-last-output-start' <= process mark.  The region between them
841;;   is the text which has been inserted immediately before.
842;; - `comint-last-input-start' and `comint-last-input-end' are unchanged.
843;;
844;; Input filters:
845;; --------------
846;; `comint-send-input' ensures that the process is still alive.  Further
847;; preconditions for any input filter (up to changes through filter
848;; functions):
849;; - The (CR-terminated) argument STRING is what will be sent to the
850;;   process (up to slight differences between XEmacs and Emacs).  Not
851;;   really reliable.
852;; - process mark <= `(point)'
853;; - The (CR-terminated) text between process mark and `(point)' is what
854;;   has been inserted by the user.
855;;
856;; Post-conditions for `comint-send-input':
857;; - `comint-last-input-start' <= `comint-last-input-end'
858;;                              = `comint-last-output-start' (!)
859;;                              = process mark = `(point)'.
860;;   The region between the first of them is what has been inserted by the
861;;   user.
862;;
863;; Invariants which always hold outside `comint-send-input' and
864;; `comint-output-filter':
865;; ------------------------------------------------------------
866;; - `comint-last-input-start' <= `comint-last-input-end' <= process mark
867;;   if all of them are defined.  The region between the first of them is
868;;   the last input entered by the user, the region between the latter of
869;;   them is the text from Singular printed since the last input.
870;; - `comint-last-output-start' <= process mark if both are defined.
871;; - It is a reasonable assumption that the text from process mark up to
872;;   `(point-max)' is user input.
873
874;;}}}
875
876(defun singular-get-old-input (get-section)
877  "Retrieve old input.
878Retrivies from beginning of current section to point if GET-SECTION is
879non-nil, otherwise on a per-line base."
880  (if get-section
881      ;; get input from input section
882      (let ((section (singular-section-at (point))))
883        (if (eq (singular-section-type section) 'input)
884            (setq old-input (singular-input-section-to-string section (point)))
885          (error "Not on an input section")))
886    ;; get input from line
887    (save-excursion
888      (beginning-of-line)
889      (singular-skip-prompt-forward)
890      (let ((old-point (point)))
891        (end-of-line)
892        (buffer-substring old-point (point))))))
893
894(defun singular-send-or-copy-input (send-full-section)
895  "NOT READY!!"
896  (interactive "P")
897
898  (let ((process (get-buffer-process (current-buffer)))
899        pmark)
900    ;; some checks and initializations
901    (or process (error "Current buffer has no process"))
902    (setq pmark (marker-position (process-mark process)))
903
904    (cond
905     (;; check for demo mode and show next chunk if necessary
906      (and singular-demo-mode
907          (eq (point) pmark)
908          (eq pmark (point-max)))
909      (singular-demo-mode (singular-demo-show-next-chunk)))
910
911     (;; get old input
912      (< (point) pmark)
913      (let ((old-input (singular-get-old-input send-full-section)))
914        (goto-char (point-max))
915        (insert old-input)))
916
917     (;; send input from pmark to point
918      t
919      ;; note that the input string does not include its terminal newline
920      (let* ((raw-input (buffer-substring pmark (point)))
921             (input raw-input)
922             (history raw-input))
923
924        ;; insert newline into buffer
925        (insert ?\n)
926
927        ;; insert input into history
928        (if (and (funcall comint-input-filter history)
929                 (or (null comint-input-ignoredups)
930                     (not (ring-p comint-input-ring))
931                     (ring-empty-p comint-input-ring)
932                     (not (string-equal (ring-ref comint-input-ring 0) history))))
933            (ring-insert comint-input-ring history))
934
935        ;; run hooks and reset index into history
936        (run-hook-with-args 'comint-input-filter-functions (concat input "\n"))
937        (setq comint-input-ring-index nil)
938
939        ;; update markers and create a new simple section
940        (set-marker comint-last-input-start pmark)
941        (set-marker comint-last-input-end (point))
942        (set-marker (process-mark process) (point))
943        (singular-debug 'interactive-simple-secs
944                        (message "Simple input section: %S"
945                                 (singular-simple-sec-create 'input (point)))
946                        (singular-simple-sec-create 'input (point)))
947
948        ;; do it !!
949        (send-string process input)
950        (send-string process "\n"))))))
951
952(defun singular-output-filter (process string)
953  "Insert STRING containing output from PROCESS into its associated buffer.
954
955Takes care off:
956- current buffer, even in case of non-local exits;
957- point and restriction in buffer associated with process;
958- markers which should not be advanced when inserting output.
959Updates:
960- process mark;
961- `comint-last-output-start';
962- simple sections;
963- mode line.
964Runs the hooks on `comint-output-filter-functions'.
965
966For a more detailed descriptions of the output filter, the markers it
967sets, and output filter functions refer to the section \"Some lengthy
968notes on filters\" in singular.el."
969  (let ((process-buffer (process-buffer process))
970        (old-buffer (current-buffer)))
971
972    ;; check whether buffer is still alive
973    (if (and process-buffer (buffer-name process-buffer))
974        (unwind-protect
975            (progn
976              (set-buffer process-buffer)
977              (let ((old-point (point))
978                    (old-point-min (point-min))
979                    (old-point-max (point-max))
980                    (old-pmark (marker-position (process-mark process)))
981                    (n (length string)))
982                (widen)
983                (goto-char old-pmark)
984
985                ;; adjust point and narrowed region borders
986                (if (<= (point) old-point) (setq old-point (+ old-point n)))
987                (if (< (point) old-point-min) (setq old-point-min (+ old-point-min n)))
988                (if (<= (point) old-point-max) (setq old-point-max (+ old-point-max n)))
989
990                ;; do it !!
991                (insert-before-markers string)
992
993                ;; reset markers and simple sections which may have
994                ;; been advanced by above insertion.  We rely on the
995                ;; fact that `set-marker' always returns some non-nil
996                ;; value.  Looks nicer this way.
997                (and (= comint-last-input-end (point))
998                     (set-marker comint-last-input-end old-pmark)
999                     ;; this may happen only on startup and only if
1000                     ;; `comint-last-input-end' has been modified,
1001                     ;; too.  Hence, we check for it after the first
1002                     ;; test.
1003                     (= comint-last-input-start (point))
1004                     (set-marker comint-last-input-start old-pmark))
1005                (and (= singular-simple-sec-last-end (point))
1006                     (singular-simple-sec-reset-last old-pmark))
1007
1008                ;; set new markers and create/extend new simple section
1009                (set-marker comint-last-output-start old-pmark)
1010                (singular-debug 'interactive-simple-secs
1011                                (message "Simple output section: %S"
1012                                         (singular-simple-sec-create 'output (point)))
1013                                (singular-simple-sec-create 'output (point)))
1014
1015                ;; restore old values, run hooks, and force mode line update
1016                (narrow-to-region old-point-min old-point-max)
1017                (goto-char old-point)
1018                (run-hook-with-args 'comint-output-filter-functions string)
1019                (force-mode-line-update)))
1020
1021          ;; this is unwind-protected
1022          (set-buffer old-buffer)))))
1023;;}}}
1024
1025;;{{{ Singular interactive mode
1026(defun singular-interactive-mode ()
1027  "Major mode for interacting with Singular.
1028
1029NOT READY [how to send input]!
1030
1031NOT READY [multiple Singulars]!
1032
1033Singular buffers are automatically limited in length \(by default, to
10342048 lines).  This limit may be adjusted by setting
1035`singular-buffer-maximum-size' before Singular interactive mode starts
1036up or by setting `comint-buffer-maximum-size' while Singular
1037interactive mode is running.
1038
1039\\{singular-interactive-mode-map}
1040Customization: Entry to this mode runs the hooks on `comint-mode-hook'
1041and `singular-interactive-mode-hook' \(in that order).  Before each
1042input, the hooks on `comint-input-filter-functions' are run.  After
1043each Singular output, the hooks on `comint-output-filter-functions'
1044are run.
1045
1046NOT READY [much more to come.  See shell.el.]!"
1047  (interactive)
1048
1049  ;; run comint mode and do basic mode setup
1050  (comint-mode)
1051  (setq major-mode 'singular-interactive-mode)
1052  (setq mode-name "Singular Interaction")
1053  (use-local-map singular-interactive-mode-map)
1054
1055  ;; customize comint for Singular
1056  (setq comint-prompt-regexp singular-prompt-regexp)
1057  (setq comint-delimiter-argument-list singular-delimiter-argument-list)
1058  (setq comint-input-ignoredups singular-input-ignoredups)
1059  (make-local-variable 'comint-buffer-maximum-size)
1060  (setq comint-buffer-maximum-size singular-buffer-maximum-size)
1061  (setq comint-input-ring-size singular-input-ring-size)
1062  (setq comint-input-filter singular-history-filter)
1063  ;; do not add `comint-truncate-buffer' if it already has been added
1064  ;; globally.  This is sort of a bug in `add-hook'.
1065  (and (default-boundp 'comint-output-filter-functions)
1066       (not (memq 'comint-truncate-buffer
1067                  (default-value 'comint-output-filter-functions)))
1068       (add-hook 'comint-output-filter-functions
1069                 'comint-truncate-buffer nil t))
1070
1071  ;; get name of history file (if any)
1072  (setq comint-input-ring-file-name (getenv "SINGULARHIST"))
1073  (if (or (not comint-input-ring-file-name)
1074          (equal comint-input-ring-file-name "")
1075          (equal (file-truename comint-input-ring-file-name) "/dev/null"))
1076      (setq comint-input-ring-file-name nil))
1077
1078  ;; initialize singular demo mode
1079  (singular-demo-mode-init)
1080
1081  ;; selective display
1082  (setq selective-display t)
1083  (setq selective-display-ellipses t)
1084  (cond
1085   ;; Emacs
1086   ((eq singular-emacs-flavor 'emacs)
1087    (setq buffer-display-table (or (copy-sequence standard-display-table)
1088                                   (make-display-table)))
1089    (set-display-table-slot buffer-display-table
1090     'selective-display (vconcat singular-folding-ellipsis)))
1091    ;; XEmacs
1092   (t
1093    (set-glyph-image invisible-text-glyph singular-folding-ellipsis (current-buffer))))
1094
1095  ;; input and output filters
1096  (singular-debug 'interactive-filter
1097                  (add-hook 'comint-input-filter-functions
1098                            'singular-debug-input-filter nil t))
1099  (singular-debug 'interactive-filter
1100                  (add-hook 'comint-output-filter-functions
1101                            'singular-debug-output-filter nil t))
1102
1103  (run-hooks 'singular-interactive-mode-hook))
1104;;}}}
1105
1106;;{{{ Starting singular
1107(defvar singular-start-file "~/.emacs_singularrc"
1108  "Name of start-up file to pass to Singular.
1109If the file named by this variable exists it is given as initial input
1110to any Singular process being started.  Note that this may lose due to
1111a timing error if Singular discards input when it starts up.")
1112
1113(defvar singular-default-executable "Singular"
1114  "Default name of Singular executable.
1115Used by `singular' when new Singular processes are started.")
1116
1117(defvar singular-default-name "singular"
1118  "Default process name for Singular process.
1119Used by `singular' when new Singular processes are started.")
1120
1121(defvar singular-default-switches '("-t")
1122  "Default switches for Singular processes.
1123Used by `singular' when new Singular processes are started.")
1124
1125(defun singular-exit-sentinel (process message)
1126 "Clean up after termination of Singular.
1127Writes back input ring after regular termination of Singular if
1128process buffer is still alive."
1129  (save-excursion
1130    (singular-debug 'interactive
1131                    (message "Sentinel: %s" (substring message 0 -1)))
1132    (if (string-match "finished\\|exited" message)
1133        (let ((process-buffer (process-buffer process)))
1134          (if (and process-buffer
1135                   (buffer-name process-buffer)
1136                   (set-buffer process-buffer))
1137              (progn
1138                (singular-debug 'interactive (message "Writing input ring back"))
1139                (comint-write-input-ring)))))))
1140
1141(defun singular-exec (buffer name executable start-file switches)
1142  "Start a new Singular process NAME in BUFFER, running EXECUTABLE.
1143EXECUTABLE should be a string denoting an executable program.
1144SWITCHES should be a list of strings that are passed as command line
1145switches.  START-FILE should be the name of a file which contents is
1146sent to the process.
1147
1148Deletes any old processes running in that buffer.
1149Moves point to the end of BUFFER.
1150Initializes all important markers and the simple sections.
1151Runs `comint-exec-hook' and `singular-exec-hook' (in that order).
1152Returns BUFFER."
1153  (let ((old-buffer (current-buffer)))
1154    (unwind-protect
1155        (progn
1156          (set-buffer buffer)
1157
1158          ;; delete any old processes
1159          (let ((process (get-buffer-process buffer)))
1160            (if process (delete-process process)))
1161
1162          ;; create new process
1163          (singular-debug 'interactive (message "Starting new Singular"))
1164          (let ((process (comint-exec-1 name buffer executable switches)))
1165
1166            ;; set process filter and sentinel
1167            (set-process-filter process 'singular-output-filter)
1168            (set-process-sentinel process 'singular-exit-sentinel)
1169            (make-local-variable 'comint-ptyp)
1170            (setq comint-ptyp process-connection-type) ; T if pty, NIL if pipe.
1171
1172            ;; go to the end of the buffer, set up markers, and
1173            ;; initialize simple sections
1174            (goto-char (point-max))
1175            (set-marker comint-last-input-start (point))
1176            (set-marker comint-last-input-end (point))
1177            (set-marker comint-last-output-start (point))
1178            (set-marker (process-mark process) (point))
1179            (singular-simple-sec-init (point))
1180
1181            ;; feed process with start file and read input ring.  Take
1182            ;; care about the undo information.
1183            (if start-file
1184                (let ((buffer-undo-list t) start-string)
1185                  (singular-debug 'interactive (message "Feeding start file"))
1186                  (sleep-for 1)                 ; try to avoid timing errors
1187                  (insert-file-contents start-file)
1188                  (setq start-string (buffer-substring (point) (point-max)))
1189                  (delete-region (point) (point-max))
1190                  (send-string process start-string)))
1191            (singular-debug 'interactive (message "Reading input ring"))
1192            (comint-read-input-ring t)
1193
1194            ;; execute hooks
1195            (run-hooks 'comint-exec-hook)
1196            (run-hooks 'singular-exec-hook))
1197         
1198          buffer)
1199      ;; this code is unwide-protected
1200      (set-buffer old-buffer))))
1201
1202;; Note:
1203;;
1204;; In contrast to shell.el, `singular' does not run
1205;; `singular-interactive-mode' every time a new Singular process is
1206;; started, but only when a new buffer is created.  This behaviour seems
1207;; more intuitive w.r.t. local variables and hooks.
1208
1209(defun singular (&optional executable name switches)
1210  "Run an inferior Singular process, with I/O through an Emacs buffer.
1211
1212NOT READY [arguments, default values, and interactive use]!
1213
1214If buffer exists but Singular is not running, starts new Singular.
1215If buffer exists and Singular is running, just switches to buffer.
1216If a file `~/.emacs_singularrc' exists, it is given as initial input.
1217Note that this may lose due to a timing error if Singular discards
1218input when it starts up.
1219
1220If a new buffer is created it is put in Singular interactive mode,
1221giving commands for sending input and handling ouput of Singular.  See
1222`singular-interactive-mode'.
1223
1224Every time `singular' starts a new Singular process it runs the hooks
1225on `comint-exec-hook' and `singular-exec-hook' \(in that order).
1226
1227Type \\[describe-mode] in the Singular buffer for a list of commands."
1228  ;; handle interactive calls
1229  (interactive (list singular-default-executable
1230                     singular-default-name
1231                     singular-default-switches))
1232
1233  (let* (;; get default values for optional arguments
1234         (executable (or executable singular-default-executable))
1235         (name (or name singular-default-name))
1236         (switches (or switches singular-default-switches))
1237
1238         (buffer-name (singular-process-name-to-buffer-name name))
1239         ;; buffer associated with Singular, nil if there is none
1240         (buffer (get-buffer buffer-name)))
1241
1242    (if (not buffer)
1243        (progn
1244          ;; create new buffer and call `singular-interactive-mode'
1245          (singular-debug 'interactive (message "Creating new buffer"))
1246          (setq buffer (get-buffer-create buffer-name))
1247          (set-buffer buffer)
1248          (singular-debug 'interactive (message "Calling `singular-interactive-mode'"))
1249          (singular-interactive-mode)))
1250
1251    (if (not (comint-check-proc buffer))
1252        ;; create new process if there is none
1253        (singular-exec buffer name executable
1254                       (if (file-exists-p singular-start-file)
1255                           singular-start-file)
1256                       switches))
1257
1258    ;; pop to buffer
1259    (singular-debug 'interactive (message "Calling `pop-to-buffer'"))
1260    (pop-to-buffer buffer)))
1261
1262;; for convenience only
1263(defalias 'Singular 'singular)
1264;;}}}
1265;;}}}
1266
1267(provide 'singular)
1268
1269;;; singular.el ends here.
Note: See TracBrowser for help on using the repository browser.