(provide "io-mode") (in-package "editor") (export '(*io-mode-hook* *io-tab-always-indent* *io-keyword-file*)) (export '(io-mode io-indent-line io-newline-and-indent io-electric-insert io-electric-close)) (defvar *io-tab-always-indent* t) (defvar *io-indent-column* 4) (defvar *io-keyword-file* "io") (defvar *io-mode-syntax-table* nil) (unless *io-mode-syntax-table* (setq *io-mode-syntax-table* (make-syntax-table)) (set-syntax-symbol *io-mode-syntax-table* #\_) (set-syntax-start-multi-comment *io-mode-syntax-table* "/*") (set-syntax-end-multi-comment *io-mode-syntax-table* "*/") (set-syntax-start-c++-comment *io-mode-syntax-table* #\/ t) (set-syntax-end-c++-comment *io-mode-syntax-table* #\LFD) (set-syntax-string *io-mode-syntax-table* #\") (set-syntax-string *io-mode-syntax-table* #\') (set-syntax-match *io-mode-syntax-table* #\( #\)) (set-syntax-match *io-mode-syntax-table* #\[ #\]) (set-syntax-escape *io-mode-syntax-table* #\\)) (defvar *io-mode-map* nil) (unless *io-mode-map* (setq *io-mode-map* (make-sparse-keymap)) (define-key *io-mode-map* #\( 'io-electric-insert) (define-key *io-mode-map* #\) 'io-electric-close) (define-key *io-mode-map* #\TAB 'io-indent-line) (define-key *io-mode-map* #\RET 'io-newline-and-indent)) (defvar *io-keyword-hash-table* nil) (defvar *io-mode-hook* nil "io-mode: hook") (defvar io-regexp-keyword nil "io-mode: regexp") (setq *io-regexp-keyword* (compile-regexp-keyword-list `( ("#[^\r\n]*$" t :comment) ("\\b\\(0[x]\\)?[0-9a-f.]+\\(e[+-]?[0-9]+\\)?\\b" t (:color 1)) ))) (defun io-indent-line () (interactive "*") (if (or (not (interactive-p)) *io-tab-always-indent* (save-excursion (skip-chars-backward " \t") (bolp))) (case (save-excursion (goto-bol) (parse-point-syntax)) (:string) (:comment (let ((column (calc-c-comment-indent))) (when (integerp column) (smart-indentation column)))) (t (let ((column (calc-io-indent))) (when (integerp column) (smart-indentation column))))) (insert "\t")) t) (defun io-newline-and-indent (&optional (arg 1)) (interactive "*p") (delete-trailing-spaces) (io-indent-line) (insert #\LFD arg) (io-indent-line)) (defun calc-io-indent () (let ((col 0)) (save-excursion (goto-bol) (while (scan-buffer "(" :reverse t :regexp nil :tail nil :no-dup t) (if (not (parse-point-syntax)) (setq col (+ col *io-indent-column*))) ) ) (save-excursion (goto-bol) (if (looking-at "^[^(\n]*?).*?$") ; (if (looking-at "^[ \t]*?).*?$") (setq col (- col *io-indent-column*))) (while (scan-buffer ")" :reverse t :regexp nil :tail nil :no-dup t) (if (not (parse-point-syntax)) (setq col (- col *io-indent-column*))) ) ) ; (message (format nil "~d" col)) col)) (defun io-electric-insert (&optional (arg 1)) (interactive "*p") (unless (prog1 (parse-point-syntax) (self-insert-command arg)) (io-indent-line)) t) (defun io-electric-close (&optional (arg 1)) (interactive "*p") (unless (prog1 (parse-point-syntax) (self-insert-command arg)) (io-indent-line)) (save-excursion (forward-char -1) (and (goto-matched-parenthesis) (show-matched-parenthesis))) t) (defun io-mode () (interactive) (kill-all-local-variables) (setq buffer-mode 'io-mode) (setq mode-name "io") (use-keymap *io-mode-map*) (use-syntax-table *io-mode-syntax-table*) (and *io-keyword-file* (null *io-keyword-hash-table*) (setq *io-keyword-hash-table* (load-keyword-file *io-keyword-file* t))) (when *io-keyword-hash-table* (make-local-variable 'keyword-hash-table) (setq keyword-hash-table *io-keyword-hash-table*)) (make-local-variable 'regexp-keyword-list) (setf regexp-keyword-list *io-regexp-keyword*) (setq mode-specific-indent-command 'io-indent-line) (setq comment-indent-function 'c-comment-indent) (run-hooks '*io-mode-hook*))