;; Run the Neuron program under Emacs, so we don't have to use MicroEmacs to ;; edit programs. ;; ;; $Id: neuron.el,v 1.1 1994/03/22 19:14:40 holt Exp $ ;; ;; $Log: neuron.el,v $ ; Revision 1.1 1994/03/22 19:14:40 holt ; Initial revision ; ;; ;; Written by Gary Holt (holt@klab.caltech.edu) 16-Mar-1993. ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Copyright (C) 1993 Free Software Foundation, Inc. ;; ;; GNU Emacs is free software; you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by ;; the Free Software Foundation; either version 1, or (at your option) ;; any later version. ;; GNU Emacs is distributed in the hope that it will be useful, ;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;; GNU General Public License for more details. ;; You should have received a copy of the GNU General Public License ;; along with GNU Emacs; see the file COPYING. If not, write to ;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. ;; ;; This package provides a convenient interface between GNU emacs and ;; a neuron program. Neuron is run as a subprocess of emacs (using the ;; comint interface); commands can be submitted to neuron by simply ;; typing in the neuron buffer. Also an entire hoc file can be executed ;; simply by typing C-c C-c. ;; ;; A rudimentary hoc-mode is also provided that can indent lines reasonably ;; well based on the structure of the hoc program. I assume some people ;; probably hate automatic indentation, so this feature can be turned off ;; easily. Just type M-x hoc-toggle-indent to turn off indentation; this ;; still allows C-c C-c to communicate with neuron. ;; ;; ;; This package seems to work on both emacs-19 and emacs-18; I haven't ;; tried it with lemacs or any of the other variants of GNU emacs. ;; It has only been tested so far with the current beta version of ;; neuron. For older versions which do not support the // comment style, ;; you may have to change comment-start to "/* " and comment-end to "*/" ;; Other than that, it should work fine. ;; ;; ;; To install this package, place the following lines in your .emacs file: ;; ;;(autoload 'neuron "neuron" "Interact with neuron simulator" t) ;;(autoload 'hoc-mode "neuron" "Edit a hoc (higher order calculator) file" t) ;;(setq auto-mode-alist (append '(("\\.hoc$" . hoc-mode)) auto-mode-alist)) ;; ; Make hoc mode load automatically. ;; ;; You also might want to redefine some of the following variables. ;; (defvar neuron-program-name "I-don't-exist" "*The name of the program to run in the neuron buffer.") ; Specifying a non-existent name ; asks the user for the program. (defvar hoc-block-indent 2 "*Indentation of hoc statements with respect to containing block.") (defvar hoc-continued-statement-offset 2 "*Extra indent for lines not starting new statements.") (defvar hoc-save-some-buffers t "*If non-nil, hoc-send-buffer asks user whether to save any modified buffers.") (defvar hoc-temp-directory nil "*Directory used for creating temporary files for hoc-send-region. If nil, uses the directory of the hoc file you're editing. The name should end in a slash.") (defvar hoc-temp-filename "____delete_me.hoc" "*File name used for temporary files. Currently this file isn't deleted automatically. Sorry.") ; ; Backwards compatibility with emacs-18: ; (if (string-lessp emacs-version "19") (progn ; Execute if emacs 18: (defun make-comint (name program) "Replacement for emacs-19 make-comint." (make-shell name program)) (defun comint-send-input () "Replacement for emacs-19 comint-send-input." (shell-send-input)) (autoload 'make-shell "shell") ; Load the shell automatically. (autoload 'calculate-c-indent-within-comment "c-mode") ; c mode is always loaded in emacs-19, ; but not in emacs-18. (setq neuron-last-input-start 'last-input-start ; Define which variables neuron-last-input-end 'last-input-end ; we should use. neuron-prompt-regexp 'shell-prompt-pattern neuron-mode-map 'shell-mode-map)) (progn ; Execute if emacs 19: (setq neuron-last-input-start 'comint-last-input-start neuron-last-input-end 'comint-last-input-end neuron-prompt-regexp 'comint-prompt-regexp neuron-mode-map 'comint-mode-map))) ;;; ;;; Make sure user has everything set up correctly to run neuron: ;;; (defun neuron-check-startup () "Validates the set up of neuron. Asks user for anything which is not already defined." (interactive) (let (neuron-home) (while (not (and (setq neuron-home (getenv "NEURONHOME")) (file-directory-p neuron-home))) (setq neuron-home (expand-file-name (read-file-name "Value of $NEURONHOME: " nil nil t))) (if (string= (substring neuron-home (1- (length neuron-home))) "/") (setq neuron-home ; Remove a trailing slash. (substring neuron-home 0 (1- (length neuron-home))))) (setenv "NEURONHOME" neuron-home))) (if (getenv "CPU") nil ; Needs to have CPU type defined. (setenv "CPU" (read-from-minibuffer "CPU type: " (upcase (or (getenv "ARCH") ""))))) (neuron-set-program-name)) ; Read the program name. (defun neuron-set-program-name () "Sets the file name of the neuron program to run. Use this function if you have several neuron programs and you want to switch between them." (interactive) ; (setq neuron-program-name "this-file-hopefully-doesn't-exist") (while (not (file-exists-p neuron-program-name)) (setq neuron-program-name (expand-file-name (read-file-name "Neuron program: " nil neuron-program-name t))))) ;;; ;;; Start up neuron mode: ;;; (defun neuron () "Run the neuron program so it can talk to GNU emacs. This allows us to dispense with the built-in microemacs editor. The program to run is stored in neuron-program-name. The default directory is the default from the current buffer unless neuron-default-directory is defined." (interactive) (switch-to-buffer (find-neuron-buffer)) ; Make the neuron buffer. (goto-char (point-max))) ; Go to the bottom. ;;; ;;; Function to find which buffer the neuron program is running in, or to make ;;; it if it doesn't exist. ;;; (defun find-neuron-buffer () (let (buffer (get-buffer "*neuron*")); Try to get an existing buffer. (if (get-buffer-process buffer) buffer ; Make sure it has a process. ;; ;; Create a new neuron process: ;; (neuron-check-startup) ; Make sure environment is set ; correctly. (let* ((default-directory ; Set the default directory to be (if (and (boundp 'neuron-default-directory) ; the current (neuron-default-directory)) ; unless a directory is neuron-default-directory ; specified. default-directory)) (buffer (make-comint "neuron" neuron-program-name))) (save-excursion (set-buffer buffer) (make-variable-buffer-local neuron-prompt-regexp) ; Set prompt for (set neuron-prompt-regexp "^.*oc>")) ; neuron. (sleep-for 1) ; Wait for header to display. buffer)))) ; Return it. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; ;;; Definition of hoc mode. ;;; (defvar hoc-function-start-pattern "^[ ]*\\(proc\\|func\\)[ ]+[a-zA-Z_0-9]+[ ]*([ ,a-zA-Z_0-9]*)[ ]*{" "*A regular expression which matches a hoc procedure or function definition.") ;; ;; Keymaps: ;; (defvar hoc-mode-map nil "Keymap for hoc mode with automatic indentation.") (defvar hoc-indent-disabled-map nil "Keymap for hoc mode with indentation disabled.") (defun hoc-define-keys (keymap &optional no-indent) "Defines standard hoc-mode keys for keymap. If no-indent is non-nil, only defines the keys not related to indenting." (if no-indent nil (define-key keymap "\177" 'backward-delete-char-untabify) (define-key keymap "\M-\C-q" 'hoc-indent-exp) ; Indent expression. (define-key hoc-mode-map "}" '(lambda (arg) (interactive "P") (insert "}") ; Put the brace in. (hoc-indent-line) ; Indent the line properly. (delete-char -1) ; Remove it. (self-insert-command (prefix-numeric-value arg)))) ; Insert it so the ; matching brace blinks. ) (define-key keymap "\C-ce" 'hoc-send-line) ; Send line to neuron. (define-key keymap "\C-cr" 'hoc-send-region); Send region to neuron. (define-key keymap "\C-c\C-c" 'hoc-send-buffer); Send buffer. (define-key keymap "\C-c\C-n" 'hoc-next-function) (define-key keymap "\C-c\C-p" 'hoc-previous-function) (define-key keymap "\C-c\C-f" 'hoc-send-function) (define-key keymap "\C-cf" 'hoc-mark-function)) (if hoc-indent-disabled-map nil (setq hoc-indent-disabled-map (make-sparse-keymap)) (hoc-define-keys hoc-indent-disabled-map t)) (if hoc-mode-map nil (setq hoc-mode-map (make-sparse-keymap)) (hoc-define-keys hoc-mode-map)) ;; ;; Syntax table: ;; This syntax table was stolen shamelessly from c-mode.el. ;; (defvar hoc-mode-syntax-table nil "Syntax table in use in hoc-mode buffers.") (if hoc-mode-syntax-table nil (setq hoc-mode-syntax-table (make-syntax-table)) (modify-syntax-entry ?\\ "\\" hoc-mode-syntax-table) (modify-syntax-entry ?/ ". 14" hoc-mode-syntax-table) (modify-syntax-entry ?* ". 23" hoc-mode-syntax-table) (modify-syntax-entry ?+ "." hoc-mode-syntax-table) (modify-syntax-entry ?- "." hoc-mode-syntax-table) (modify-syntax-entry ?= "." hoc-mode-syntax-table) (modify-syntax-entry ?% "." hoc-mode-syntax-table) (modify-syntax-entry ?< "." hoc-mode-syntax-table) (modify-syntax-entry ?> "." hoc-mode-syntax-table) (modify-syntax-entry ?& "." hoc-mode-syntax-table) (modify-syntax-entry ?| "." hoc-mode-syntax-table) (modify-syntax-entry ?\' "\"" hoc-mode-syntax-table)) ;; ;; Turn on hoc mode: ;; (defun hoc-mode () "Major mode for editing .hoc files for neurons. The most important command is C-c C-c, which sends the buffer to neuron to execute. A process is created if none exists. Other keys: \\{hoc-mode-map} Entry into this mode calls the value of hoc-mode-hook with no arguments, if that value is non-nil. By default, tab indents the current line according to indentation rules similar to c-mode. If you want tab to insert a hardware tab, you can turn off hoc-mode indentation by calling hoc-indent-toggle. Variables controlling hoc mode indentation: hoc-block-indent Additional indentation for each block surrounded by braces. Only relevant if hoc-indent-enable is non-nil. hoc-continued-statement-offset Additional indentation for a line which is a continuation of the previous line. Only relevant if hoc-indent-enable is non-nil." (interactive) (kill-all-local-variables) ; Trash previous major mode. (setq major-mode 'hoc-mode) (setq mode-name "Hoc") (make-local-variable 'comment-start) (make-local-variable 'comment-end) (make-local-variable 'comment-start-skip) (make-local-variable 'comment-indent-function) (make-local-variable 'require-final-newline) (make-local-variable 'indent-line-function) (make-local-variable 'hoc-indent-enabled) (setq comment-start "// " comment-end "" comment-start-skip "// *" ; Used to be "\\(// *\\|/\\* *\\)", but ; comment-indent has this stupid code ; that checks for parentheses in the ; regular expression. comment-indent-function 'c-comment-indent hoc-indent-enabled nil ; Turn indentation off so we can toggle ; it on (& set up many other params). require-final-newline t) ; Neuron (at least the older versions) ; may do very strange things if its ; input doesn't end in a newline. (hoc-toggle-indent) ; Turn indentation mode on. (run-hooks 'hoc-mode-hook)) (defun hoc-toggle-indent () "Toggles the function of the TAB key. TAB can either insert a hardware tab or calculate a line indentation as is done in c-mode." (interactive) (cond (hoc-indent-enabled ; Did it used to be on? (setq hoc-indent-enabled nil ; Turn it off. indent-line-function 'indent-to-left-margin) (use-local-map hoc-indent-disabled-map)) ; Enable only C-c C-c. (t ; Used to be off: (setq hoc-indent-enabled t ; Turn it on. indent-line-function 'hoc-indent-line) (use-local-map hoc-mode-map)))) ; Enable all the indentation keys. (defun hoc-next-function () "Finds the next hoc function by searching for a pattern matching beginning of function." (interactive) (re-search-forward hoc-function-start-pattern)) (defun hoc-previous-function () "Finds the prior hoc function by searching for a pattern matching beginning of function." (interactive) (re-search-backward hoc-function-start-pattern)) (defun hoc-send-line () "Sends current line of text to the hoc interpreter (neuron)." (interactive) (let ((eolptr (progn (end-of-line) (point)))) ; Mark end of line. (beginning-of-line) ; Move to first character. (hoc-send-string (buffer-substring (point) eolptr)))) (defun hoc-send-string (string-to-send) "Sends a string to the neuron process. All tabs are removed from the string to prevent readline from doing variable name expansion." (let* ((buffer (find-neuron-buffer)) ; Find neuron buffer. (process (get-buffer-process buffer)) beg-insert) (pop-to-buffer buffer) ; Switch to the neuron buffer. (goto-char (point-max)) ; Move to the end. (setq beg-insert (point)) ; Remember where insertion started. (insert string-to-send) ; Put the text in. (untabify beg-insert (point)) ; Remove tabs. (comint-send-input))) ; Send the input. (defun hoc-send-region (beg-region end-region) "Sends a region of text to the hoc interpreter (neuron). Makes a temp file in the directory specified by hoc-temp-directory. The temp file is not deleted. Sorry." (interactive "r") ;; ;; Put the string we are sending into a temporary buffer and save it into ;; a temporary file. We could send a multi-line string directly, but that ;; causes neuron to repeat its prompt. Also, neuron gets very confused ;; when multiline comments are input via the terminal. ;; (let ((temp-file-name (expand-file-name (concat (or hoc-temp-directory default-directory) hoc-temp-filename))) (string-to-send (buffer-substring beg-region end-region)) (temp-buffer (or (get-buffer " *hoc-temp*") (generate-new-buffer " *hoc-temp*"))) (hoc-save-some-buffers nil)) ; Temporarily turn off buffer saving. (save-excursion (set-buffer temp-buffer) ; Switch to temporary buffer. (make-local-variable 'version-control) ; Don't make backups of (setq version-control 'never) ; ____delete_me.hoc. (delete-region (point-min) (point-max)) (insert string-to-send) ; Put the text in. (goto-char (point-max)) ; Put a final newline at the end, if (beginning-of-line) ; there isn't one, or else hoc will (if (equal (point-max) (point)) ; give a bizarre error message. nil (progn (goto-char (point-max)) (insert "\n"))) (write-region (point-min) (point-max) hoc-temp-filename nil 'no-message)) (kill-buffer temp-buffer) (let* ((buffer (find-neuron-buffer)) ; Get the neuron buffer. (process (get-buffer-process buffer))) ; Get the process. (pop-to-buffer buffer) ; Switch to the neuron buffer. (goto-char (point-max)) ; Move to the end. (move-marker (eval neuron-last-input-start) (point)) ; Remember where input started. (move-marker (eval neuron-last-input-end) (point)) ; Remember where last input ended. (set-marker (process-mark process) (point)) (process-send-string process (concat "{ xopen(\"" temp-file-name "\") }\n"))))) (defun hoc-send-buffer () "Sends the current buffer to neuron. This saves the file before sending it. Neuron is actually sent a command to read the file." (interactive) (let ((file-to-execute (buffer-file-name))) ; File we save it in. (save-excursion (goto-char (point-max)) ; Put a final newline at the end, if (beginning-of-line) ; there isn't one, or else hoc will (if (equal (point-max) (point)) ; give a bizarre error message. nil (progn (goto-char (point-max)) (insert "\n")))) (save-buffer) ; Save the current buffer. (if hoc-save-some-buffers (save-some-buffers)) ; Ask user if we should save ; other buffers. (let* ((buffer (find-neuron-buffer)) ; Get the neuron buffer. (process (get-buffer-process buffer))) ; Get the process. (pop-to-buffer buffer) ; Switch to the neuron buffer. (goto-char (point-max)) ; Move to the end. (move-marker (eval neuron-last-input-start) (point)) ; Remember where input started. (move-marker (eval neuron-last-input-end) (point)) ; Remember where last input ended. (set-marker (process-mark process) (point)) (process-send-string process (concat "{ xopen(\"" file-to-execute "\") }\n"))))) ;; ;; Mark the current hoc function. Places point at the beginning, mark at the ;; end. ;; (defun hoc-mark-function () "Places point at beginning of function, mark at end." (interactive) (if (re-search-backward hoc-function-start-pattern (point-min) t) (progn (search-forward "{") (forward-char -1) ; Go to just before opening brace. (mark-sexp 1) ; Mark this expression. (forward-line 0)))) ; Go to beginning of current line. (defun hoc-send-function () "Sends current function to neuron. Use when you've only modified one function and you just want to reexecute its definition." (interactive) (hoc-mark-function) (hoc-send-region (point) (mark))) ;; ;; Functions for indenting hoc lines: ;; (defun hoc-indent-exp () "Indent each line of the current hoc grouping following point. To indent a whole block of code, point must be positioned just before the opening brace, as in c-mode." (interactive) (mark-sexp 1) (indent-region (point) (mark) nil)) (defun hoc-indent-line () "Indent current line as hoc code." (interactive) (let ((new-col nil)) ; new-col is position we want to be at, ; if different. (save-excursion (let* ((old-col (current-column)) (old-indent (current-indentation)) (indent (hoc-calculate-indent)) (beg-line (progn (beginning-of-line) (point))) ; Where line starts. shift-amt) (if (not indent) nil ; Are we in a string? If so, no change (setq shift-amt (- old-indent indent)) ; Calculate difference. (if (/= shift-amt 0) ; Any change? (progn (skip-chars-forward " \t") ; Skip over any indentations. (delete-region beg-line (point)) ; Delete leading whitespace. (indent-to indent))) ; Set correct indentation. ;; ;; If user was positioned in the whitespace preceding the first ;; character, position him to the indent position. Otherwise ;; it is very confusing because the cursor doesn't end up ;; where it is expected if the line is blank. ;; (if (<= old-col old-indent) (setq new-col indent))))) (if new-col (move-to-column (max 0 new-col))))) ;; ;; Function to back up to last non-blank character not inside a comment. ;; Swiped from c-mode and simplified. ;; (defun hoc-backward-to-noncomment (lim) (let (stop) (while (not stop) ;; ;; First look for old-style /* */ comments: ;; (while (not stop) (skip-chars-backward " \r\t\n\f" lim) (if (and (>= (point) (+ 2 lim)) (save-excursion (forward-char -2) (looking-at "\\*/"))) (while (and (search-backward "/*" lim 'move) (hoc-in-quote))) (setq stop t))) ;; ;; Now make sure there isn't a // on the line: ;; (let ((opoint (point)) ; Remember previous end of line. (bol-point (progn (beginning-of-line) (point)))) ; Go to beginning. (while (and (search-forward (if (eq major-mode 'hoc-mode) "//" ":") opoint t) ; Look for // or : in mod mode. (if (hoc-in-quote) t ; Skip if quoted. (forward-char -2) ; Found one. Backup to first /. (setq stop nil)))) ; Check again for /* */. (if stop ; Didn't find a //? (goto-char opoint)))))) ; Restore cursor position. (defun hoc-beginning-of-statement nil "Function to move point to the first non-blank character in the current statement." (interactive) (while (progn (beginning-of-line) ; See if current line could be the ; first line of a statement. (skip-chars-backward " \t\f\n"); Move to end of last line. (= (preceding-char) ?\\))) ; Is this a continuation? (skip-chars-forward " \t\f\n")) ; Move to first non-blank char of ; statement. (defun hoc-in-old-style-comment () "Returns the first character of a comment in the old style (/* */), if point is somewhere in the body of a comment. Returns nil otherwise." (let ((opoint (point)) found-cmt) (while (and (setq found-cmt (search-backward "/*" (point-min) t)) (hoc-in-quote))) ; Search backwards for opening comment. (if found-cmt ; Found beginning of comment? (setq found-cmt (if (search-forward "*/" opoint t) ; Loop for end of comment. nil ; Found. This comment's over. (point)))) (goto-char opoint) ; Restore cursor position. found-cmt)) ;; ;; The following function tries to determine if we are inside a double quoted ;; string or not. The idea for this was borrowed somewhat from cplus-md.el. ;; (defun hoc-in-quote () "Returns true if point is in a quoted string, nil if not." (let ((opoint (point)) ; Previous location of point. (n-quotes 0)) (while (progn ; Back up to where string could ; possibly begin. (beginning-of-line) ; Move to beginning of current line. (skip-chars-backward " \t\f\n\r") ; Find last non-blank char. (= (preceding-char) ?\\))) ; Back up a line if last line ends in / (while (search-forward "\"" opoint t) ; Find the next quote. (if (/= (preceding-char) ?\\) ; Recognize a backslash escape. (setq n-quotes (1+ n-quotes))) ; Remember that we saw another quote. (forward-char 1)) ; Skip the matched character. (goto-char opoint) ; Restore point position. (not (zerop (logand n-quotes 1))))) ; We are in a quote if there are an ; odd number of quotes. (defun hoc-calculate-indent () "Calculates indentation for current line. Returns nil if we're inside a string; always returns a number otherwise." (if (hoc-in-old-style-comment) (calculate-c-indent-within-comment) (save-excursion (beginning-of-line) (skip-chars-forward " \t") ; Move to first non-blank char. (let ((old-point (point))) ;;; ;;; The algorithm for indenting is a little simpler than C mode, because ;;; hoc doesn't have statements that go on for more than one line unless ;;; they're continued by a backslash. ;;; (if (= (following-char) ?\}) ; Conclusion of block? (progn (forward-char 1) ; Move to the other side of {. (backward-sexp) ; Go to the matching {. (hoc-beginning-of-statement) ; Go to beginning, in case this line ; is continued. (current-indentation)) ; Use its indentation. ;;; ;;; This is not a closing brace. If this isn't a continuation line, indent ;;; the same as the previous line unless there are unmatched opening braces. ;;; (hoc-backward-to-noncomment (point-min)) ; Go to previous char. (if (/= (preceding-char) ?\\) ; If it wasn't a backslash, just use (let* ((eol-prec (point)) ; Remember where this line ends. (n-unmatched-open 0) ; Number of unmatched open braces. current-char (beg-prec (progn (hoc-beginning-of-statement) (point)))) ; Go to beginning of prior statement. (if (= (following-char) ?\}) (forward-char 1)) ; Skip a leading brace. (while (re-search-forward "[{}]" eol-prec t) ; Find a significant character. (if (hoc-in-quote) nil ; Ignore if in a quoted string. (setq current-char (preceding-char)) (cond ((= current-char ?\{) ; Opening brace? (setq n-unmatched-open (1+ n-unmatched-open))) ((= current-char ?\}) ; Closing brace? (setq n-unmatched-open (1- n-unmatched-open)))))) (goto-char beg-prec) ; Go back to beginning of prior stmt. (+ (current-indentation) (* hoc-block-indent n-unmatched-open)) ) ;;; ;;; This is a continued statement. Find the last unbalanced parenthesis and ;;; use its indentation, or else just indent from the beginning of the block. ;;; (hoc-beginning-of-statement) (let* ((statement-begin-column (current-column)) (parse-sexp-ignore-comments t) (sexp-list (parse-partial-sexp (point) old-point)) (inner-sexp (car (cdr sexp-list)))) (cond ((nth 3 sexp-list) ; Are we in a string? nil) ; Don't change indentation. (inner-sexp ; Are we inside a parenthesis? (goto-char inner-sexp) ; Move to open parenthesis. (+ (current-column) 1)) ; Indentation level is 1 more. (t ; Otherwise, just indent a little (goto-char old-point) ; Move cursor to first nonblank char ; of line we're indenting. (if (looking-at "else") statement-begin-column (+ statement-begin-column hoc-continued-statement-offset))) ) ) ) ) ) ) ) ) ;; ;; A rudimentary mod-file mode. This is basically hoc mode except that ;; the comment separator is changed. Note that the hoc mode indentation ;; does a lot of unnecessary stuff with comments and trailing backslashes, ;; that that shouldn't interfere. ;; ;; The indentation won't work properly for verbatim blocks or things ;; like that, but I don't care much. ;; (defun mod-mode () "Major mode for editing .mod files. The only feature of this mode is automatic indentation." (interactive) (hoc-mode) ; Switch to hoc mode. ;; ;; Now make modifications from hoc mode: ;; (setq comment-start ": " ; Comments in mod mode. comment-end "" comment-start-skip ": *" mode-name "Mod" major-mode 'mod-mode)) (provide 'neuron)