├── defunkt ├── defunkt.el ├── sgml.el ├── theme.el ├── github.el ├── twittering-mode.el ├── shell.el ├── erlang.el ├── dired.el ├── global.el ├── temp_files.el ├── css.el ├── coffee.el ├── markdown.el ├── lisp.el ├── git.el ├── python.el ├── erc.el ├── lua.el ├── bindings.el ├── artist.el ├── modes.el ├── custom.el ├── ruby.el ├── todo.el ├── javascript.el └── defuns.el ├── vendor ├── coffee-mode ├── treetop.el ├── ack.el ├── http-twiddle.el ├── ruby-hacks.el ├── textile-mode.el ├── any-ini-mode.el └── lua-mode.el ├── .gitignore ├── restore.rb ├── README.markdown ├── emacs.el ├── install.rb ├── defunkt.el └── .gitmodules /defunkt/defunkt.el: -------------------------------------------------------------------------------- 1 | ../defunkt.el -------------------------------------------------------------------------------- /vendor/coffee-mode: -------------------------------------------------------------------------------- 1 | /Users/chris/Code/coffee-mode -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | url/* 2 | .DS_Store 3 | local.el 4 | *.elc 5 | private.el 6 | -------------------------------------------------------------------------------- /defunkt/sgml.el: -------------------------------------------------------------------------------- 1 | (add-hook 'sgml-mode-hook 2 | (lambda () 3 | (define-key sgml-mode-map "\C-m" 'reindent-then-newline-and-indent))) 4 | -------------------------------------------------------------------------------- /defunkt/theme.el: -------------------------------------------------------------------------------- 1 | (require 'color-theme) 2 | (setq color-theme-is-global t) 3 | 4 | (load-file "~/.emacs.d/vendor/twilight-emacs/color-theme-twilight.el") 5 | (color-theme-twilight) -------------------------------------------------------------------------------- /defunkt/github.el: -------------------------------------------------------------------------------- 1 | ;; github specific lovelies 2 | 3 | (defvar *github-root* "~/Code/github") 4 | 5 | (defun github-ido-find-file () 6 | (interactive) 7 | (ido-find-file-in-dir *github-root*)) 8 | -------------------------------------------------------------------------------- /defunkt/twittering-mode.el: -------------------------------------------------------------------------------- 1 | (defun twittering-friends-refresh () 2 | (interactive) 3 | (twittering-mode) 4 | (twittering-friends-timeline)) 5 | (global-set-key "\C-x\C-t" 'twittering-friends-refresh) -------------------------------------------------------------------------------- /restore.rb: -------------------------------------------------------------------------------- 1 | # 2 | # After a fresh clone. For defunkt. 3 | # 4 | 5 | File.open('local.el', 'w') do |f| 6 | f.puts '(load "defunkt")' 7 | end 8 | 9 | puts "Don't forget to M-x byte-compile-file js2" 10 | -------------------------------------------------------------------------------- /README.markdown: -------------------------------------------------------------------------------- 1 | (defun kts (emacs config) 2 | "chris wanstrath // chris@ozmm.org" 3 | 4 | (git-clone "git://github.com/defunkt/emacs.git") 5 | (ruby "emacs/install.rb") 6 | (find-file "emacs/local.el") 7 | (insert '(load "defunkt")) 8 | (save-buffer)) 9 | -------------------------------------------------------------------------------- /emacs.el: -------------------------------------------------------------------------------- 1 | (add-to-list 'load-path "~/.emacs.d") 2 | 3 | ;; You're expected to populate .emacs.d/local.el 4 | ;; with your own code. This file is under .gitignore 5 | ;; so it won't be version-controlled. The idea is to 6 | ;; make this file load other version-controlled files. 7 | (load "local") 8 | -------------------------------------------------------------------------------- /defunkt/shell.el: -------------------------------------------------------------------------------- 1 | (global-set-key "\C-x\C-z" 'shell) ; shortcut for shell 2 | (add-hook 'shell-mode-hook 'ansi-color-for-comint-mode-on) 3 | 4 | (eval-after-load 'shell 5 | '(progn 6 | (define-key shell-mode-map [up] 'comint-previous-input) 7 | (define-key shell-mode-map [down] 'comint-next-input) 8 | (define-key shell-mode-map "\C-p" 'comint-previous-input) 9 | (define-key shell-mode-map "\C-n" 'comint-next-input))) -------------------------------------------------------------------------------- /defunkt/erlang.el: -------------------------------------------------------------------------------- 1 | (let* ((emacs-version "2.6.4") 2 | (tools-path 3 | (concat "/usr/local/lib/erlang/lib/tools-" emacs-version "/emacs"))) 4 | (when (file-exists-p tools-path) 5 | (setq load-path (cons tools-path load-path)) 6 | (setq erlang-root-dir "/usr/local/lib/erlang") 7 | (setq exec-path (cons "/usr/local/lib/erlang/bin" exec-path)) 8 | (require 'erlang-start) 9 | (defvar inferior-erlang-prompt-timeout t))) 10 | -------------------------------------------------------------------------------- /defunkt/dired.el: -------------------------------------------------------------------------------- 1 | ; Dired 2 | (require 'dired) 3 | 4 | ; remap 'o' in dired mode to open a file 5 | (defun dired-open-mac () 6 | (interactive) 7 | (let ((file-name (dired-get-file-for-visit))) 8 | (if (file-exists-p file-name) 9 | (call-process "/usr/bin/open" nil 0 nil file-name)))) 10 | (define-key dired-mode-map "o" 'dired-open-mac) 11 | 12 | ; - is `cd ..` (like vim) 13 | (define-key dired-mode-map "-" 'dired-up-directory) 14 | 15 | ; prefer dired over dumping dir list to buffer 16 | (global-set-key "\C-x\C-d" 'dired) -------------------------------------------------------------------------------- /defunkt/global.el: -------------------------------------------------------------------------------- 1 | (setq tags-file-name "TAGS") 2 | (setq-default tab-width 2) 3 | (setq-default indent-tabs-mode nil) 4 | (setq mac-emulate-three-button-mouse nil) 5 | (setq cua-highlight-region-shift-only t) 6 | (prefer-coding-system 'utf-8) 7 | (setq vc-handled-backends nil) 8 | (cua-mode nil) 9 | (setq gist-view-gist t) 10 | 11 | ;; works in both aquamacs and carbon 12 | (when (functionp 'tool-bar-mode) 13 | (tool-bar-mode -1)) 14 | 15 | ;; aquamacs specific 16 | (when (boundp 'aquamacs-version) 17 | (one-buffer-one-frame-mode 0)) 18 | -------------------------------------------------------------------------------- /defunkt/temp_files.el: -------------------------------------------------------------------------------- 1 | ; stolen from http://github.com/febuiles/dotemacs/tree/master/temp_files.el 2 | (defvar user-temporary-file-directory 3 | (concat temporary-file-directory user-login-name "/")) 4 | (make-directory user-temporary-file-directory t) 5 | (setq backup-by-copying t) 6 | (setq backup-directory-alist 7 | `(("." . ,user-temporary-file-directory) 8 | (,tramp-file-name-regexp nil))) 9 | (setq auto-save-list-file-prefix 10 | (concat user-temporary-file-directory ".auto-saves-")) 11 | (setq auto-save-file-name-transforms 12 | `((".*" ,user-temporary-file-directory t))) -------------------------------------------------------------------------------- /install.rb: -------------------------------------------------------------------------------- 1 | # this is not the ruby you're looking for 2 | require 'fileutils' 3 | 4 | alias :V :lambda 5 | 6 | Joiner = V do |base| 7 | V do |*others| 8 | File.join(base, *others) 9 | end 10 | end 11 | 12 | Home = Joiner[ File.expand_path( '~' ) ] 13 | Cwd = Joiner[ File.expand_path(File.dirname(__FILE__)) ] 14 | 15 | Link = V do |target, new| 16 | FileUtils.ln_s Cwd[ target ], Home[ new ] rescue puts("~/#{new} exists.") 17 | end 18 | 19 | Link[ 'emacs.el', '.emacs' ] 20 | Link[ '.', '.emacs.d' ] 21 | 22 | Git = V do |command, dir| 23 | Dir.chdir(dir) do 24 | `git #{command}` 25 | end 26 | end 27 | 28 | `git submodule update --init --recursive` 29 | -------------------------------------------------------------------------------- /defunkt/css.el: -------------------------------------------------------------------------------- 1 | ;; css 2 | 3 | (add-hook 'css-mode-hook 4 | (lambda () 5 | (setq css-mode-indent-depth 2) 6 | (make-local-variable 'indent-line-function) 7 | (setq indent-line-function 'css-indent) 8 | (define-key css-mode-map "\C-ct" 'css-insert-section) 9 | (define-key css-mode-map [tab] 'defunkt-indent))) 10 | 11 | (defun css-indent () 12 | (interactive) 13 | (insert " ")) 14 | 15 | (defun css-insert-section (section) 16 | "Inserts a kyle-style css section." 17 | (interactive "sSection: ") 18 | (insert "/*--------------------------------------------------------------------\n") 19 | (insert (concat " @group " section "\n")) 20 | (insert "--------------------------------------------------------------------*/\n") 21 | (insert "\n") 22 | (insert "\n") 23 | (insert "\n") 24 | (insert "/* @end */") 25 | (forward-line -2)) -------------------------------------------------------------------------------- /defunkt/coffee.el: -------------------------------------------------------------------------------- 1 | (defun defunkt-coffee-mode-hook () 2 | "defunkt's hacks and experiments for `coffee-mode.el'." 3 | 4 | ;; Compile .js on every save. 5 | ;; (add-hook 'before-save-hook 6 | ;; '(lambda () 7 | ;; (when (not (string= (buffer-name) "Cakefile")) 8 | ;; (shell-command "cake build")))) 9 | 10 | 11 | 12 | ;; aww yeah 13 | (define-key coffee-mode-map "\C-L" 'coffee-insert-console) 14 | 15 | ;; I like debug mode, sometimes. 16 | (setq coffee-debug-mode nil)) 17 | 18 | (add-hook 'coffee-mode-hook (lambda () (defunkt-coffee-mode-hook))) 19 | 20 | (defadvice textmate-next-line (around coffee-tm-next-line) 21 | (interactive) 22 | (if (string= major-mode "coffee-mode") 23 | (progn 24 | (end-of-line) 25 | (coffee-newline-and-indent)) 26 | ad-do-it)) 27 | (ad-activate 'textmate-next-line) 28 | 29 | (defun coffee-insert-console () 30 | (interactive) 31 | (insert "console.log ")) 32 | -------------------------------------------------------------------------------- /defunkt/markdown.el: -------------------------------------------------------------------------------- 1 | (add-to-list 'load-path "~/.emacs.d/vendor/markdown-mode") 2 | (autoload 'markdown-mode "markdown-mode.el" 3 | "Major mode for editing Markdown files" t) 4 | 5 | (setq auto-mode-alist (cons '("\\.markdown" . markdown-mode) auto-mode-alist)) 6 | (setq auto-mode-alist (cons '("\\.md" . markdown-mode) auto-mode-alist)) 7 | (setq auto-mode-alist (cons '("\\.ronn?" . markdown-mode) auto-mode-alist)) 8 | 9 | 10 | ;; Not ready. 11 | (defun defunkt-markdown-insert-link () 12 | "Inserts an awesome link: [Word][ref] with [ref]: url at the 13 | bottom. Prompts you, for sure." 14 | (interactive) 15 | (insert "[") 16 | (save-excursion 17 | (insert "]") 18 | (insert "[]"))) 19 | 20 | (add-hook 21 | 'markdown-mode-hook 22 | '(lambda () 23 | (define-key markdown-mode-map (kbd "C-c i") 'defunkt-markdown-insert-link) 24 | (define-key markdown-mode-map (kbd "A-r") 'markdown-preview) 25 | (define-key markdown-mode-map (kbd "") 'defunkt-indent))) 26 | -------------------------------------------------------------------------------- /defunkt.el: -------------------------------------------------------------------------------- 1 | (add-to-list 'load-path "~/.emacs.d/vendor") 2 | 3 | ; custom place to save customizations 4 | (setq custom-file "~/.emacs.d/defunkt/custom.el") 5 | (when (file-exists-p custom-file) (load custom-file)) 6 | 7 | (when (file-exists-p ".passwords") (load ".passwords")) 8 | 9 | (load "defunkt/lisp") 10 | (load "defunkt/global") 11 | (load "defunkt/defuns") 12 | (load "defunkt/bindings") 13 | (load "defunkt/modes") 14 | (load "defunkt/theme") 15 | (load "defunkt/temp_files") 16 | (load "defunkt/github") 17 | (load "defunkt/git") 18 | (load "defunkt/todo") 19 | 20 | (when (file-exists-p "defunkt/private") 21 | (load "defunkt/private")) 22 | 23 | (vendor 'ack) 24 | (vendor 'cheat) 25 | (vendor 'magit) 26 | (vendor 'gist) 27 | (vendor 'growl) 28 | (vendor 'twittering-mode) 29 | (vendor 'textile-mode) 30 | (vendor 'yaml-mode) 31 | (vendor 'open-file-in-github) 32 | (vendor 'ooc-mode) 33 | (vendor 'coffee-mode) 34 | (vendor 'lua-mode) 35 | (vendor 'any-ini-mode) 36 | (vendor 'mustache-mode) 37 | (vendor 'scss-mode) 38 | -------------------------------------------------------------------------------- /defunkt/lisp.el: -------------------------------------------------------------------------------- 1 | ;; 2 | ; defunkt's lisp playground 3 | ; 4 | 5 | (defun empty? (target) 6 | (eq target nil)) 7 | 8 | (defalias 'nil? 'empty?) 9 | (setq else t) 10 | 11 | ; 12 | ; (each (dog cat monkey) (x) 13 | ; (print x)) 14 | ; 15 | (defmacro each (list iterator body) 16 | `(let ((_l (if (listp ',list) ',list ,list))) 17 | (while (not (empty? _l)) 18 | (funcall (lambda (,@iterator) ,body) (car _l)) 19 | (setq _l (cdr _l))))) 20 | 21 | ; 22 | ; (eacht (dog cat monkey) 23 | ; (print this)) 24 | ; 25 | (defmacro eacht (list body) 26 | `(each ,list (this) ,body)) 27 | 28 | ; rubyish 29 | (defun select (list body) 30 | (if (empty? list) 31 | nil 32 | (if (funcall body (car list)) 33 | (cons (car list) (select (cdr list) body)) 34 | (select (cdr list) body)))) 35 | 36 | ; rubyish 37 | (defun reject (list body) 38 | (if (empty? list) 39 | nil 40 | (if (funcall body (car list)) 41 | (reject (cdr list) body) 42 | (cons (car list) (reject (cdr list) body))))) -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "twilight-emacs"] 2 | path = vendor/twilight-emacs 3 | url = git://github.com/crafterm/twilight-emacs.git 4 | [submodule "/magit"] 5 | path = vendor/magit 6 | url = git://github.com/technomancy/magit.git 7 | [submodule "cheat.el"] 8 | path = vendor/cheat.el 9 | url = git://github.com/defunkt/cheat.el.git 10 | [submodule "gist.el"] 11 | path = vendor/gist.el 12 | url = git://github.com/defunkt/gist.el.git 13 | [submodule "vendor/textmate.el"] 14 | path = vendor/textmate.el 15 | url = git://github.com/defunkt/textmate.el.git 16 | [submodule "vendor/yaml-mode.el"] 17 | path = vendor/yaml-mode.el 18 | url = git://github.com/yoshiki/yaml-mode.git 19 | [submodule "vendor/open-file-in-github"] 20 | path = vendor/open-file-in-github 21 | url = git://gist.github.com/170861.git 22 | [submodule "vendor/markdown-mode"] 23 | path = vendor/markdown-mode 24 | url = git://github.com/defunkt/markdown-mode.git 25 | [submodule "vendor/mustache-mode"] 26 | path = vendor/mustache-mode 27 | url = git://github.com/mustache/emacs 28 | [submodule "vendor/scss-mode"] 29 | path = vendor/scss-mode 30 | url = https://github.com/antonj/scss-mode 31 | -------------------------------------------------------------------------------- /defunkt/git.el: -------------------------------------------------------------------------------- 1 | ;; git stuff 2 | ;; experimental 3 | ;; depends on textmate.el as it 4 | ;; share's textmate.el's concept of 5 | ;; a project root 6 | 7 | (defun defunkt-git-modeline () 8 | (interactive) 9 | (let ((root (textmate-project-root))) 10 | (when (file-directory-p (concat root ".git")) 11 | (defunkt-set-mode-line (concat "Git: " (defunkt-git-current-branch root))) 12 | (force-mode-line-update t)))) 13 | 14 | (defun defunkt-set-mode-line (mode-line) 15 | ;; this has to be built in... 16 | (setq mode-line-format 17 | (append 18 | (butlast mode-line-format (- (length mode-line-format) 8)) 19 | (cons mode-line (nthcdr 8 mode-line-format))))) 20 | 21 | (defun defunkt-git-current-branch (root) 22 | (let ((result) (branches 23 | (split-string 24 | (shell-command-to-string 25 | (concat 26 | "git --git-dir=" 27 | root 28 | ".git branch --no-color")) 29 | "\n" t))) 30 | (while (and branches (null result)) 31 | (if (string-match "^\* \\(.+\\)" (car branches)) 32 | (setq result (match-string 1 (car branches))) 33 | (setq branches (cdr branches)))) 34 | result)) 35 | 36 | ;; (add-hook 'find-file-hook 'defunkt-git-modeline) 37 | ;; (add-hook 'dired-after-readin-hook 'defunkt-git-modeline) -------------------------------------------------------------------------------- /defunkt/python.el: -------------------------------------------------------------------------------- 1 | (add-hook 'python-mode-hook 2 | (lambda () 3 | (define-key python-mode-map "\C-m" 4 | 'python-reindent-then-newline-and-indent) 5 | (add-hook 'local-write-file-hooks 6 | '(lambda() 7 | (save-excursion 8 | (untabify (point-min) (point-max)) 9 | (delete-trailing-whitespace)))) 10 | (set (make-local-variable 'tab-width) 4) 11 | (set (make-local-variable 'indent-tabs-mode) 'nil))) 12 | 13 | (defun python-reindent-then-newline-and-indent () 14 | "Reindents the current line then creates an indented newline." 15 | (interactive "*") 16 | (newline) 17 | (save-excursion 18 | (end-of-line 0) 19 | (indent-according-to-mode) 20 | (delete-region (point) (progn (skip-chars-backward " \t") (point)))) 21 | (when (python-previous-line-is-comment) 22 | (insert "# ")) 23 | (indent-according-to-mode)) 24 | 25 | (defun python-previous-line-is-comment () 26 | "Returns `t' if the previous line is a Python comment." 27 | (save-excursion 28 | (forward-line -1) 29 | (python-line-is-comment))) 30 | 31 | (defun python-line-is-comment () 32 | "Returns `t' if the current line is a Python comment." 33 | (save-excursion 34 | (beginning-of-line) 35 | (search-forward "#" (point-at-eol) t))) 36 | -------------------------------------------------------------------------------- /defunkt/erc.el: -------------------------------------------------------------------------------- 1 | ;; channel name in prompt 2 | (setq erc-prompt (lambda () 3 | (if (and (boundp 'erc-default-recipients) (erc-default-target)) 4 | (erc-propertize (concat (erc-default-target) ">") 'read-only t 'rear-nonsticky t 'front-nonsticky t) 5 | (erc-propertize (concat "ERC>") 'read-only t 'rear-nonsticky t 'front-nonsticky t)))) 6 | 7 | (setq erc-track-exclude-types '("JOIN" "PART" "QUIT" "NICK" "MODE")) 8 | (setq erc-button-url-regexp 9 | "\\([-a-zA-Z0-9_=!?#$@~`%&*+\\/:;,]+\\.\\)+[-a-zA-Z0-9_=!?#$@~`%&*+\\/:;,]*[-a-zA-Z0-9\\/]") 10 | 11 | (setq erc-mode-line-format "%t (%n)") 12 | 13 | (defun defunkt-erc-update-topic (parsed) 14 | (interactive) 15 | 16 | (if (get-buffer (erc-response.contents parsed)) 17 | (with-current-buffer (erc-response.contents parsed) 18 | (if (hash-table-p erc-channel-users) 19 | (let* ((users (number-to-string (hash-table-count erc-channel-users))) 20 | (erc-mode-line-format (concat "%t (%n) " users))) 21 | (erc-update-mode-line-buffer (current-buffer))))))) 22 | 23 | ;; (add-hook 'erc-server-JOIN-functions 24 | ;; (lambda (PROC parsed) 25 | ;; (defunkt-erc-update-topic parsed))) 26 | ;; (add-hook 'erc-server-PART-functions 27 | ;; (lambda (PROC parsed) 28 | ;; (defunkt-erc-update-topic parsed))) 29 | 30 | (setq erc-autojoin-channels-alist 31 | '(("freenode.net" "#github" "#logicalawesome" "#rip" 32 | "#resque" "#{" "#sinatra" "#redis" "#coffeescript" 33 | "#thechangelog" ))) -------------------------------------------------------------------------------- /vendor/treetop.el: -------------------------------------------------------------------------------- 1 | ; from http://github.com/hornbeck/public_emacs 2 | 3 | (defvar treetop-mode-hook nil) 4 | 5 | (defvar treetop-mode-map 6 | (let ((treetop-mode-map (make-keymap))) 7 | (define-key treetop-mode-map "\C-j" 'newline-and-indent) 8 | treetop-mode-map) 9 | "Keymap for treetop major mode") 10 | 11 | (add-to-list 'auto-mode-alist '("\\.treetop\\'" . treetop-mode)) 12 | 13 | (defconst treetop-font-lock-keywords 14 | (list 15 | '("\\<\\grammar\\|rule\\|def\\|end\\>" . font-lock-builtin-face)) 16 | "Minimal highlighting expressions for treetop mode") 17 | 18 | (defvar treetop-mode-syntax-table 19 | (let ((treetop-mode-syntax-table (make-syntax-table))) 20 | (modify-syntax-entry ?_ "w" treetop-mode-syntax-table) 21 | (modify-syntax-entry ?/ ". 124b" treetop-mode-syntax-table) 22 | (modify-syntax-entry ?* ". 23" treetop-mode-syntax-table) 23 | (modify-syntax-entry ?\n "> b" treetop-mode-syntax-table) 24 | treetop-mode-syntax-table) 25 | "Syntax table for treetop-mode") 26 | 27 | (defun treetop-mode () 28 | "Major mode for editing treetop files" 29 | (interactive) 30 | (kill-all-local-variables) 31 | (set-syntax-table treetop-mode-syntax-table) 32 | (use-local-map treetop-mode-map) 33 | (set (make-local-variable 'font-lock-defaults) '(treetop-font-lock-keywords)) 34 | (set (make-local-variable 'indent-line-function) 'treetop-indent-line) 35 | (local-set-key "\t" " ") 36 | (setq major-mode 'treetop-mode) 37 | (setq mode-name "treetop") 38 | (run-hooks 'treetop-mode-hook)) 39 | 40 | (provide 'treetop) -------------------------------------------------------------------------------- /defunkt/lua.el: -------------------------------------------------------------------------------- 1 | ;; use an indentation width of two spaces 2 | (setq lua-indent-level 2) 3 | 4 | (defun lua-insert-puts () 5 | (interactive) 6 | (insert "puts()") 7 | (backward-char)) 8 | 9 | (defun lua-rake-run () 10 | (interactive) 11 | (shell-command "rake run")) 12 | 13 | (add-hook 'lua-mode-hook 14 | '(lambda () 15 | (define-key lua-mode-map (kbd "A-r") 'lua-rake-run) 16 | (define-key lua-mode-map "\C-L" 'lua-insert-puts))) 17 | 18 | ;; Add dangling '(', remove '=' 19 | ;; (setq lua-cont-eol-regexp 20 | ;; (eval-when-compile 21 | ;; (concat 22 | ;; "\\((\\|\\_<" 23 | ;; (regexp-opt '("and" "or" "not" "in" "for" "while" 24 | ;; "local" "function") t) 25 | ;; "\\_>\\|" 26 | ;; "\\(^\\|[^" lua-operator-class "]\\)" 27 | ;; (regexp-opt '("+" "-" "*" "/" "^" ".." "==" "<" ">" "<=" ">=" "~=") t) 28 | ;; "\\)" 29 | ;; "\\s *\\="))) 30 | 31 | ;; (defun lua-calculate-indentation (&optional parse-start) 32 | ;; "Overwrites the default lua-mode function that calculates the 33 | ;; column to which the current line should be indented to." 34 | ;; (save-excursion 35 | ;; (when parse-start 36 | ;; (goto-char parse-start)) 37 | 38 | ;; ;; We calculate the indentation column depending on the previous 39 | ;; ;; non-blank, non-comment code line. Also, when the current line 40 | ;; ;; is a continuation of that previous line, we add one additional 41 | ;; ;; unit of indentation. 42 | ;; (+ (if (lua-is-continuing-statement-p) lua-indent-level 0) 43 | ;; (if (lua-goto-nonblank-previous-line) 44 | ;; (+ (current-indentation) (lua-calculate-indentation-right-shift-next)) 45 | ;; 0)))) 46 | 47 | ;; (defun lua-calculate-indentation-right-shift-next (&optional parse-start) 48 | -------------------------------------------------------------------------------- /defunkt/bindings.el: -------------------------------------------------------------------------------- 1 | ; general 2 | (global-set-key "\C-x\C-b" 'buffer-menu) 3 | (global-set-key "\C-x\C-m" 'execute-extended-command) 4 | (global-set-key "\C-c\C-m" 'execute-extended-command) 5 | (global-set-key "\C-c\C-g" 'gist-buffer-confirm) 6 | (global-set-key "\C-xg" 'magit-status) 7 | (global-set-key "\M-i" 'insert-soft-tab) 8 | (global-set-key "\M-z" 'defunkt-zap-to-char) 9 | (global-set-key "\C-xp" 'defunkt-ido-find-project) 10 | (global-set-key "\C-cp" 'defunkt-ido-find-config) 11 | (global-set-key "\C-cP" 'defunkt-goto-config) 12 | (global-set-key [C-return] 'defunkt-duplicate-line) 13 | (global-set-key "\C-x\C-g" 'github-ido-find-file) 14 | (global-set-key "\C-R" 'replace-string) 15 | (global-set-key (kbd "C-S-N") 'word-count) 16 | (global-set-key (kbd "A-F") 'ack) 17 | 18 | ; todo 19 | (global-set-key [M-return] 'defunkt-todo-toggle) 20 | (global-set-key "\C-xt" 'defunkt-todo-quick-enter) 21 | (global-set-key [M-down] 'defunkt-todo-move-item-down) 22 | (global-set-key [M-up] 'defunkt-todo-move-item-up) 23 | 24 | ; vim emulation 25 | (global-set-key [C-tab] 'other-window) 26 | ;; (global-set-key [M-up] 'defunkt-inc-num-at-point) 27 | ;; (global-set-key [M-down] 'defunkt-dec-num-at-point) 28 | (global-set-key (kbd "C-*") 'isearch-forward-at-point) 29 | (global-set-key [remap kill-word] 'defunkt-kill-word) 30 | (global-set-key (kbd "C-S-k") 'defunkt-backward-kill-line) 31 | (global-set-key [remap backward-kill-word] 'defunkt-backward-kill-word) 32 | (global-set-key [remap aquamacs-backward-kill-word] 'defunkt-backward-kill-word) 33 | 34 | ;; no printing! 35 | ;; no changing meta key!! 36 | (when (boundp 'osx-key-mode-map) 37 | ;; Option is my meta key. 38 | (define-key osx-key-mode-map (kbd "A-;") 39 | '(lambda () (interactive) (message "noop"))) 40 | 41 | ;; What's paper? 42 | (define-key osx-key-mode-map (kbd "A-p") 43 | '(lambda () (interactive) (message "noop")))) 44 | 45 | ; no mailing! 46 | (global-unset-key (kbd "C-x m")) 47 | (global-unset-key "\C-z") 48 | -------------------------------------------------------------------------------- /defunkt/artist.el: -------------------------------------------------------------------------------- 1 | ;;; integrate ido with artist-mode 2 | (defun artist-ido-select-operation (type) 3 | "Use ido to select a drawing operation in artist-mode" 4 | (interactive (list (ido-completing-read "Drawing operation: " 5 | (list "Pen" "Pen Line" "line" "straight line" "rectangle" 6 | "square" "poly-line" "straight poly-line" "ellipse" 7 | "circle" "text see-thru" "text-overwrite" "spray-can" 8 | "erase char" "erase rectangle" "vaporize line" "vaporize lines" 9 | "cut rectangle" "cut square" "copy rectangle" "copy square" 10 | "paste" "flood-fill")))) 11 | (artist-select-operation type)) 12 | (defun artist-ido-select-settings (type) 13 | "Use ido to select a setting to change in artist-mode" 14 | (interactive (list (ido-completing-read "Setting: " 15 | (list "Set Fill" "Set Line" "Set Erase" "Spray-size" "Spray-chars" 16 | "Rubber-banding" "Trimming" "Borders")))) 17 | (if (equal type "Spray-size") 18 | (artist-select-operation "spray set size") 19 | (call-interactively (artist-fc-get-fn-from-symbol 20 | (cdr (assoc type '(("Set Fill" . set-fill) 21 | ("Set Line" . set-line) 22 | ("Set Erase" . set-erase) 23 | ("Rubber-banding" . rubber-band) 24 | ("Trimming" . trimming) 25 | ("Borders" . borders) 26 | ("Spray-chars" . spray-chars)))))))) 27 | (add-hook 'artist-mode-init-hook 28 | (lambda () 29 | (define-key artist-mode-map (kbd "C-c C-a C-o") 'artist-ido-select-operation) 30 | (define-key artist-mode-map (kbd "C-c C-a C-c") 'artist-ido-select-settings))) -------------------------------------------------------------------------------- /defunkt/modes.el: -------------------------------------------------------------------------------- 1 | ;; others 2 | (load "defunkt/dired") 3 | (load "defunkt/ruby") 4 | (load "defunkt/shell") 5 | (load "defunkt/javascript") 6 | (load "defunkt/erlang") 7 | (load "defunkt/python") 8 | (load "defunkt/sgml") 9 | (load "defunkt/erc") 10 | (load "defunkt/artist") 11 | (load "defunkt/coffee") 12 | (load "defunkt/markdown") 13 | (load "defunkt/css") 14 | (load "defunkt/lua") 15 | 16 | ;; all modes 17 | (add-hook 'before-save-hook 'delete-trailing-whitespace) 18 | 19 | ;; emacs 20 | (define-key emacs-lisp-mode-map (kbd "A-r") 'eval-buffer) 21 | 22 | ; bash 23 | (setq auto-mode-alist (cons '("\\.bashrc" . sh-mode) auto-mode-alist)) 24 | 25 | ; obj-c 26 | (setq auto-mode-alist (cons '("\\.m$" . objc-mode) auto-mode-alist)) 27 | ;; (setq c-default-style "bsd" c-basic-offset 2) 28 | 29 | ; magit 30 | (eval-after-load 'magit 31 | '(progn 32 | (set-face-foreground 'magit-diff-add "green3") 33 | (set-face-foreground 'magit-diff-del "red3"))) 34 | 35 | ; paredit 36 | (autoload 'paredit-mode "paredit" 37 | "Minor mode for pseudo-structurally editing Lisp code." 38 | t) 39 | (add-hook 'emacs-lisp-mode-hook (lambda () (paredit-mode +1))) 40 | 41 | ; jasper 42 | (setq auto-mode-alist (cons '("\\.jr" . emacs-lisp-mode) auto-mode-alist)) 43 | 44 | ; mode-compile 45 | (autoload 'mode-compile "mode-compile" 46 | "Command to compile current buffer file based on the major mode" t) 47 | (global-set-key "\C-cc" 'mode-compile) 48 | 49 | (autoload 'mode-compile-kill "mode-compile" 50 | "Command to kill a compilation launched by `mode-compile'" t) 51 | (global-set-key "\C-ck" 'mode-compile-kill) 52 | 53 | 54 | ; yaml 55 | (add-to-list 'auto-mode-alist '("\\.yml$" . yaml-mode)) 56 | (add-hook 'yaml-mode-hook 57 | '(lambda () 58 | (define-key yaml-mode-map "\C-m" 'newline-and-indent))) 59 | 60 | 61 | ; c 62 | (add-hook 'c-mode-hook 63 | '(lambda () 64 | (setq c-auto-newline t) 65 | (define-key c-mode-map "{" 'defunkt/c-electric-brace))) 66 | 67 | ;; mustache 68 | (add-to-list 'auto-mode-alist '("\\.mustache$" . mustache-mode)) 69 | 70 | ;; textmate.el 71 | (vendor 'textmate) 72 | (textmate-mode) 73 | (setq textmate-find-files-command "git ls-tree --full-tree --name-only -r HEAD") -------------------------------------------------------------------------------- /defunkt/custom.el: -------------------------------------------------------------------------------- 1 | ;; customization 2 | (custom-set-variables 3 | ;; custom-set-variables was added by Custom. 4 | ;; If you edit it by hand, you could mess it up, so be careful. 5 | ;; Your init file should contain only one such instance. 6 | ;; If there is more than one, they won't work right. 7 | '(aquamacs-additional-fontsets nil t) 8 | '(aquamacs-customization-version-id 190 t) 9 | '(cua-mode nil nil (cua-base)) 10 | '(default-frame-alist (quote ((tool-bar-lines . 0) (foreground-color . "white") (background-color . "black") (menu-bar-lines . 1) (font . "-apple-inconsolata-medium-r-normal--20-180-72-72-m-180-iso10646-1")))) 11 | '(erc-modules (quote (autojoin button completion fill irccontrols match menu netsplit noncommands readonly ring scrolltobottom stamp track))) 12 | '(javascript-shell-command "johnson") 13 | '(js2-auto-indent-flag nil) 14 | '(js2-basic-offset 2) 15 | '(js2-bounce-indent-flag t) 16 | '(js2-enter-indents-newline t) 17 | '(js2-strict-missing-semi-warning nil) 18 | '(python-honour-comment-indentation nil) 19 | '(ruby-deep-arglist nil) 20 | '(ruby-deep-indent-paren nil) 21 | '(ruby-deep-indent-paren-style nil) 22 | '(show-paren-mode nil) 23 | '(standard-indent 2) 24 | '(tabbar-mode nil nil (tabbar)) 25 | '(text-mode-hook (quote (smart-spacing-mode))) 26 | '(transient-mark-mode t)) 27 | (custom-set-faces 28 | ;; custom-set-faces was added by Custom. 29 | ;; If you edit it by hand, you could mess it up, so be careful. 30 | ;; Your init file should contain only one such instance. 31 | ;; If there is more than one, they won't work right. 32 | '(default ((t (:stipple nil :background "black" :foreground "white" :inverse-video nil :box nil :strike-through nil :overline nil :underline nil :slant normal :weight normal :height 180 :width normal :family "apple-inconsolata")))) 33 | '(autoface-default ((t (:inherit default :background "black" :foreground "white" :inverse-video nil :box nil :strike-through nil :overline nil :underline nil :slant normal :weight normal :height 180 :width normal :family "apple-inconsolata")))) 34 | '(emacs-lisp-mode-default ((t (:inherit autoface-default))) t) 35 | '(js2-mode-default ((t (:inherit autoface-default))) t) 36 | '(minibuffer-prompt ((((background dark)) (:foreground "cyan" :height 180)))) 37 | '(mode-line ((t (:inherit aquamacs-variable-width :background "grey75" :foreground "black" :width normal)))) 38 | '(text-mode-default ((t (:inherit autoface-default))) t)) 39 | -------------------------------------------------------------------------------- /defunkt/ruby.el: -------------------------------------------------------------------------------- 1 | ; rinari 2 | (vendor 'rinari) 3 | (setq rinari-tags-file-name "TAGS") 4 | (add-hook 'rinari-minor-mode-hook 5 | (lambda () 6 | (define-key rinari-minor-mode-map (kbd "A-r") 'rinari-test))) 7 | 8 | ; rhtml 9 | (setq auto-mode-alist (cons '("\\.html\\.erb" . nxml-mode) auto-mode-alist)) 10 | (setq auto-mode-alist (cons '("\\.erb" . nxml-mode) auto-mode-alist)) 11 | 12 | ; ruby 13 | (vendor 'ruby-hacks) 14 | (setq auto-mode-alist (cons '("Rakefile" . ruby-mode) auto-mode-alist)) 15 | (setq auto-mode-alist (cons '("Capfile" . ruby-mode) auto-mode-alist)) 16 | (setq auto-mode-alist (cons '("Gemfile" . ruby-mode) auto-mode-alist)) 17 | (setq auto-mode-alist (cons '("\\.rake" . ruby-mode) auto-mode-alist)) 18 | (setq auto-mode-alist (cons '("\\.god" . ruby-mode) auto-mode-alist)) 19 | (setq auto-mode-alist (cons '("\\.ru" . ruby-mode) auto-mode-alist)) 20 | (setq auto-mode-alist (cons '("\\.gemspec" . ruby-mode) auto-mode-alist)) 21 | 22 | ;; no warnings when compiling 23 | (setq ruby-dbg-flags "") 24 | 25 | (add-hook 'ruby-mode-hook 26 | (lambda () 27 | (add-hook 'local-write-file-hooks 28 | '(lambda() 29 | (save-excursion 30 | (untabify (point-min) (point-max))))) 31 | (set (make-local-variable 'indent-tabs-mode) 'nil) 32 | (set (make-local-variable 'tab-width) 2) 33 | (define-key ruby-mode-map "\C-m" 'ruby-reindent-then-newline-and-indent) 34 | (require 'ruby-electric) 35 | (ruby-electric-mode t))) 36 | 37 | (defadvice ruby-do-run-w/compilation (before kill-buffer (name cmdlist)) 38 | (let ((comp-buffer-name (format "*%s*" name))) 39 | (when (get-buffer comp-buffer-name) 40 | (kill-buffer comp-buffer-name)))) 41 | (ad-activate 'ruby-do-run-w/compilation) 42 | 43 | ; where'd this go? 44 | (defun ruby-reindent-then-newline-and-indent () 45 | "Reindents the current line then creates an indented newline." 46 | (interactive "*") 47 | (newline) 48 | (save-excursion 49 | (end-of-line 0) 50 | (indent-according-to-mode) 51 | (delete-region (point) (progn (skip-chars-backward " \t") (point)))) 52 | (when (ruby-previous-line-is-comment) 53 | (insert "# ")) 54 | (indent-according-to-mode)) 55 | 56 | (defun ruby-previous-line-is-comment () 57 | "Returns `t' if the previous line is a Ruby comment." 58 | (save-excursion 59 | (forward-line -1) 60 | (ruby-line-is-comment))) 61 | 62 | (defun ruby-line-is-comment () 63 | "Returns `t' if the current line is a Ruby comment." 64 | (save-excursion 65 | (beginning-of-line) 66 | (search-forward "#" (point-at-eol) t))) 67 | 68 | ; treetop 69 | (vendor 'treetop) -------------------------------------------------------------------------------- /defunkt/todo.el: -------------------------------------------------------------------------------- 1 | (defvar defunkt-todo-global-file "~/.todo" 2 | "Path to the todo file used by `defunkt-todo-quick-jump' and friends.") 3 | 4 | (defun defunkt-todo-quick-enter () 5 | "Prompts for a new todo item to be inserted into the global todo file." 6 | (interactive) 7 | (let ((item (read-string "TODO: "))) 8 | (if (string= "" item) 9 | (defunkt-todo-quick-jump) 10 | (defunkt-todo-add-global-item item)))) 11 | 12 | (defun defunkt-todo-quick-jump () 13 | "Visits the global todo file." 14 | (interactive) 15 | (find-file defunkt-todo-global-file)) 16 | 17 | (defun defunkt-todo-add-global-item (item) 18 | "Adds an item to the global todo file." 19 | (save-excursion 20 | (set-buffer (find-file-noselect defunkt-todo-global-file)) 21 | (when (not (= (point-min) (point-max))) 22 | (goto-char (point-max)) 23 | (insert "\n")) 24 | (insert item) 25 | (defunkt-todo-toggle)) 26 | (message "TODO: Item added.")) 27 | 28 | (defun defunkt-todo-toggle () 29 | "Toggles the todo state if it's active, otherwise activates it. " 30 | (interactive) 31 | (save-excursion 32 | (move-beginning-of-line 1) 33 | (if (string= (char-to-string (char-after)) "[") 34 | (defunkt-todo-toggle-status) 35 | (insert "[ ] ")) 36 | (save-buffer))) 37 | 38 | (defun defunkt-todo-done? () 39 | "Is this line a done todo item?" 40 | (save-excursion 41 | (move-beginning-of-line 1) 42 | (search-forward "[ ]" (+ 3 (point)) t))) 43 | 44 | (defun defunkt-todo-toggle-status () 45 | "Toggle the todo state." 46 | (interactive) 47 | (save-excursion 48 | (if (defunkt-todo-done?) 49 | (defunkt-todo-set-done) 50 | (defunkt-todo-set-begun)))) 51 | 52 | (defun defunkt-todo-set-begun () 53 | "Set a todo item as begun." 54 | (defunkt-todo-set-status " ")) 55 | 56 | (defun defunkt-todo-set-done () 57 | "Set a todo item as done." 58 | (defunkt-todo-set-status "X")) 59 | 60 | (defun defunkt-todo-set-status (status) 61 | "Give the current todo item to an arbitrary status." 62 | (save-excursion 63 | (move-beginning-of-line 1) 64 | (forward-char 1) 65 | (delete-char 1) 66 | (insert status))) 67 | 68 | (defun defunkt-todo-move-item-up () 69 | "Moves the focused todo item down a line." 70 | (interactive) 71 | (save-excursion 72 | (beginning-of-line 1) 73 | (when (not (= (point-min) (point))) 74 | (let ((word (delete-and-extract-region (point) (point-at-eol)))) 75 | (delete-char 1) 76 | (forward-line -1) 77 | (insert (concat word "\n"))) 78 | (save-buffer))) 79 | (when (not (= (point-min) (point))) 80 | (forward-line -2))) 81 | 82 | (defun defunkt-todo-move-item-down () 83 | "Moves the focused todo item up a line." 84 | (interactive) 85 | (let (eof chars) 86 | (setq chars (- (point) (point-at-bol))) 87 | (save-excursion 88 | (end-of-line 1) 89 | (setq eof (= (point-max) (point))) 90 | (when (not eof) 91 | (let ((word (delete-and-extract-region (point-at-bol) (point)))) 92 | (delete-char 1) 93 | (forward-line 1) 94 | (insert (concat word "\n"))) 95 | (save-buffer))) 96 | (when (not eof) 97 | (forward-line 1) 98 | 99 | ))) -------------------------------------------------------------------------------- /vendor/ack.el: -------------------------------------------------------------------------------- 1 | ;;; ack.el --- Use ack where you might usually use grep. 2 | 3 | ;; Copyright (C) 2008 Philip Jackson 4 | 5 | ;; Author: Philip Jackson 6 | ;; Version: 0.4 7 | 8 | ;; This file is not currently part of GNU Emacs. 9 | 10 | ;; This program is free software; you can redistribute it and/or 11 | ;; modify it under the terms of the GNU General Public License as 12 | ;; published by the Free Software Foundation; either version 2, or (at 13 | ;; your option) any later version. 14 | 15 | ;; This program is distributed in the hope that it will be useful, but 16 | ;; WITHOUT ANY WARRANTY; without even the implied warranty of 17 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 18 | ;; General Public License for more details. 19 | 20 | ;; You should have received a copy of the GNU General Public License 21 | ;; along with this program ; see the file COPYING. If not, write to 22 | ;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330, 23 | ;; Boston, MA 02111-1307, USA. 24 | 25 | ;;; Commentary: 26 | 27 | ;; ack.el provides a simple compilation mode for the perl grep-a-like 28 | ;; ack (http://petdance.com/ack/). 29 | 30 | ;; If `ack-guess-type' is non-nil and `ack-mode-type-map' has a 31 | ;; reasonable value then ack.el will try and guess what you would like 32 | ;; in the --type argument for ack. 33 | 34 | ;; To install/use put ack.el in your load-path and (require 'ack) in 35 | ;; your initialisation file. You can then M-x ack and you're off. 36 | 37 | (require 'compile) 38 | 39 | (defvar ack-guess-type nil 40 | "Setting this value to `t' will have `ack' do its best to fill 41 | in the --type argument to the ack command") 42 | 43 | (defvar ack-command "ack --nocolor --nogroup " 44 | "The command to be run by the ack function.") 45 | 46 | (defvar ack-mode-type-map 47 | '(((c++-mode) . "cpp") 48 | ((c-mode) . "cc") 49 | ((css-mode) . "css") 50 | ((emacs-lisp-mode) . "elisp") 51 | ((fortran-mode) . "fortran") 52 | ((html-mode) . "html") 53 | ((xml-mode nxml-mode) . "xml") 54 | ((java-mode) . "java") 55 | ((ruby-mode) . "ruby") 56 | ((js2-mode) . "js") 57 | ((lisp-mode) . "lisp") 58 | ((perl-mode cperl-mode) . "perl")) 59 | "alist describing how to fill in the '--type=' argument to ack") 60 | 61 | (defun ack-find-type-for-mode () 62 | (catch 'found 63 | (dolist (mode-type ack-mode-type-map) 64 | (when (member major-mode (car mode-type)) 65 | (throw 'found (cdr mode-type)))))) 66 | 67 | (defun ack-build-command () 68 | (let ((type (ack-find-type-for-mode))) 69 | (concat ack-command 70 | (when (and ack-guess-type type) 71 | (concat " --type=" type)) " -- "))) 72 | 73 | (define-compilation-mode ack-mode "Ack" 74 | "Ack compilation mode." 75 | nil) 76 | 77 | ;;;###autoload 78 | (defun ack (command-args) 79 | (interactive 80 | (list (read-from-minibuffer "Run ack (like this): " 81 | (ack-build-command) 82 | nil 83 | nil 84 | 'ack-history))) 85 | (compilation-start (concat command-args " " (textmate-project-root)) 86 | 'ack-mode)) 87 | 88 | (provide 'ack) 89 | -------------------------------------------------------------------------------- /defunkt/javascript.el: -------------------------------------------------------------------------------- 1 | ; js2 2 | (autoload 'js2-mode "js2" nil t) 3 | (add-to-list 'auto-mode-alist '("\\.js$" . js2-mode)) 4 | 5 | ; js-shell 6 | (autoload 'javascript-shell "javascript-mode" nil t) 7 | 8 | (defun js2-insert-console () 9 | (interactive) 10 | (insert "console.log()") 11 | (backward-char)) 12 | 13 | (defun js2-execute-buffer () 14 | (interactive) 15 | (shell-command (concat "node " (buffer-file-name)))) 16 | 17 | (defun js2-execute-line () 18 | (interactive) 19 | (save-excursion 20 | (call-process-region (point-at-bol) 21 | (point-at-eol) 22 | "johnson" 23 | nil 24 | (get-buffer-create "*johnson-line*")) 25 | (with-current-buffer (get-buffer "*johnson-line*") 26 | (search-backward "\n\n" nil t) 27 | (replace-match "" nil t) 28 | (message (buffer-string)) 29 | (kill-buffer nil)))) 30 | 31 | (add-hook 'js2-mode-hook 32 | '(lambda () 33 | (add-hook 'before-save-hook 'delete-trailing-whitespace) 34 | (define-key js2-mode-map (kbd "A-r") 'js2-execute-buffer) 35 | (define-key js2-mode-map (kbd "A-R") 'js2-execute-line) 36 | (define-key js2-mode-map "\C-L" 'js2-insert-console) 37 | (defun js-continued-var-decl-list-p () 38 | "Return non-nil if point is inside a continued variable declaration 39 | list." 40 | (interactive) 41 | (let ((start (save-excursion (js-re-search-backward "\\" nil t)))) 42 | (and start 43 | (save-excursion (re-search-backward "\n" start t)) 44 | (not (save-excursion 45 | (js-re-search-backward 46 | ";\\|[^, \t][ \t]*\\(/[/*]\\|$\\)" start t)))))) 47 | (defun js-proper-indentation (parse-status) 48 | "Return the proper indentation for the current line." 49 | (save-excursion 50 | (back-to-indentation) 51 | (let ((ctrl-stmt-indent (js-ctrl-statement-indentation)) 52 | (same-indent-p (looking-at "[]})]\\|\\\\|\\")) 53 | (continued-expr-p (js-continued-expression-p))) 54 | (cond (ctrl-stmt-indent) 55 | ((js-continued-var-decl-list-p) 56 | (js-re-search-backward "\\" nil t) 57 | (+ (current-indentation) js2-basic-offset)) 58 | ((nth 1 parse-status) 59 | (goto-char (nth 1 parse-status)) 60 | (if (looking-at "[({[][ \t]*\\(/[/*]\\|$\\)") 61 | (progn 62 | (skip-syntax-backward " ") 63 | (when (= (char-before) ?\)) (backward-list)) 64 | (back-to-indentation) 65 | (cond (same-indent-p 66 | (current-column)) 67 | (continued-expr-p 68 | (+ (current-column) (* 2 js2-basic-offset))) 69 | (t 70 | (+ (current-column) js2-basic-offset)))) 71 | (unless same-indent-p 72 | (forward-char) 73 | (skip-chars-forward " \t")) 74 | (current-column))) 75 | (continued-expr-p js2-basic-offset) 76 | (t 0))))))) -------------------------------------------------------------------------------- /vendor/http-twiddle.el: -------------------------------------------------------------------------------- 1 | ;;; http-twiddle.el -- send & twiddle & resend HTTP requests 2 | ;; 3 | ;; Version 1.0 written by Luke Gorrie in February 2006 4 | ;; This program belongs to the public domain. 5 | ;; 6 | ;; This is a program for testing hand-written HTTP requests. You write 7 | ;; your request in an Emacs buffer (using http-twiddle-mode) and then 8 | ;; press `C-c C-c' each time you want to try sending it to the server. 9 | ;; This way you can interactively debug the requests. To change port or 10 | ;; destination do `C-u C-c C-c'. 11 | ;; 12 | ;; The program is particularly intended for the POST-"500 internal 13 | ;; server error"-edit-POST loop of integration with SOAP programs. 14 | ;; 15 | ;; The mode is activated by `M-x http-twiddle-mode' or automatically 16 | ;; when opening a filename ending with .http-twiddle. 17 | ;; 18 | ;; The request can either be written from scratch or you can paste it 19 | ;; from a snoop/tcpdump and then twiddle from there. 20 | ;; 21 | ;; See the documentation for the `http-twiddle-mode' and 22 | ;; `http-twiddle-mode-send' functions below for more details and try 23 | ;; `M-x http-twiddle-mode-demo' for a simple get-started example. 24 | ;; 25 | ;; Tested with GNU Emacs 21.4.1 and not tested/ported on XEmacs yet. 26 | 27 | ;;; Example buffer: 28 | 29 | ;; POST / HTTP/1.0 30 | ;; Connection: close 31 | ;; Content-Length: $Content-Length 32 | ;; 33 | ;; The request body goes here 34 | 35 | (require 'font-lock) ; faces 36 | 37 | (eval-when-compile 38 | (unless (fboundp 'define-minor-mode) 39 | (require 'easy-mmode) 40 | (defalias 'define-minor-mode 'easy-mmode-define-minor-mode)) 41 | (require 'cl)) 42 | 43 | (define-minor-mode http-twiddle-mode 44 | "Major mode for twiddling around with HTTP requests and sending them. 45 | Use `http-twiddle-mode-send' (\\[http-twiddle-mode-send]) to send the request." 46 | nil 47 | " http-twiddle" 48 | '(("\C-c\C-c" . http-twiddle-mode-send))) 49 | 50 | (defvar http-twiddle-show-request t 51 | "*Show the request in the transcript.") 52 | 53 | (add-to-list 'auto-mode-alist '("\\.http-twiddle$" . http-twiddle-mode)) 54 | 55 | (defvar http-twiddle-endpoint nil 56 | "Cache of the (HOST PORT) to send the request to.") 57 | 58 | (defvar http-twiddle-process nil 59 | "Socket connected to the webserver.") 60 | 61 | (defvar http-twiddle-port-history '() 62 | "History of port arguments entered in the minibuffer. 63 | \(To make XEmacs happy.)") 64 | 65 | (defvar http-twiddle-host-history '() 66 | "History of port arguments entered in the minibuffer. 67 | \(To make XEmacs happy.)") 68 | 69 | (defun http-twiddle-mode-send (host port) 70 | "Send the current buffer to the server. 71 | Linebreaks are automatically converted to CRLF (\\r\\n) format and any 72 | occurences of \"$Content-Length\" are replaced with the actual content 73 | length." 74 | (interactive (http-twiddle-read-endpoint)) 75 | ;; close any old connection 76 | (when http-twiddle-process 77 | (kill-buffer (process-buffer http-twiddle-process))) 78 | (let ((content (buffer-string))) 79 | (with-temp-buffer 80 | (insert content) 81 | (http-twiddle-convert-cr-to-crlf) 82 | (http-twiddle-expand-content-length) 83 | (let ((request (buffer-string))) 84 | (setq http-twiddle-process 85 | (open-network-stream "http-twiddle" "*HTTP Twiddle*" host port)) 86 | (set-process-filter http-twiddle-process 'http-twiddle-process-filter) 87 | (set-process-sentinel http-twiddle-process 'http-twiddle-process-sentinel) 88 | (process-send-string http-twiddle-process request) 89 | (save-selected-window 90 | (pop-to-buffer (process-buffer http-twiddle-process)) 91 | (when http-twiddle-show-request 92 | (insert request) 93 | (set-window-start (selected-window) (point)) 94 | (add-text-properties (point-min) (point-max) 95 | '(face font-lock-comment-face))) 96 | (set-mark (point))))))) 97 | 98 | (defun http-twiddle-read-endpoint () 99 | "Return the endpoint (HOST PORT) to send the request to." 100 | (if (and http-twiddle-endpoint (null current-prefix-arg)) 101 | http-twiddle-endpoint 102 | (setq http-twiddle-endpoint 103 | (list (read-string "Host: (default localhost) " 104 | nil 'http-twiddle-host-history "localhost") 105 | (let ((input (read-from-minibuffer "Port: " nil nil t 'http-twiddle-port-history))) 106 | (if (integerp input) 107 | input 108 | (error "Not an integer: %S" input))))))) 109 | 110 | (defun http-twiddle-convert-cr-to-crlf () 111 | "Convert \\n linebreaks to \\r\\n in the whole buffer." 112 | (save-excursion 113 | (goto-char (point-min)) 114 | (while (re-search-forward "[^\r]\n" nil t) 115 | (backward-char) 116 | (insert "\r")))) 117 | 118 | (defun http-twiddle-expand-content-length () 119 | "Replace any occurences of $Content-Length with the actual Content-Length." 120 | (save-excursion 121 | (goto-char (point-min)) 122 | (let ((content-length 123 | (save-excursion (when (search-forward "\r\n\r\n" nil t) 124 | (- (point-max) (point)))))) 125 | (unless (null content-length) 126 | (let ((case-fold-search t)) 127 | (while (search-forward "$content-length" nil t) 128 | (replace-match (format "%d" content-length) nil t))))))) 129 | 130 | (defun http-twiddle-process-filter (process string) 131 | "Process data from the socket by inserting it at the end of the buffer." 132 | (with-current-buffer (process-buffer process) 133 | (goto-char (point-max)) 134 | (insert string))) 135 | 136 | (defun http-twiddle-process-sentinel (process what) 137 | (with-current-buffer (process-buffer process) 138 | (goto-char (point-max)) 139 | (let ((start (point))) 140 | (insert "Connection closed\n") 141 | (add-text-properties start (point) '(face font-lock-string-face))))) 142 | 143 | (defun http-twiddle-mode-demo () 144 | (interactive) 145 | (pop-to-buffer (get-buffer-create "*http-twiddle demo*")) 146 | (http-twiddle-mode 1) 147 | (erase-buffer) 148 | (insert "POST / HTTP/1.0\nContent-Length: $Content-Length\nConnection: close\n\nThis is the POST body.\n") 149 | (message "Now press `C-c C-c' and enter a webserver address (e.g. google.com port 80).")) 150 | 151 | (provide 'http-twiddle) 152 | 153 | -------------------------------------------------------------------------------- /vendor/ruby-hacks.el: -------------------------------------------------------------------------------- 1 | ;;; ruby-hacks.el --- provide features for ruby-mode 2 | 3 | ;; Copyright (C) 2006 Dmitry Galinsky 4 | ;; Copyright (C) 2008 Chris Wanstrath 5 | 6 | ;; Authors: Dmitry Galinsky 7 | ;; Chris Wanstrath 8 | 9 | ;; Keywords: ruby rails languages oop 10 | 11 | ;;; License 12 | 13 | ;; This program is free software; you can redistribute it and/or 14 | ;; modify it under the terms of the GNU General Public License 15 | ;; as published by the Free Software Foundation; either version 2 16 | ;; of the License, or (at your option) any later version. 17 | 18 | ;; This program is distributed in the hope that it will be useful, 19 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of 20 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21 | ;; GNU General Public License for more details. 22 | 23 | ;; You should have received a copy of the GNU General Public License 24 | ;; along with this program; if not, write to the Free Software 25 | ;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 26 | 27 | ;;; Code: 28 | 29 | ;; setup align for ruby-mode 30 | (require 'align) 31 | 32 | (defconst align-ruby-modes '(ruby-mode) 33 | "align-perl-modes is a variable defined in `align.el'.") 34 | 35 | (defconst ruby-align-rules-list 36 | '((ruby-comma-delimiter 37 | (regexp . ",\\(\\s-*\\)[^/ \t\n]") 38 | (modes . align-ruby-modes) 39 | (repeat . t)) 40 | (ruby-string-after-func 41 | (regexp . "^\\s-*[a-zA-Z0-9.:?_]+\\(\\s-+\\)['\"]\\w+['\"]") 42 | (modes . align-ruby-modes) 43 | (repeat . t)) 44 | (ruby-symbol-after-func 45 | (regexp . "^\\s-*[a-zA-Z0-9.:?_]+\\(\\s-+\\):\\w+") 46 | (modes . align-ruby-modes))) 47 | "Alignment rules specific to the ruby mode. 48 | See the variable `align-rules-list' for more details.") 49 | 50 | (add-to-list 'align-perl-modes 'ruby-mode) 51 | (add-to-list 'align-dq-string-modes 'ruby-mode) 52 | (add-to-list 'align-sq-string-modes 'ruby-mode) 53 | (add-to-list 'align-open-comment-modes 'ruby-mode) 54 | (dolist (it ruby-align-rules-list) 55 | (add-to-list 'align-rules-list it)) 56 | 57 | ;; hideshow ruby support 58 | 59 | (defun display-code-line-counts (ov) 60 | (when (eq 'code (overlay-get ov 'hs)) 61 | (overlay-put ov 'face 'font-lock-comment-face) 62 | (overlay-put ov 'display 63 | (format " ... %d lines" 64 | (count-lines (overlay-start ov) 65 | (overlay-end ov)))))) 66 | 67 | (eval-after-load "hideshow" 68 | (unless 'hs-set-up-overlay 69 | (setq hs-set-up-overlay 'display-code-line-counts))) 70 | 71 | (add-hook 'hs-minor-mode-hook 72 | (lambda () 73 | (unless hs-set-up-overlay 74 | (setq hs-set-up-overlay 'display-code-line-counts)))) 75 | 76 | (defun ruby-hs-minor-mode (&optional arg) 77 | (interactive) 78 | (require 'hideshow) 79 | (unless (assoc 'ruby-mode hs-special-modes-alist) 80 | (setq 81 | hs-special-modes-alist 82 | (cons (list 'ruby-mode 83 | "\\(def\\|do\\)" 84 | "end" 85 | "#" 86 | (lambda (&rest args) (ruby-end-of-block)) 87 | ;(lambda (&rest args) (ruby-beginning-of-defun)) 88 | ) 89 | hs-special-modes-alist))) 90 | (hs-minor-mode arg)) 91 | 92 | ;; other stuff 93 | 94 | (defun ruby-newline-and-indent () 95 | (interactive) 96 | (newline) 97 | (ruby-indent-command)) 98 | 99 | (defun ruby-toggle-string<>simbol () 100 | "Easy to switch between strings and symbols." 101 | (interactive) 102 | (let ((initial-pos (point))) 103 | (save-excursion 104 | (when (looking-at "[\"']") ;; skip beggining quote 105 | (goto-char (+ (point) 1)) 106 | (unless (looking-at "\\w") 107 | (goto-char (- (point) 1)))) 108 | (let* ((point (point)) 109 | (start (skip-syntax-backward "w")) 110 | (end (skip-syntax-forward "w")) 111 | (end (+ point start end)) 112 | (start (+ point start)) 113 | (start-quote (- start 1)) 114 | (end-quote (+ end 1)) 115 | (quoted-str (buffer-substring-no-properties start-quote end-quote)) 116 | (symbol-str (buffer-substring-no-properties start end))) 117 | (cond 118 | ((or (string-match "^\"\\w+\"$" quoted-str) 119 | (string-match "^\'\\w+\'$" quoted-str)) 120 | (setq quoted-str (substring quoted-str 1 (- (length quoted-str) 1))) 121 | (kill-region start-quote end-quote) 122 | (goto-char start-quote) 123 | (insert (concat ":" quoted-str))) 124 | ((string-match "^\:\\w+$" symbol-str) 125 | (setq symbol-str (substring symbol-str 1)) 126 | (kill-region start end) 127 | (goto-char start) 128 | (insert (format "'%s'" symbol-str)))))) 129 | (goto-char initial-pos))) 130 | 131 | (require 'inf-ruby) 132 | 133 | (defun run-ruby-in-buffer (buf script &optional params) 134 | "Run CMD as a ruby process in BUF if BUF does not exist." 135 | (let ((abuf (concat "*" buf "*"))) 136 | (when (not (comint-check-proc abuf)) 137 | (set-buffer (make-comint buf rails-ruby-command nil script params))) 138 | (inferior-ruby-mode) 139 | (make-local-variable 'inferior-ruby-first-prompt-pattern) 140 | (make-local-variable 'inferior-ruby-prompt-pattern) 141 | (setq inferior-ruby-first-prompt-pattern "^>> " 142 | inferior-ruby-prompt-pattern "^>> ") 143 | (pop-to-buffer abuf))) 144 | 145 | (defun complete-ruby-method (prefix &optional maxnum) 146 | (if (capital-word-p prefix) 147 | (let* ((cmd "x = []; ObjectSpace.each_object(Class){|i| x << i.to_s}; x.map{|i| i.match(/^%s/) ? i.gsub(/^%s/, '') : nil }.compact.sort{|x,y| x.size <=> y.size}") 148 | (cmd (if maxnum (concat cmd (format "[0...%s]" maxnum)) cmd))) 149 | (el4r-ruby-eval (format cmd prefix prefix))) 150 | (save-excursion 151 | (goto-char (- (point) (+ 1 (length prefix)))) 152 | (when (and (looking-at "\\.") 153 | (capital-word-p (word-at-point)) 154 | (el4r-ruby-eval (format "::%s rescue nil" (word-at-point)))) 155 | (let* ((cmd "%s.public_methods.map{|i| i.match(/^%s/) ? i.gsub(/^%s/, '') : nil }.compact.sort{|x,y| x.size <=> y.size}") 156 | (cmd (if maxnum (concat cmd (format "[0...%s]" maxnum)) cmd))) 157 | (el4r-ruby-eval (format cmd (word-at-point) prefix prefix))))))) 158 | 159 | 160 | (provide 'ruby-hacks) -------------------------------------------------------------------------------- /defunkt/defuns.el: -------------------------------------------------------------------------------- 1 | (defun air () 2 | (interactive) 3 | (replace-string "240" "180") 4 | (save-buffer)) 5 | 6 | (defun big () 7 | (interactive) 8 | (replace-string "180" "240") 9 | (save-buffer)) 10 | 11 | (defun insert-soft-tab () 12 | (interactive) 13 | (insert " ")) 14 | 15 | (defun defunkt-indent () 16 | (interactive) 17 | (insert " ")) 18 | 19 | (defun mustache () 20 | (interactive) 21 | (mustache-mode) 22 | (setq truncate-lines t)) 23 | 24 | (defun email () 25 | (interactive) 26 | (markdown-mode) 27 | (turn-on-word-wrap)) 28 | 29 | (defun defunkt-zap-to-char (arg char) 30 | "Kill up to but excluding ARG'th occurrence of CHAR. 31 | Case is ignored if `case-fold-search' is non-nil in the current buffer. 32 | Goes backward if ARG is negative; error if CHAR not found. 33 | This emulates Vim's `dt` behavior, which rocks." 34 | (interactive "p\ncZap to char: ") 35 | (if (char-table-p translation-table-for-input) 36 | (setq char (or (aref translation-table-for-input char) char))) 37 | (kill-region (point) 38 | (progn 39 | (search-forward (char-to-string char) nil nil arg) 40 | (- (point) 1))) 41 | (backward-char 1)) 42 | 43 | (defun word-count () 44 | "Count words in buffer" 45 | (interactive) 46 | (shell-command-on-region (point-min) (point-max) "wc -w")) 47 | 48 | (defun defunkt-ido-find-config () 49 | (interactive) 50 | (find-file 51 | (concat "~/.emacs.d/defunkt/" 52 | (ido-completing-read "Config file: " 53 | (directory-files "~/.emacs.d/defunkt/" 54 | nil 55 | "^[^.]"))))) 56 | 57 | (defun defunkt-delete-till-end-of-buffer () 58 | "Deletes all text from mark until `end-of-buffer'." 59 | (interactive) 60 | (save-excursion 61 | (let ((beg (point))) 62 | (end-of-buffer) 63 | (delete-region beg (point))))) 64 | 65 | (defun defunkt-ido-find-project () 66 | (interactive) 67 | (find-file 68 | (concat "~/Code/" (ido-completing-read "Project: " 69 | (directory-files "~/Code/" nil "^[^.]"))))) 70 | 71 | (defun defunkt-goto-config () 72 | (interactive) 73 | (find-file "~/.emacs.d/defunkt.el")) 74 | 75 | ;; fix kill-word 76 | (defun defunkt-kill-word (arg) 77 | "Special version of kill-word which swallows spaces separate from words" 78 | (interactive "p") 79 | 80 | (let ((whitespace-regexp "\\s-+")) 81 | (kill-region (point) 82 | (cond 83 | ((looking-at whitespace-regexp) (re-search-forward whitespace-regexp) (point)) 84 | ((looking-at "\n") (kill-line) (defunkt-kill-word arg)) 85 | (t (forward-word arg) (point)))))) 86 | 87 | (defun defunkt-backward-kill-word (arg) 88 | "Special version of backward-kill-word which swallows spaces separate from words" 89 | (interactive "p") 90 | (if (looking-back "\\s-+") 91 | (kill-region (point) (progn (re-search-backward "\\S-") (forward-char 1) (point))) 92 | (backward-kill-word arg))) 93 | 94 | ; set the mode based on the shebang; 95 | ; TODO: this sometimes breaks 96 | (defun defunkt-shebang-to-mode () 97 | (interactive) 98 | (let* 99 | ((bang (buffer-substring (point-min) (prog2 (end-of-line) (point) (move-beginning-of-line 1)))) 100 | (mode (progn 101 | (string-match "^#!.+[ /]\\(\\w+\\)$" bang) 102 | (match-string 1 bang))) 103 | (mode-fn (intern (concat mode "-mode")))) 104 | (when (functionp mode-fn) 105 | (funcall mode-fn)))) 106 | ;(add-hook 'find-file-hook 'defunkt-shebang-to-mode) 107 | 108 | ; duplicate the current line 109 | (defun defunkt-duplicate-line () 110 | (interactive) 111 | (beginning-of-line) 112 | (copy-region-as-kill (point) (progn (end-of-line) (point))) 113 | (textmate-next-line) 114 | (yank) 115 | (beginning-of-line) 116 | (indent-according-to-mode)) 117 | 118 | ; for loading libraries in from the vendor directory 119 | (defun vendor (library) 120 | (let* ((file (symbol-name library)) 121 | (normal (concat "~/.emacs.d/vendor/" file)) 122 | (suffix (concat normal ".el")) 123 | (defunkt (concat "~/.emacs.d/defunkt/" file))) 124 | (cond 125 | ((file-directory-p normal) (add-to-list 'load-path normal) (require library)) 126 | ((file-directory-p suffix) (add-to-list 'load-path suffix) (require library)) 127 | ((file-exists-p suffix) (require library))) 128 | (when (file-exists-p (concat defunkt ".el")) 129 | (load defunkt)))) 130 | 131 | (defun defunkt-backward-kill-line () 132 | (interactive) 133 | (kill-line 0)) 134 | 135 | (require 'thingatpt) 136 | (defun defunkt-change-num-at-point (fn) 137 | (let* ((num (string-to-number (thing-at-point 'word))) 138 | (bounds (bounds-of-thing-at-point 'word))) 139 | (save-excursion 140 | (goto-char (car bounds)) 141 | (defunkt-kill-word 1) 142 | (insert (number-to-string (funcall fn num 1)))))) 143 | 144 | (defun defunkt-inc-num-at-point () 145 | (interactive) 146 | (defunkt-change-num-at-point '+)) 147 | 148 | (defun defunkt-dec-num-at-point () 149 | (interactive) 150 | (defunkt-change-num-at-point '-)) 151 | 152 | (defun url-fetch-into-buffer (url) 153 | (interactive "sURL:") 154 | (insert (concat "\n\n" ";; " url "\n")) 155 | (insert (url-fetch-to-string url))) 156 | 157 | (defun url-fetch-to-string (url) 158 | (with-current-buffer (url-retrieve-synchronously url) 159 | (beginning-of-buffer) 160 | (search-forward-regexp "\n\n") 161 | (delete-region (point-min) (point)) 162 | (buffer-string))) 163 | 164 | (defun gist-buffer-confirm (&optional private) 165 | (interactive "P") 166 | (when (yes-or-no-p "Are you sure you want to Gist this buffer? ") 167 | (gist-region-or-buffer private))) 168 | 169 | (defun defunkt-clean-slate () 170 | "Kills all buffers except *scratch*" 171 | (interactive) 172 | (let ((buffers (buffer-list)) (safe '("*scratch*"))) 173 | (while buffers 174 | (when (not (member (car buffers) safe)) 175 | (kill-buffer (car buffers)) 176 | (setq buffers (cdr buffers)))))) 177 | 178 | (defun defunkt/c-electric-brace (arg) 179 | "Inserts a closing curly, too." 180 | (interactive "*P") 181 | (c-electric-brace arg) 182 | (save-excursion 183 | (insert "\n") 184 | (insert "}") 185 | (indent-according-to-mode))) 186 | 187 | ;; from http://platypope.org/blog/2007/8/5/a-compendium-of-awesomeness 188 | ;; I-search with initial contents 189 | (defvar isearch-initial-string nil) 190 | 191 | (defun isearch-set-initial-string () 192 | (remove-hook 'isearch-mode-hook 'isearch-set-initial-string) 193 | (setq isearch-string isearch-initial-string) 194 | (isearch-search-and-update)) 195 | 196 | (defun isearch-forward-at-point (&optional regexp-p no-recursive-edit) 197 | "Interactive search forward for the symbol at point." 198 | (interactive "P\np") 199 | (if regexp-p (isearch-forward regexp-p no-recursive-edit) 200 | (let* ((end (progn (skip-syntax-forward "w_") (point))) 201 | (begin (progn (skip-syntax-backward "w_") (point)))) 202 | (if (eq begin end) 203 | (isearch-forward regexp-p no-recursive-edit) 204 | (setq isearch-initial-string (buffer-substring begin end)) 205 | (add-hook 'isearch-mode-hook 'isearch-set-initial-string) 206 | (isearch-forward regexp-p no-recursive-edit))))) 207 | -------------------------------------------------------------------------------- /vendor/textile-mode.el: -------------------------------------------------------------------------------- 1 | ;;; textile-mode.el --- Textile markup editing major mode 2 | 3 | ;; Copyright (C) 2006 Free Software Foundation, Inc. 4 | 5 | ;; Author: Julien Barnier 6 | ;; $Id: textile-mode.el 6 2006-03-30 22:37:08Z juba $ 7 | 8 | ;; This file is free software; you can redistribute it and/or modify 9 | ;; it under the terms of the GNU General Public License as published by 10 | ;; the Free Software Foundation; either version 2, or (at your option) 11 | ;; any later version. 12 | 13 | ;; This file is distributed in the hope that it will be useful, 14 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | ;; GNU General Public License for more details. 17 | 18 | ;; You should have received a copy of the GNU General Public License 19 | ;; along with GNU Emacs; see the file COPYING. If not, write to 20 | ;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330, 21 | ;; Boston, MA 02111-1307, USA. 22 | 23 | ;;; Commentary: 24 | 25 | ;; 26 | 27 | 28 | ;; Known bugs or limitations: 29 | 30 | ;; - if several {style}, [lang] or (class) attributes are given for 31 | ;; the same block, only the first one of each type will be 32 | ;; highlighted. 33 | ;; 34 | ;; - some complex imbrications of inline markup and attributes are 35 | ;; not well-rendered (for example, *strong *{something}notstrong*) 36 | ;; 37 | 38 | 39 | 40 | ;;; Code: 41 | 42 | 43 | 44 | (defvar textile-mode-map 45 | (let ((map (make-sparse-keymap))) 46 | (define-key map [foo] 'textile-do-foo) 47 | map) 48 | "Keymap for `textile-mode'.") 49 | 50 | 51 | (defun textile-re-concat (l) 52 | "Concatenate the elements of a list with a \\| separator and 53 | non-matching parentheses" 54 | (concat 55 | "\\(?:" 56 | (mapconcat 'identity l "\\|") 57 | "\\)")) 58 | 59 | 60 | (setq textile-attributes 61 | '("{[^}]*}" "([^)]*)" "\\[[^]]*\\]")) 62 | 63 | (setq textile-blocks 64 | '("^h1" "^h2" "^h3" "^h4" "^h5" "^h6" "^p" "^bq" "^fn[0-9]+" "^#+ " "^\\*+ " "^table")) 65 | 66 | (setq textile-inline-markup 67 | '("\\*" "\\*\\*" "_" "__" "\\?\\?" "@" "-" "\\+" "^" "~" "%")) 68 | 69 | (setq textile-alignments 70 | '( "<>" "<" ">" "=" "(+" ")+")) 71 | 72 | (setq textile-table-alignments 73 | '( "<>" "<" ">" "=" "_" "\\^" "~" "\\\\[0-9]+" "/[0-9]+")) 74 | 75 | ; from gnus-button-url-regexp 76 | (setq textile-url-regexp "\\b\\(\\(www\\.\\|\\(s?https?\\|ftp\\|file\\|gopher\\|nntp\\|news\\|telnet\\|wais\\|mailto\\|info\\):\\)\\(//[-a-z0-9_.]+:[0-9]*\\)?[-a-z0-9_=!?#$@~%&*+\\/:;.,[:word:]]+[-a-z0-9_=#$@~%&*+\\/[:word:]]\\)") 77 | 78 | 79 | (defun textile-block-matcher (bloc) 80 | "Return the matcher regexp for a block element" 81 | (concat 82 | "^" 83 | bloc 84 | (textile-re-concat textile-alignments) "?" 85 | (textile-re-concat textile-attributes) "*" 86 | "\\. " 87 | "\\(\\(?:.\\|\n\\)*?\\)\n\n")) 88 | 89 | (defun textile-attribute-matcher (attr-start attr-end) 90 | "Return the matcher regexp for an attribute" 91 | (concat 92 | (textile-re-concat (append textile-blocks textile-inline-markup)) 93 | (textile-re-concat textile-alignments) "*" 94 | (textile-re-concat textile-attributes) "*" 95 | "\\(" attr-start "[^" 96 | (if (string-equal attr-end "\\]") "]" attr-end) 97 | "]*" attr-end "\\)")) 98 | 99 | (defun textile-inline-markup-matcher (markup) 100 | "Return the matcher regexp for an inline markup" 101 | (concat 102 | "\\W\\(" 103 | markup 104 | "\\(?:\\w\\|\\w.*?\\w\\|[[{(].*?\\w\\)" 105 | markup 106 | "\\)\\W")) 107 | 108 | (defun textile-list-bullet-matcher (bullet) 109 | "Return the matcher regexp for a list bullet" 110 | (concat 111 | "^\\(" bullet "\\)" 112 | (textile-re-concat textile-alignments) "*" 113 | (textile-re-concat textile-attributes) "*")) 114 | 115 | (defun textile-alignments-matcher () 116 | "Return the matcher regexp for an alignments or indentation" 117 | (concat 118 | "\\(?:" (textile-re-concat textile-blocks) "\\|" "!" "\\)" 119 | "\\(" (textile-re-concat textile-alignments) "+" "\\)")) 120 | 121 | (defun textile-table-matcher () 122 | "Return the matcher regexp for a table row or header" 123 | (concat 124 | "\\(?:" 125 | "^table" (textile-re-concat textile-table-alignments) "*" (textile-re-concat textile-attributes) "*" "\\. *$" 126 | "\\|" 127 | "^" (textile-re-concat textile-table-alignments) "*" (textile-re-concat textile-attributes) "*" "\\(?:\\. *|\\)" 128 | "\\|" 129 | "|" (textile-re-concat textile-table-alignments) "*" (textile-re-concat textile-attributes) "*" "\\(?:\\. \\)?" 130 | "\\|" 131 | "| *$" 132 | "\\)")) 133 | 134 | (defun textile-link-matcher () 135 | "Return the matcher regexp for a link" 136 | (concat 137 | "\\(?:" 138 | "\\(?:" "\".*?\"" "\\|" "\\[.*?\\]" "\\)?" 139 | textile-url-regexp 140 | "\\|" 141 | "\".*?\":[^ \n\t]+" 142 | "\\)")) 143 | 144 | (defun textile-image-matcher () 145 | "Return the matcher regexp for an image link" 146 | (concat 147 | "!" 148 | (textile-re-concat textile-alignments) "*" 149 | "/?\\w[^ \n\t]*?\\(?: *(.*?)\\|\\w\\)" 150 | "!:?")) 151 | 152 | (defun textile-acronym-matcher () 153 | "Return the matcher regexp for an acronym" 154 | (concat 155 | "\\w+" "(.*?)")) 156 | 157 | (defvar textile-font-lock-keywords 158 | (list 159 | ;; headers 160 | `(,(textile-block-matcher "h1") 1 'textile-h1-face t t) 161 | `(,(textile-block-matcher "h2") 1 'textile-h2-face t t) 162 | `(,(textile-block-matcher "h3") 1 'textile-h3-face t t) 163 | `(,(textile-block-matcher "h4") 1 'textile-h4-face t t) 164 | `(,(textile-block-matcher "h5") 1 'textile-h5-face t t) 165 | `(,(textile-block-matcher "h6") 1 'textile-h6-face t t) 166 | ;; blockquotes 167 | `(,(textile-block-matcher "bq") 1 'textile-blockquote-face t t) 168 | ;; footnotes 169 | `(,(textile-block-matcher "fn[0-9]+") 1 'textile-footnote-face t t) 170 | ;; footnote marks 171 | '("\\w\\([[0-9]+]\\)" 1 'textile-footnotemark-face prepend t) 172 | ;; acronyms 173 | `(,(textile-acronym-matcher) 0 'textile-acronym-face t t) 174 | 175 | ;; emphasis 176 | `(,(textile-inline-markup-matcher "__") 1 'textile-emph-face prepend t) 177 | `(,(textile-inline-markup-matcher "_") 1 'textile-emph-face prepend t) 178 | '("\\(.\\|\n\\)*?" 0 'textile-emph-face prepend t) 179 | ;; strength 180 | `(,(textile-inline-markup-matcher "\\*\\*") 1 'textile-strong-face prepend t) 181 | `(,(textile-inline-markup-matcher "\\*") 1 'textile-strong-face prepend t) 182 | '("\\(.\\|\n\\)*?" 0 'textile-strong-face prepend t) 183 | ;; citation 184 | `(,(textile-inline-markup-matcher "\\?\\?") 1 'textile-citation-face prepend t) 185 | ;; code 186 | `(,(textile-inline-markup-matcher "@") 1 'textile-code-face prepend t) 187 | ;; deletion 188 | `(,(textile-inline-markup-matcher "-") 1 'textile-deleted-face prepend t) 189 | ;; insertion 190 | `(,(textile-inline-markup-matcher "\\+") 1 'textile-inserted-face prepend t) 191 | ;; superscript 192 | `(,(textile-inline-markup-matcher "\\^") 1 'textile-superscript-face prepend t) 193 | ;; subscript 194 | `(,(textile-inline-markup-matcher "~") 1 'textile-subscript-face prepend t) 195 | ;; span 196 | `(,(textile-inline-markup-matcher "%") 1 'textile-span-face prepend t) 197 | 198 | ;; image link 199 | `(,(textile-image-matcher) 0 'textile-image-face t t) 200 | 201 | ;; ordered list bullet 202 | `(,(textile-list-bullet-matcher "#+") 1 'textile-ol-bullet-face) 203 | ;; unordered list bullet 204 | `(,(textile-list-bullet-matcher "\\*+") 1 'textile-ul-bullet-face) 205 | 206 | ;; style 207 | `(,(textile-attribute-matcher "{" "}") 1 'textile-style-face t t) 208 | ;; class 209 | `(,(textile-attribute-matcher "(" ")") 1 'textile-class-face t t) 210 | ;; lang 211 | `(,(textile-attribute-matcher "\\[" "\\]") 1 'textile-lang-face t t) 212 | 213 | ;; alignments and indentation 214 | `(,(textile-alignments-matcher) 1 'textile-alignments-face t t) 215 | 216 | ;; tables 217 | `(,(textile-table-matcher) 0 'textile-table-face t t) 218 | 219 | ;; links 220 | `(,(textile-link-matcher) 0 'textile-link-face t t) 221 | 222 | ;;
 blocks
223 |        '("
\\(.\\|\n\\)*?
" 0 'textile-pre-face t t) 224 | ;; blocks 225 | '("\\(.\\|\n\\)*?" 0 'textile-code-face t t)) 226 | "Keywords/Regexp for fontlocking of textile-mode") 227 | 228 | 229 | ;; (defvar textile-imenu-generic-expression 230 | ;; ...) 231 | 232 | ;; (defvar textile-outline-regexp 233 | ;; ...) 234 | 235 | 236 | (define-derived-mode textile-mode text-mode "Textile" 237 | "A major mode for editing textile files." 238 | (set (make-local-variable 'font-lock-defaults) '(textile-font-lock-keywords t)) 239 | (set (make-local-variable 'font-lock-multiline) 'undecided)) 240 | 241 | 242 | 243 | 244 | ;; FACES 245 | 246 | (defgroup textile-faces nil 247 | "Faces used by textile-mode for syntax highlighting" 248 | :group 'faces) 249 | 250 | (defface textile-h1-face 251 | '((t (:height 2.0 :weight bold))) 252 | "Face used to highlight h1 headers." 253 | :group 'textile-faces) 254 | 255 | (defface textile-h2-face 256 | '((t (:height 1.75 :weight bold))) 257 | "Face used to highlight h2 headers." 258 | :group 'textile-faces) 259 | 260 | (defface textile-h3-face 261 | '((t (:height 1.6 :weight bold))) 262 | "Face used to highlight h3 headers." 263 | :group 'textile-faces) 264 | 265 | (defface textile-h4-face 266 | '((t (:height 1.35 :weight bold))) 267 | "Face used to highlight h4 headers." 268 | :group 'textile-faces) 269 | 270 | (defface textile-h5-face 271 | '((t (:height 1.2 :weight bold))) 272 | "Face used to highlight h5 headers." 273 | :group 'textile-faces) 274 | 275 | (defface textile-h6-face 276 | '((t (:height 1.0 :weight bold))) 277 | "Face used to highlight h6 headers." 278 | :group 'textile-faces) 279 | 280 | (defface textile-blockquote-face 281 | '((t (:foreground "ivory4"))) 282 | "Face used to highlight bq blocks." 283 | :group 'textile-faces) 284 | 285 | (defface textile-footnote-face 286 | '((t (:foreground "orange red"))) 287 | "Face used to highlight footnote blocks." 288 | :group 'textile-faces) 289 | 290 | (defface textile-footnotemark-face 291 | '((t (:foreground "orange red"))) 292 | "Face used to highlight footnote marks." 293 | :group 'textile-faces) 294 | 295 | (defface textile-style-face 296 | '((t (:foreground "sandy brown"))) 297 | "Face used to highlight style parameters." 298 | :group 'textile-faces) 299 | 300 | (defface textile-class-face 301 | '((t (:foreground "yellow green"))) 302 | "Face used to highlight class and id parameters." 303 | :group 'textile-faces) 304 | 305 | (defface textile-lang-face 306 | '((t (:foreground "sky blue"))) 307 | "Face used to highlight lang parameters." 308 | :group 'textile-faces) 309 | 310 | (defface textile-emph-face 311 | '((t (:slant italic))) 312 | "Face used to highlight emphasized words." 313 | :group 'textile-faces) 314 | 315 | (defface textile-strong-face 316 | '((t (:weight bold))) 317 | "Face used to highlight strong words." 318 | :group 'textile-faces) 319 | 320 | (defface textile-code-face 321 | '((t (:foreground "ivory3"))) 322 | "Face used to highlight inline code." 323 | :group 'textile-faces) 324 | 325 | (defface textile-citation-face 326 | '((t (:slant italic))) 327 | "Face used to highlight citations." 328 | :group 'textile-faces) 329 | 330 | (defface textile-deleted-face 331 | '((t (:strike-through t))) 332 | "Face used to highlight deleted words." 333 | :group 'textile-faces) 334 | 335 | (defface textile-inserted-face 336 | '((t (:underline t))) 337 | "Face used to highlight inserted words." 338 | :group 'textile-faces) 339 | 340 | (defface textile-superscript-face 341 | '((t (:height 1.1))) 342 | "Face used to highlight superscript words." 343 | :group 'textile-faces) 344 | 345 | (defface textile-subscript-face 346 | '((t (:height 0.8))) 347 | "Face used to highlight subscript words." 348 | :group 'textile-faces) 349 | 350 | (defface textile-span-face 351 | '((t (:foreground "pink"))) 352 | "Face used to highlight span words." 353 | :group 'textile-faces) 354 | 355 | (defface textile-alignments-face 356 | '((t (:foreground "cyan"))) 357 | "Face used to highlight alignments." 358 | :group 'textile-faces) 359 | 360 | (defface textile-ol-bullet-face 361 | '((t (:foreground "red"))) 362 | "Face used to highlight ordered lists bullets." 363 | :group 'textile-faces) 364 | 365 | (defface textile-ul-bullet-face 366 | '((t (:foreground "blue"))) 367 | "Face used to highlight unordered list bullets." 368 | :group 'textile-faces) 369 | 370 | (defface textile-pre-face 371 | '((t (:foreground "green"))) 372 | "Face used to highlight
 blocks."
373 |   :group 'textile-faces)
374 | 
375 | (defface textile-code-face
376 |   '((t (:foreground "yellow")))
377 |   "Face used to highlight  blocks."
378 |   :group 'textile-faces)
379 | 
380 | (defface textile-table-face
381 |   '((t (:foreground "red")))
382 |   "Face used to highlight tables."
383 |   :group 'textile-faces)
384 | 
385 | (defface textile-link-face
386 |   '((t (:foreground "blue")))
387 |   "Face used to highlight links."
388 |   :group 'textile-faces)
389 | 
390 | (defface textile-image-face
391 |   '((t (:foreground "pink")))
392 |   "Face used to highlight image links."
393 |   :group 'textile-faces)
394 | 
395 | (defface textile-acronym-face
396 |   '((t (:foreground "cyan")))
397 |   "Face used to highlight acronyms links."
398 |   :group 'textile-faces)
399 | 
400 | 
401 | (provide 'textile-mode)
402 |  ;;; textile-mode.el ends here


--------------------------------------------------------------------------------
/vendor/any-ini-mode.el:
--------------------------------------------------------------------------------
  1 | ;;; any-ini-mode.el --- keyword highlighting for .ini files etc based on a 'source of truth'
  2 | 
  3 | ;;; Copyright (C) 2002, 2003 Robert Fitzgerald 
  4 | 
  5 | ;;; Author: Robert Fitzgerald 
  6 | ;;; Created: Mar 2003
  7 | ;;; Version: 1.0.4
  8 | ;;; Keywords: convenience 
  9 | 
 10 | ;;; This file is not part of GNU Emacs.
 11 | 
 12 | ;;; This program is free software; you can redistribute it and/or
 13 | ;;; modify it under the terms of the GNU General Public License as
 14 | ;;; published by the Free Software Foundation; either version 2, or (at
 15 | ;;; your option) any later version.
 16 | 
 17 | ;;; This program is distributed in the hope that it will be useful, but
 18 | ;;; WITHOUT ANY WARRANTY; without even the implied warranty of
 19 | ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 20 | ;;; General Public License for more details.
 21 | 
 22 | ;;; You should have received a copy of the GNU General Public License
 23 | ;;; along with this program ; see the file COPYING.  If not, write to
 24 | ;;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 25 | ;;; Boston, MA 02111-1307, USA.
 26 | 
 27 | ;;; Commentary:
 28 |  
 29 | ;;; When a file is visted in .ini mode the _valid_ section and parameter names
 30 | ;;; are highlighted as keywords, the comments are highlighted as comments and everything 
 31 | ;;; else is displayed in your normal font. 
 32 | 
 33 | ;;; The list of valid section and parameter names is built dynamically, based on a 
 34 | ;;; canonical file ('source of truth') that contains all valid options.
 35 | 
 36 | ;;; In this way, you can easily spot a mis-typed name when you're editting your files, 
 37 | ;;; rather than having to wait for your application to misbehave.
 38 | 
 39 | ;;; It's also useful if, like me, you have users who can't spell 'log_file_path' or
 40 | ;;; colleagues who insist on creating parameters called 'defaulttofirstbackupdirectory'.
 41 |  
 42 | ;;; You may also define, among other things, a valid comment character and a
 43 | ;;; valid assignment charcter.
 44 | 
 45 | ;;; Collectively, the definition of a canonical file and a comment character etc 
 46 | ;;; define a 'style' of .ini file.
 47 | ;;;
 48 | ;;; You may set up a default style for all .ini mode buffers, or, more usefully,
 49 | ;;; you may set up several styles that will be automatically applied, based on the name
 50 | ;;; of the file being visited.
 51 | 
 52 | ;;; any-ini-mode now includes support for `imenu'.
 53 | ;;;
 54 | ;;; `imenu-generic-expression' is set up for each buffer to find the section names
 55 | ;;; and, by default, a menu of section names is automatically added to the menubar.
 56 | ;;;
 57 | ;;; If you setup `speedbar' correctly, this means that you can also navigate the 
 58 | ;;; sections with `speedbar'.
 59 | ;;;
 60 | ;;; See the `any-ini-imenu' customization group and the documentation for `imenu'
 61 | ;;; and `speedbar' for more details.
 62 | 
 63 | ;;; Finally, you may want to try running the `any-ini-toggle-errorcheck-mode' command.
 64 | ;;; See the docstring for this command for an explantion.
 65 | 
 66 | ;;; Customization is via the `any-ini' group in the `local' customization section.
 67 | 
 68 | ;;;
 69 | ;;; To load any-ini-mode on startup, copy this file to your load-path and add this to 
 70 | ;;; your .emacs file -
 71 | ;;;
 72 | ;;;    (require 'any-ini-mode)
 73 | ;;;
 74 | ;;; You may also want to specify that .ini mode should apply by default
 75 | ;;; to all .ini and .conf files, for example. Here's how -
 76 | ;;;
 77 | ;;;    (add-to-list 'auto-mode-alist '(".*\\.ini$" . any-ini-mode))
 78 | ;;;    (add-to-list 'auto-mode-alist '(".*\\.conf$" . any-ini-mode))
 79 | ;;;
 80 | 
 81 | ;;; Example:
 82 | ;;;
 83 | ;;; You deal with three applications - larry, mo and curly.
 84 | ;;; Each requires a config file - larry.conf, mo.ini and .curlyrc - and none of the parameter
 85 | ;;; names that are valid in a mo.ini file are valid in a larry.conf or a .curlyrc, etc. etc.
 86 | ;;; 
 87 | ;;; No problem.
 88 | ;;;
 89 | ;;; First, create a canonical config file for each app (the names of these files are unimportant).
 90 | ;;; This is simply a template containing all the valid sections and parameters.
 91 | ;;; eg.
 92 | ;;;
 93 | ;;; --------------------------------------------------------------------------------------
 94 | ;;; | # canon.larry.conf - canonical config file for the larry app                       |
 95 | ;;; | # this file is maintained by the larry developers in ~devel/larry/etc              |
 96 | ;;; | # Applies to larry v6.6.6 and up                                                   |
 97 | ;;; | # Last updated 12-24-2001 by groucho                                               |
 98 | ;;; |                                                                                    |
 99 | ;;; | [USER]                                                                             |
100 | ;;; | editor =                                                                           |
101 | ;;; | #group =           # deprecated v6.6.6                                             |
102 | ;;; | home =                                                                             |
103 | ;;; |                                                                                    |
104 | ;;; | [BACKUP]                                                                           |
105 | ;;; | path =                                                                             |
106 | ;;; | always =           #                                                               |
107 | ;;; | never =            # NB - only one of these should be set TRUE in a live file      |
108 | ;;; | sometimes =        #                                                               |
109 | ;;; |                                                                                    |
110 | ;;; --------------------------------------------------------------------------------------
111 | ;;;
112 | ;;; Next, create 3 styles (call them larry.conf, mo.ini and .curlyrc) in `any-ini-styles-alist' 
113 | ;;; and set the canonical file for each type.  You can also specify, for example, that a mo.ini
114 | ;;; uses `<' and `>' to bracket section names and that a .curlyrc uses `:' as its assignment 
115 | ;;; character.
116 | ;;;
117 | ;;; Finally, add this to your .emacs file -
118 | ;;; 
119 | ;;;    (require 'any-ini-mode) 
120 | ;;;    (add-to-list 'auto-mode-alist '(".*\\.ini$" . any-ini-mode))
121 | ;;;    (add-to-list 'auto-mode-alist '(".*\\.conf$" . any-ini-mode))
122 | ;;;    (add-to-list 'auto-mode-alist '("\\.curlyrc" . any-ini-mode))
123 | ;;;
124 | 
125 | ;;; Change Log:
126 | 
127 | ;;; Changes from 1.0.3 to 1.0.4:
128 | 
129 | ;;; * Improved doc strings for `any-ini-param-name-regexp' and `any-ini-section-name-regexp'
130 | ;;;   Based on feedback from Dave Pearson and others
131 | 
132 | ;;; Changes from 1.0.2 to 1.0.3:
133 | 
134 | ;;; * Fixed up for use with `describe-mode'.
135 | ;;;   Thanks to Vagn Johansen
136 | 
137 | ;;; Changes from 1.0.1 to 1.0.2:
138 | 
139 | ;;; * Add an `imenu' menu for section names
140 | ;;;   See `any-ini-setup-imenu' for details.
141 | 
142 | ;;; Changes from 1.0.0 to 1.0.1:
143 | 
144 | ;;; * Use new `any-ini-regexp-opt' function in place of standard `regexp-opt' function.
145 | ;;;   Necessary because of occasional memory problems with `regexp-opt' during parsing 
146 | ;;;   of very large (1500+ lines) files.
147 | 
148 | ;;; Customization:
149 | 
150 | (defgroup any-ini nil
151 |   "Major mode for editing .ini files with customizable keyword highlighting."
152 |   :tag ".ini"
153 |   :group 'local)
154 | 
155 | (defgroup any-ini-faces nil
156 |   "Faces for .ini mode.
157 | 
158 | Comments use `font-lock-comment-face'."
159 |   :tag ".ini faces"
160 |   :group 'any-ini)
161 | 
162 | (defgroup any-ini-imenu nil
163 |   ".ini interaction with `imenu'.
164 | 
165 | See Info Node `(emacs)Imenu' for more details."
166 |   :tag ".ini imenu"
167 |   :group 'any-ini)
168 | 
169 | (defcustom any-ini-canonical-ini-files '(("~/.any.ini.canon" nil))
170 |   "*Alist of files to be parsed for valid section and parameter names.
171 | 
172 | Each description has the form (FILENAME TYPE).
173 | 
174 | Files may be parsed in three ways, based on TYPE :
175 | 
176 | :is-canonical-file (nil)
177 | 
178 | The file will be treated as a canonical file.
179 | 
180 | It will be parsed twice, once to extract the section names and once
181 | to extract the parameter names.
182 | 
183 | The section names will be extracted using `any-ini-section-start-chars',
184 | `any-ini-section-name-regexp' and `any-ini-section-end-chars'.
185 | 
186 | The parameter names will be extracted using `any-ini-param-name-regexp'.
187 | Parameter names will be extracted only if they are followed by an
188 | assignment character (see `any-ini-assignment-chars'), possibly with
189 | intervening whitespace. It is not necessary, however, for the parameters
190 | to have any values assigned.
191 | 
192 | :is-list-of-section-names (1)
193 | 
194 | The file will be treated as a simple list of valid section names.
195 | The first whitespace-delimited word on each line will be checked against
196 | `any-ini-section-name-regexp' and those that pass will be extracted.
197 | 
198 | :is-list-of-paramter-names (2)
199 | 
200 | The file will be treated as a simple list of valid parameter names.
201 | The first whitespace-delimited word on each line will be checked against
202 | `any-ini-param-name-regexp' and those that pass will be extracted.
203 | 
204 | In all cases,  whitespace is ignored and `any-ini-comment-start-chars' is
205 | used to disregard comments."
206 |   :group 'any-ini
207 |   :type '(repeat (list :tag "Canonical files" :value ("~/.any.ini.canon" nil)
208 | 		       (file  :tag "Filename")
209 | 		       (choice :tag "Type" 
210 | 			       (const :tag "Canonical file" nil)
211 | 			       (const :tag "List of section names" 1)
212 | 			       (const :tag "List of parameter names" 2)))))
213 | 
214 | (defcustom any-ini-comment-start-chars '( ?\# )
215 |   "Characters that may start a comment.
216 | 
217 | Multi-line comments are not handled; a comment is assumed
218 | to end with a linefeed or formfeed.
219 | 
220 | Default value is `#'."
221 |   :group 'any-ini
222 |   :type '(repeat :tag "Comment chars" (character :value ?\# :tag "Char")))
223 | 
224 | (defcustom any-ini-param-name-regexp "[-_A-Za-z0-9]+"
225 |   "Regexp to describe valid parameter name.
226 | 
227 | This regexp is used only when a canonical file is parsed for valid
228 | parameter names.
229 | 
230 | The actual keyword highlighting of parameter names is based on the
231 | list of parameter names thus created, _not_ on this regexp.
232 | 
233 | The regexp should describe the characters that make up a valid
234 | parameter _name_ only (eg. My_Param-11 ). The mode itself will
235 | take care of handling any surrounding whitespace and/or assignment
236 | character.
237 | 
238 | Default value is \"[-_A-Za-z0-9]+\".
239 | 
240 | See also `any-ini-assignment-chars'."
241 |   :group 'any-ini
242 |   :type '(regexp :tag "Params regexp" :value "[-_A-Za-z0-9]+"))
243 | 
244 | (defcustom any-ini-assignment-chars '( ?\= )
245 |   "Characters that show the assignment of a value to a parameter.
246 | 
247 | Parameter names will be extracted from a canonical file only if they are
248 | followed by an assignment character, possibly with intervening whitespace.
249 | It is not necessary, however, for the parameter to have any values assigned.
250 | 
251 | The same rules apply to highlighting a parameter name in an `any-ini-mode'
252 | buffer.
253 | 
254 | Default value is `='."
255 |   :group 'any-ini
256 |   :type '(repeat :tag "Assignment chars" (character :value ?\= :tag "Char")))
257 | 
258 | (defcustom any-ini-section-name-regexp "[-_A-Za-z0-9]+"
259 |   "Regexp to describe valid section name.
260 | 
261 | This regexp is used only when a canonical file is parsed for valid
262 | section names.
263 | 
264 | The actual keyword highlighting of section names is based on the
265 | list of section names thus created, _not_ on this regexp.
266 | 
267 | This regexp should describe the characters that make up a valid
268 | section _name_ only (eg. MY_SECTION-22 ). The mode itself will
269 | take care of handling any surrounding brackets.
270 | 
271 | See `any-ini-section-start-chars' and `any-ini-section-end-chars' for 
272 | the definition of the bracketting characters.
273 | 
274 | Default value is \"[-_A-Za-z0-9]+\"."
275 |   :group 'any-ini
276 |   :type '(regexp :tag "Sections regexp" :value "[-_A-Za-z0-9]+"))
277 | 
278 | (defcustom any-ini-section-start-chars '( ?\[ )
279 |   "Characters that may begin a section heading.
280 | 
281 | NB - No attempt is made to pair-up the characters that start and end a
282 | section heading.  It's assumed that a section heading that is begun
283 | by a valid starting character may be ended by _any_ valid ending character. 
284 | 
285 | Default value is `['.
286 | 
287 | See also `any-ini-section-end-chars'."
288 |   :group 'any-ini
289 |   :type '(repeat :tag "Section start chars" (character :value ?\[ :tag "Char")))
290 |  
291 | (defcustom any-ini-section-end-chars '( ?\] )
292 |   "Characters that may end a section heading.
293 | 
294 | NB - No attempt is made to pair-up the characters that start and end a
295 | section heading.  It's assumed that a section heading that is begun
296 | by a valid starting character may be ended by _any_ valid ending character. 
297 | 
298 | Default value is `]'.
299 | 
300 | See also `any-ini-section-start-chars'."
301 |   :group 'any-ini
302 |   :type '(repeat :tag "Section end chars" (character :value ?\]  :tag "Char")))
303 | 
304 | (defcustom any-ini-styles-alist nil
305 |   "List of .ini styles that may be used in preference to the default style.
306 | 
307 | Each item has the form -
308 | 
309 | \(STYLENAME CANON_FILES COMMENT_CHARS PARAM_REGEXP ASSIGNERS SECTION_REGEXP SECT_STARTERS SECT_ENDERS KEYWORDS)
310 | 
311 | STYLENAME: Each style list should be given a meaningful name. When a file is
312 | visited in .ini mode, `any-ini-styles-alist' will be searched for a STYLENAME
313 | that matches the name of the file.  If a match is found, the style settings in
314 | the list will be applied. If not, the default style will be used.
315 | 
316 | CANON_FILES: See the documentation for `any-ini-canonical-ini-files'
317 | COMMENT_CHARS: See the documentation for `any-ini-comment-start-chars'
318 | PARAM_REGEXP: See the documentation for `any-ini-param-name-regexp'
319 | ASSIGNERS: See the documentation for `any-ini-assignment-chars'
320 | SECTION_REGEXP: See the documentation for `any-ini-section-name-regexp'
321 | SECT_STARTERS: See the documentation for `any-ini-section-start-chars'
322 | SECT_ENDERS: See the documentation for `any-ini-section-end-chars'."
323 |   :group 'any-ini
324 |   :type '(repeat (list
325 | 	  (string :tag "Style name" :value "new.ini")
326 | 	  (repeat :tag "Canonical files" (list :value ("~/.new.ini.canon" nil)
327 | 			(file  :tag "Filename")
328 | 			(choice :tag "Type" 
329 | 				(const :tag "Canonical file" nil)
330 | 				(const :tag "List of section names" 1)
331 | 				(const :tag "List of parameter names" 2))))
332 | 	  (repeat :tag "Comment chars" (character :value ?\# :tag "Char"))
333 | 	  (regexp :tag "Params regexp" :value "[-_A-Za-z0-9]+")
334 | 	  (repeat :tag "Assignment chars" (character :value ?\= :tag "Char"))
335 | 	  (regexp :tag "Sections regexp" :value "[-_A-Za-z0-9]+")
336 | 	  (repeat :tag "Section start chars" (character :value ?\[ :tag "Char"))
337 | 	  (repeat :tag "Section end chars" (character :value ?\] :tag "Char" )))))
338 | 
339 | (defcustom any-ini-mode-mode-hook nil
340 |   "Normal hook run when entering .ini mode."
341 |   :type 'hook
342 |   :group 'any-ini)
343 | 
344 | (defcustom any-ini-param-face  'font-lock-function-name-face
345 |   "*Font that .ini mode will use to highlight parameter names."
346 |   :type 'face
347 |   :group 'any-ini-faces)
348 | 
349 | (defcustom any-ini-section-face  'font-lock-keyword-face
350 |   "*Font that .ini mode will use to highlight section names."
351 |   :type 'face
352 |   :group 'any-ini-faces)
353 | 
354 | (defcustom any-ini-assigner-face  'default
355 |   "*Font that .ini mode will use to highlight the assignment character."
356 |   :type 'face
357 |   :group 'any-ini-faces)
358 | 
359 | (defcustom any-ini-value-face  'default
360 |   "*Font that .ini mode will use to highlight parameter values."
361 |   :type 'face
362 |   :group 'any-ini-faces)
363 | 
364 | (defcustom any-ini-section-chars-face  'default
365 |   "*Font that .ini mode will use to highlight section names."
366 |   :type 'face
367 |   :group 'any-ini-faces)
368 | 
369 | (defcustom any-ini-imenu-show-flag t
370 |   "Use `imenu' \(if available\) to add a menu of section names to menubar.
371 | 
372 | Non-nil means that a menu of section names will be automatically created
373 | for each new .ini mode buffer through a call to `imenu-add-to-menubar'.
374 | 
375 | The menu name is defined by `any-ini-imenu-name'.
376 | 
377 | `imenu-generic-expression' is _always_ initialised in .ini mode
378 | buffers, regardless of the state of this flag.  This means that the
379 | standard `imenu' commands should always be available.
380 | 
381 | See Info Node `(emacs)Imenu' for more details."
382 |   :group 'any-ini-imenu
383 |   :type 'boolean)
384 | 
385 | (defcustom any-ini-imenu-name "Sections"
386 |   "Name to use for menu of section names."
387 |   :group 'any-ini-imenu
388 |   :type 'string)
389 | 
390 | ;;; Constants:
391 | 
392 | (defconst any-ini-buffer-errorcheck nil
393 |   "Buffer-local version of this var indicates if a buffer is using
394 | any-ini-errorcheck-mode.")
395 | 
396 | (defconst any-ini-style nil
397 |   "Keyword highlighting style to apply to a file.
398 | 
399 | This variable should be set by `any-ini-set-my-style'.
400 | Setting it directly won't have the desired effect. 
401 | 
402 | When `any-ini-style' is nil, the default style is applied.
403 | See also `any-ini-set-my-style' and `any-ini-styles-alist'.
404 | 
405 | *NB - You may be tempted to set this as a file variable
406 | eg.
407 | 
408 | ;;   -*- mode: any-ini; any-ini-style: \"apache\" -*-
409 | 
410 | but, unfortunately, this won't have the desired affect either.
411 | Hopefully, this technique will be available soon.
412 | 
413 | At the moment, the following _will_ work ...
414 | 
415 | ;;   -*- mode: any-ini; eval: (any-ini-set-my-style \"apache\") -*-
416 | 
417 | ... but then you'll have to deal with `enable-local-eval' etc.")
418 | 
419 | ;;; Code:
420 | 
421 | (defun any-ini-set-my-style (&optional mystyleoverride)
422 |   "*Set keyword highlighting style for a file.
423 | 
424 | MYSTYLEOVERRIDE is a string representing the name of a highlighting style.
425 | If the style is found in `any-ini-styles-alist' it will be applied to the
426 | current buffer.
427 | 
428 | If MYSTYLEOVERRIDE is `nil', the name of the currently-visited file will
429 | be taken as the required style name and will be searched for in `any-ini-styles-alist'.
430 | 
431 | If a matching style is not found for MYSTYLEOVERRIDE or the filename, the 
432 | default style will be applied.
433 | 
434 | If this function is called with a prefix argument and MYSTYLEOVERRIDE is `nil', 
435 | the default style will be applied, regardless of name of the visited file.
436 | 
437 | The default style is the style described by the global values of -
438 | 
439 | `any-ini-canonical-ini-files', 
440 | `any-ini-comment-start-chars', 
441 | `any-ini-param-name-regexp'
442 | `any-ini-assignment-chars', 
443 | `any-ini-section-name-regexp', 
444 | `any-ini-section-start-chars'
445 | `any-ini-section-end-chars'
446 | "
447 |   (interactive
448 |    (if any-ini-styles-alist
449 |        (list 
450 | 	(completing-read "Apply any-ini-style :" any-ini-styles-alist nil t))
451 |      (message "any-ini-mode : No styles defined.")
452 |      nil))
453 |   (if (not (eq major-mode 'any-ini-mode))
454 |       (message "Major mode is not any-ini-mode.")
455 |     (make-local-variable 'any-ini-style)
456 |     (if (and current-prefix-arg (string= mystyleoverride ""))
457 | 	(setq any-ini-style nil)
458 |       (if (string= mystyleoverride "")
459 | 	  (setq any-ini-style nil)
460 | 	(setq any-ini-style mystyleoverride))
461 |       (if (and any-ini-style (stringp any-ini-style))
462 | 	  ()
463 | 	(if buffer-file-name
464 | 	    (setq any-ini-style (file-name-nondirectory buffer-file-name)))))
465 |     (any-ini-apply-style)
466 |     (font-lock-mode -1)
467 |     (font-lock-mode t)))
468 | 
469 | (defun any-ini-apply-style (&optional re-read-canons)
470 |   "Setup and apply style for a buffer, based on local `any-ini-style'.
471 | 
472 | If `any-ini-style' is nil, or is not the name of a style from `any-ini-styles-alist',
473 | then the default style will be applied.
474 | 
475 | If RE-READ-CANONS is non-nil, the relevant canon files will be re-parsed and the
476 | stored font-lock-keywords for the style updated.
477 | 
478 | Otherwise, the canon files will only be parsed if they have not previously been
479 | parsed in this Emacs session."
480 | 
481 |   (let (mystylealist nofontlocksyet)
482 |     (if any-ini-style
483 | 	(setq mystylealist (assoc any-ini-style any-ini-styles-alist)))
484 |     (cond ((not mystylealist) 
485 | 	   (kill-local-variable 'any-ini-font-lock-keywords)
486 | 	   (kill-local-variable 'any-ini-canonical-ini-files)
487 | 	   (kill-local-variable 'any-ini-comment-start-chars)
488 | 	   (kill-local-variable 'any-ini-param-name-regexp)
489 | 	   (kill-local-variable 'any-ini-assignment-chars)
490 | 	   (kill-local-variable 'any-ini-section-name-regexp)
491 | 	   (kill-local-variable 'any-ini-section-start-chars)
492 | 	   (kill-local-variable 'any-ini-section-end-chars)
493 | 	   (setq any-ini-style nil))
494 | 	  (t
495 | 	   (make-local-variable 'any-ini-font-lock-keywords)
496 | 	   (make-local-variable 'any-ini-canonical-ini-files)
497 | 	   (make-local-variable 'any-ini-comment-start-chars)
498 | 	   (make-local-variable 'any-ini-param-name-regexp)
499 | 	   (make-local-variable 'any-ini-assignment-chars)
500 | 	   (make-local-variable 'any-ini-section-name-regexp)
501 | 	   (make-local-variable 'any-ini-section-start-chars)
502 | 	   (make-local-variable 'any-ini-section-end-chars)
503 | 	   (setq any-ini-font-lock-keywords nil)
504 | 	   (if re-read-canons
505 | 	       ()
506 | 	     (let ((mysavedfontlock (get 'any-ini-styles-alist any-ini-style)))
507 | 	       (if mysavedfontlock 
508 | 		   (setq any-ini-font-lock-keywords mysavedfontlock)
509 | 		 (setq nofontlocksyet t))))
510 | 	   (setq any-ini-canonical-ini-files (nth 1 mystylealist))
511 | 	   (setq any-ini-comment-start-chars (nth 2 mystylealist))
512 | 	   (setq any-ini-param-name-regexp (nth 3 mystylealist))
513 | 	   (setq any-ini-assignment-chars (nth 4 mystylealist))
514 | 	   (setq any-ini-section-name-regexp (nth 5 mystylealist))
515 | 	   (setq any-ini-section-start-chars (nth 6 mystylealist))
516 | 	   (setq any-ini-section-end-chars (nth 7 mystylealist))))
517 |     (any-ini-setup-local-syntax-table)
518 |     (any-ini-read-keywords re-read-canons)
519 |     (any-ini-setup-imenu)
520 |     (make-local-variable 'comment-start)
521 |     (if any-ini-comment-start-chars
522 | 	(setq comment-start (string (nth 0 any-ini-comment-start-chars)))
523 |       (setq comment-start "#"))
524 |     (make-local-variable 'comment-end)
525 |     (setq comment-end "")    
526 |     (setq mode-name (concat "" (if (not any-ini-style) 
527 | 					".ini" 
528 | 				      (concat " " any-ini-style)) 
529 | 			    " file"))
530 |     (when (or nofontlocksyet re-read-canons)
531 |       (put 'any-ini-styles-alist any-ini-style any-ini-font-lock-keywords))))
532 | 
533 | (defvar any-ini-local-syntax-table nil
534 |   "Syntax table used while in .ini mode.
535 | 
536 | Spaces and tabs are defined as whitespace, linefeeds and formfeeds are defined 
537 | as comment-ending characters and the defined `any-ini-comment-start-chars' are
538 | defined as comment-starting characters.")
539 | 
540 | (defun any-ini-setup-local-syntax-table ()
541 |   "Setup local syntax table based on settings for `any-ini-comment-start-chars'.
542 | 
543 | Spaces and tabs are defined as whitespace, linefeeds and formfeeds are defined 
544 | as comment-ending characters and the defined `any-ini-comment-start-chars' are
545 | defined as comment-starting characters.
546 | 
547 | Syntax table is stored as `any-ini-local-syntax-table'."
548 |   (make-local-variable 'any-ini-local-syntax-table)
549 |   (setq any-ini-local-syntax-table (make-syntax-table))
550 |   (set-syntax-table any-ini-local-syntax-table)
551 |   (modify-syntax-entry ?\  " ")
552 |   (modify-syntax-entry ?\t " ")
553 |   (modify-syntax-entry ?\n ">")
554 |   (modify-syntax-entry ?\f ">")
555 |   (if (not any-ini-comment-start-chars)
556 |       (modify-syntax-entry ?\# "<")
557 |     (dolist (commentchar any-ini-comment-start-chars)
558 |       (modify-syntax-entry commentchar "<"))))
559 | 
560 | (defvar any-ini-map nil
561 |   "Keymap for .ini mode.")
562 | (if any-ini-map
563 |     ()
564 |   (setq any-ini-map (make-sparse-keymap)))
565 | 
566 | (defvar any-ini-abbrev-table nil
567 |   "Abbrev table used while in .ini mode.")
568 | (define-abbrev-table 'any-ini-abbrev-table ())
569 | 
570 | (defvar any-ini-font-lock-keywords nil
571 |   "Current list of keywords for highlighting in default .ini mode.
572 | 
573 | See also `any-ini-read-keywords' and `any-ini-reread-keywords'.")
574 | 
575 | (defun any-ini-re-read-keywords-etc ()
576 |   "*Re-parse the canonical files for the current style and update all style
577 | info based on the current customization settings.
578 | 
579 | Having updated the style info, this fuction will then cycle through
580 | all buffers and also update those that may be affected by the re-read.
581 | 
582 | Calls `any-ini-apply-style' in this buffer with RE-READ-CANONS as t
583 | and `any-ini-apply-style' for the other buffers with no argument."
584 |   (interactive)
585 |   (if (not (eq major-mode 'any-ini-mode))
586 |       (message "Major mode is not any-ini-mode.")
587 |     (message "any-ini-reread-keywords : working ....")
588 |     (any-ini-apply-style t)
589 |     (save-excursion
590 |       (let ((updating-style any-ini-style))
591 | 	(dolist (somebuffer (buffer-list))
592 | 		(set-buffer somebuffer)
593 | 		(when (and (eq major-mode 'any-ini-mode) (eq any-ini-style updating-style))
594 | 		  (any-ini-apply-style)
595 | 		  (font-lock-mode -1)
596 | 		  (font-lock-mode t)))))
597 |     (message "any-ini-reread-keywords : DONE.")))
598 | 
599 | (defun any-ini-read-keywords (&optional forceread)
600 |   "Create keyword-map for .ini mode, based on current canon files.
601 | 
602 | Can be called from `any-ini-reread-keywords', in which case FORCEREAD
603 | will be non-nil, the relevant canonical files will be re-read and any current
604 | font-lock-keyword info for the current style will be overwritten.
605 | 
606 | Otherwise, no action will be taken if a current font-lock-keywords list exists
607 | for the current style.
608 | 
609 | The font-lock-keyword lists for the default style are stored in the global version
610 | of `any-ini-font-lock-keywords'. The keywords for the styles from `any-ini-styles-alist'
611 | are stored in local versions of `any-ini-font-lock-keywords' and also in a plist
612 | of `any-ini-styles-alist'.
613 | 
614 | At the moment, this data is not saved between Emacs sessions - instead, it is recreated
615 | for each style, the first time the style is activated in a session."
616 |   (if (and any-ini-font-lock-keywords (not forceread))
617 |       ()
618 |     (setq any-ini-font-lock-keywords nil)
619 |     (dolist (mykeyfile any-ini-canonical-ini-files)
620 |       (setq any-ini-font-lock-keywords 
621 | 	    (append 
622 | 	     (any-ini-append-keys-from mykeyfile (list nil
623 | 						       nil
624 | 						       any-ini-comment-start-chars
625 | 						       any-ini-param-name-regexp
626 | 						       any-ini-assignment-chars
627 | 						       any-ini-section-name-regexp
628 | 						       any-ini-section-start-chars
629 | 						       any-ini-section-end-chars)
630 | 				       ) 
631 | 	     any-ini-font-lock-keywords)))
632 |     (setq any-ini-font-lock-keywords
633 | 	  (append (list (cons 
634 | 			 (concat "\\^.*\\([" 
635 | 				 (if any-ini-comment-start-chars 
636 | 				     any-ini-comment-start-chars
637 | 				  (string ?\#) )
638 | 				 "].*$\\)") 
639 | 			 (list 2 'font-lock-comment-face nil nil))
640 | 			)
641 | 		  any-ini-font-lock-keywords )))
642 |   (setq font-lock-defaults (list any-ini-font-lock-keywords nil t nil nil)))
643 | 
644 | (defun any-ini-append-keys-from (kfile mystylealist)
645 |   "Read a file and set the section and/or param names it contains as keywords
646 | in `any-ini-font-lock-keywords'."
647 |   (let (mykeyfile myfiletype myparselist isinifile my-font-lock-keywords)
648 |     (setq mykeyfile (nth 0 kfile))
649 |     (setq myfiletype (nth 1 kfile))
650 |     (cond 
651 |      ( (eq myfiletype 1) (setq myparselist '(t)))       ;; Sections list
652 |      ( (eq myfiletype 2) (setq myparselist '(nil)))     ;; Params list
653 |      ( t (setq isinifile t)             ;; .ini file, parse twice
654 | 	 (setq myparselist '(t nil)))
655 |      )
656 |     (when (file-exists-p mykeyfile)
657 |       (save-current-buffer
658 | 	(let (mykeywordslist 
659 | 	      mykeyword 
660 | 	      font
661 | 	      (my-any-ini-comment-start-chars (nth 2 mystylealist))
662 | 	      (my-any-ini-param-name-regexp (nth 3 mystylealist))
663 | 	      (my-any-ini-assignment-chars (nth 4 mystylealist))
664 | 	      (my-any-ini-section-name-regexp (nth 5 mystylealist))
665 | 	      (my-any-ini-section-start-chars (nth 6 mystylealist))
666 | 	      (my-any-ini-section-end-chars (nth 7 mystylealist)))
667 | 	  (set-buffer (get-buffer-create "*any-ini-temp*"))
668 | 	  (insert-file-contents mykeyfile nil nil nil t)
669 | 	  (dolist (sectionfile myparselist)
670 | 	    (goto-char (point-min))
671 | 	    (condition-case e
672 | 		(while t
673 | 		  (cond ((and isinifile sectionfile)
674 | 			 (re-search-forward 
675 | 			  (concat "\\(^[ \t]*\\)"
676 | 				  "\\([" 
677 | 				  (if my-any-ini-section-start-chars 
678 | 				      my-any-ini-section-start-chars 
679 | 				      (string ?\[)) 
680 | 				  "]\\)"
681 | 				  "\\(" 
682 | 				  (if my-any-ini-section-name-regexp 
683 | 				      my-any-ini-section-name-regexp
684 | 				    "[-_A-Za-z0-9]+")
685 | 				  "\\)"
686 | 				  "\\(["
687 | 				  (if my-any-ini-section-end-chars
688 | 				      my-any-ini-section-end-chars
689 | 				    (string ?\]))
690 | 				  "]\\)"
691 | 				  "\\(.*$\\)"
692 | 				  )
693 | 			  )
694 | 			 (setq mykeyword (match-string 3)))
695 | 			((and isinifile (not sectionfile))
696 | 			 (re-search-forward 
697 | 			  (concat "\\(^[ \t]*\\)\\("
698 | 				  (if my-any-ini-param-name-regexp
699 | 				      my-any-ini-param-name-regexp
700 | 				    "[-_A-Za-z0-9]+")
701 | 				  "\\)\\([ \t]*"
702 | 				  "["
703 | 				  (if my-any-ini-assignment-chars
704 | 				      my-any-ini-assignment-chars
705 | 				    (string ?\=))
706 | 				  "]"
707 | 				  ".*$\\)")
708 | 			  )
709 | 			 (setq mykeyword (match-string 2)))
710 | 			(sectionfile
711 | 			 (re-search-forward 
712 | 			  (concat "\\(^[ \t]*\\)\\("
713 | 				  (if my-any-ini-section-name-regexp
714 | 				      my-any-ini-section-name-regexp
715 | 				    "[-_A-Za-z0-9]+")
716 | 				  "\\)$")
717 | 			  )
718 | 			 (setq mykeyword (match-string 2)))
719 | 			((not sectionfile)
720 | 			 (re-search-forward 
721 | 			  (concat "\\(^[ \t]*\\)\\("
722 | 				  (if my-any-ini-param-name-regexp
723 | 				      my-any-ini-param-name-regexp
724 | 				    "[-_A-Za-z0-9]+")
725 | 				  "\\)$")
726 | 			  )
727 | 			 (setq mykeyword (match-string 2))))
728 | 		  (when mykeyword
729 | 		    (setq mykeywordslist (append (list mykeyword) mykeywordslist))))
730 | 	      (search-failed))
731 | 	    (setq my-font-lock-keywords
732 | 		  (append (list 
733 | 			   (cons 
734 | 			    (any-ini-keywords-regexp mykeywordslist sectionfile mystylealist) 
735 | 			    (if sectionfile
736 | 				(list 
737 | 				 (list 1 'any-ini-section-chars-face nil nil)
738 | 				 (list 2 'any-ini-section-face nil nil)
739 | 				 (list 3 'any-ini-section-chars-face nil nil)
740 | 				 )
741 | 			    (list (list 2 'any-ini-param-face nil nil) 
742 | 				  (list 4 'any-ini-assigner-face nil nil)
743 | 				  (list 6 'any-ini-value-face nil nil)
744 | 				  (list 7 'font-lock-comment-face nil nil)
745 | 				  ))			    
746 | 			    )
747 | 			   )
748 | 			  my-font-lock-keywords )))
749 | 	  (kill-buffer (current-buffer)))))
750 |     my-font-lock-keywords))
751 | 
752 | (defun any-ini-keywords-regexp (keywords aresections mystylealist)
753 |   "Create regexp to describe sections/params for font-locking.
754 | 
755 | NB - First part of the regexps (searching for whitespace etc at the beginning of a line),
756 | is wrapped in parentheses to ensure that the keyword part of the regexp is always be `subexp2'."
757 |   (let (
758 | 	(my-any-ini-comment-start-chars (nth 2 mystylealist))
759 | 	(my-any-ini-param-name-regexp (nth 3 mystylealist))
760 | 	(my-any-ini-assignment-chars (nth 4 mystylealist))
761 | 	(my-any-ini-section-name-regexp (nth 5 mystylealist))
762 | 	(my-any-ini-section-start-chars (nth 6 mystylealist))
763 | 	(my-any-ini-section-end-chars (nth 7 mystylealist)))
764 |     (if aresections
765 | 	(concat "\\(^[ \t]*["
766 | 		(if my-any-ini-section-start-chars
767 | 		    my-any-ini-section-start-chars
768 | 		  (string ?\[))
769 | 		"]\\)" 
770 | 		(any-ini-regexp-opt keywords t) 
771 | 		"\\([" 
772 | 		(if my-any-ini-section-end-chars
773 | 		    my-any-ini-section-end-chars
774 | 		  (string ?\]))
775 | 		"]\\)"
776 | 		"\\([ \t]*$\\|[ \t]+["
777 | 		(if my-any-ini-comment-start-chars
778 | 		    my-any-ini-comment-start-chars
779 | 		  (string ?\#))
780 | 		"].*$\\)"
781 | 		)
782 |       (concat "\\(^[ \t]*\\)"
783 | 	      (any-ini-regexp-opt keywords t) 
784 | 	      "\\([ \t]*\\)"
785 | 	      "\\([" 
786 | 	      (if my-any-ini-assignment-chars 
787 | 		  my-any-ini-assignment-chars
788 | 		(string ?\=))
789 | 	      "]\\)"
790 | 	      "\\([ \t]*\\)"
791 | 	      "\\([^"
792 | 	      (if my-any-ini-comment-start-chars
793 | 		  my-any-ini-comment-start-chars
794 | 		(string ?\#))
795 | 	      "\n]*\\)"
796 | 	      "\\(["
797 | 	      (if my-any-ini-comment-start-chars
798 | 		  my-any-ini-comment-start-chars
799 | 		(string ?\#))
800 | 	      "].*\\|[\n]\\)"
801 | 	      ))))
802 | 
803 | (defun any-ini-regexp-opt (strings paren)
804 |   "Replacement for standard `regexp-opt' function.
805 | 
806 | This replacement is necessary since the standard function can occasionally cause a memory 
807 | error when setting a file's mode from the auto-mode-alist functionality.
808 | 
809 | Error was \"Variable binding depth exceeds max-specpdl-size\" and happened only with
810 | large (1500+ lines) canonical files."
811 |   (let ((open-paren (if paren "\\(" ""))
812 |         (close-paren (if paren "\\)" "")))
813 |     (concat open-paren
814 |             (mapconcat 'regexp-quote strings "\\|")
815 |             close-paren)))
816 | 
817 | (defun any-ini-toggle-errorcheck-mode ()
818 |   "*Temorarily set fonts in this buffer to highlight spelling errors more clearly.
819 | 
820 | Resets the comment face and param-related faces in this buffer to `font-lock-string-face'.
821 | The idea is that this will make it easier to spot errors in a large or heavily-commented 
822 | file, as they should show up in `default' face against a relatively neutral background.
823 | 
824 | The fonts affected are - 
825 | 
826 | `font-lock-comment-face'
827 | `any-ini-param-face'
828 | `any-ini-assigner-face'
829 | `any-ini-value-face'
830 | "
831 |   (interactive)
832 |   (if (not (eq major-mode 'any-ini-mode))
833 |       (message "Major mode is not any-ini-mode.")
834 |     (make-variable-buffer-local 'any-ini-buffer-errorcheck)
835 |     (cond ((eq any-ini-buffer-errorcheck 1)
836 | 	   (kill-local-variable 'font-lock-comment-face)
837 | 	   (kill-local-variable 'any-ini-param-face)
838 | 	   (kill-local-variable 'any-ini-assigner-face)
839 | 	   (kill-local-variable 'any-ini-value-face)
840 | 	   (setq any-ini-buffer-errorcheck 0)
841 | 	   )
842 | 	  (t
843 | 	   (make-local-variable 'font-lock-comment-face)
844 | 	   (make-local-variable 'any-ini-param-face)
845 | 	   (make-local-variable 'any-ini-assigner-face)
846 | 	   (make-local-variable 'any-ini-value-face)
847 | 	   (setq font-lock-comment-face 'font-lock-string-face)
848 | 	   (setq any-ini-param-face 'font-lock-string-face)
849 | 	   (setq any-ini-assigner-face 'font-lock-string-face)
850 | 	   (setq any-ini-value-face 'font-lock-string-face)
851 | 	   (setq any-ini-buffer-errorcheck 1)
852 | 	   ))
853 |     (any-ini-apply-style)
854 |     (font-lock-mode -1)
855 |     (font-lock-mode t)))
856 | 
857 | (defun any-ini-setup-imenu ()
858 |   "Setup and display an `imenu' menu of section names for current buffer.
859 | 
860 | Sets up `imenu-generic-expression' \(see Info Node `(emacs)Imenu'\)
861 | based on current settings of 
862 | 
863 | `any-ini-section-name-regexp', 
864 | `any-ini-section-start-chars',
865 | `any-ini-section-end-chars'
866 | 
867 | The title of the menu is read from `any-ini-imenu-name'.
868 | 
869 | Display of the menu is controlled by `any-ini-imenu-show-flag'.
870 | 
871 | See Info Node `(emacs)Imenu' for more details."
872 |   (make-local-variable 'imenu-generic-expression)
873 |   (setq imenu-generic-expression
874 | 	(list
875 | 	 (list nil  
876 | 	       (concat "\\(^[ \t]*\\)"
877 | 		       "\\([" 
878 | 		       (if any-ini-section-start-chars 
879 | 			   any-ini-section-start-chars 
880 | 			 (string ?\[)) 
881 | 		       "]\\)"
882 | 		       "\\(" 
883 | 		       (if any-ini-section-name-regexp 
884 | 			   any-ini-section-name-regexp
885 | 			 "[-_A-Za-z0-9]+")
886 | 		       "\\)"
887 | 		       "\\(["
888 | 		       (if any-ini-section-end-chars
889 | 			   any-ini-section-end-chars
890 | 			 (string ?\]))
891 | 		       "]\\)"
892 | 		       "\\(.*$\\)"
893 | 		       )
894 | 	       3)
895 | 	 )
896 | 	)
897 |   (if any-ini-imenu-show-flag
898 |       (if (featurep 'imenu)
899 | 	  (imenu-add-to-menubar 'any-ini-imenu-name)
900 | 	(message "any-ini-mode: imenu NOT available."))))
901 | 
902 | ;;;###autoload
903 | (defun any-ini-mode ()
904 |   "*Major mode for editing config files with syntax highlighting based on a 'source of truth'.
905 | 
906 | You may set up a default style for all .ini mode buffers, or, more usefully,
907 | you may set up several styles that will be automatically applied based on the name
908 | of the file being visited.
909 | 
910 | See `any-ini-set-my-style' and `any-ini-styles-alist' for more details.
911 | 
912 | Turning on .ini mode runs the normal hook `any-ini-mode-hook'."
913 |   (interactive)
914 |   (kill-all-local-variables)
915 |   (use-local-map any-ini-map)
916 |   (setq local-abbrev-table any-ini-abbrev-table)
917 |   (setq major-mode 'any-ini-mode)
918 |   (any-ini-set-my-style)
919 |   (run-hooks 'any-ini-mode-hook))
920 | 
921 | ;; Try to pull in imenu if it exists.
922 | (condition-case nil
923 |     (require 'imenu)
924 |   (error nil))
925 | 
926 | (provide 'any-ini-mode)
927 | 
928 | ;;; any-ini-mode.el ends here
929 | 
930 | 


--------------------------------------------------------------------------------
/vendor/lua-mode.el:
--------------------------------------------------------------------------------
   1 | ;;; lua-mode.el --- a major-mode for editing Lua scripts
   2 | 
   3 | ;; Copyright (C) 1997, 2001, 2004, 2006, 2007, 2010, 2011 Free Software Foundation, Inc.
   4 | 
   5 | ;; Author: 2010-2011 Reuben Thomas 
   6 | ;;         2006 Juergen Hoetzel 
   7 | ;;         2004 various (support for Lua 5 and byte compilation)
   8 | ;;         2001 Christian Vogler 
   9 | ;;         1997 Bret Mogilefsky  starting from
  10 | ;;              tcl-mode by Gregor Schmid 
  11 | ;;              with tons of assistance from
  12 | ;;              Paul Du Bois  and
  13 | ;;              Aaron Smith .
  14 | ;; URL:		http://lua-mode.luaforge.net/
  15 | ;; Version:	20110121
  16 | ;; This file is NOT part of Emacs.
  17 | ;;
  18 | ;; This program is free software; you can redistribute it and/or
  19 | ;; modify it under the terms of the GNU General Public License
  20 | ;; as published by the Free Software Foundation; either version 2
  21 | ;; of the License, or (at your option) any later version.
  22 | ;;
  23 | ;; This program is distributed in the hope that it will be useful,
  24 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  25 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  26 | ;; GNU General Public License for more details.
  27 | ;;
  28 | ;; You should have received a copy of the GNU General Public License
  29 | ;; along with this program; if not, write to the Free Software
  30 | ;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
  31 | ;; MA 02110-1301, USA.
  32 | 
  33 | ;; Keywords: languages, processes, tools
  34 | 
  35 | 
  36 | ;;; Commentary:
  37 | 
  38 | ;; Thanks to Tobias Polzin  for function indenting
  39 | ;; patch: Indent "(" like "{"
  40 | 
  41 | ;; Thanks to Fabien  for imenu patches.
  42 | 
  43 | ;; Thanks to Simon Marshall  and Olivier
  44 | ;; Andrieu  for font-lock patches.
  45 | 
  46 | ;; Additional font-lock highlighting and indentation tweaks by
  47 | ;; Adam D. Moss .
  48 | 
  49 | ;; INSTALLATION:
  50 | 
  51 | ;; To install, just copy this file into a directory on your load-path
  52 | ;; (and byte-compile it). To set up Emacs to automatically edit files
  53 | ;; ending in ".lua" or with a lua hash-bang line using lua-mode add
  54 | ;; the following to your init file:
  55 | ;;
  56 | ;; (autoload 'lua-mode "lua-mode" "Lua editing mode." t)
  57 | ;; (add-to-list 'auto-mode-alist '("\\.lua$" . lua-mode))
  58 | ;; (add-to-list 'interpreter-mode-alist '("lua" . lua-mode))
  59 | 
  60 | ;; Usage
  61 | 
  62 | ;; Lua-mode supports c-mode style formatting and sending of
  63 | ;; lines/regions/files to a Lua interpreter. An interpreter (see
  64 | ;; variable `lua-default-application') will be started if you try to
  65 | ;; send some code and none is running. You can use the process-buffer
  66 | ;; (named after the application you chose) as if it were an
  67 | ;; interactive shell. See the documentation for `comint.el' for
  68 | ;; details.
  69 | 
  70 | ;; Lua-mode works with Hide Show minor mode (see ``hs-minor-mode``).
  71 | 
  72 | ;; Key-bindings
  73 | 
  74 | ;; To see all the keybindings for Lua mode, look at `lua-setup-keymap'
  75 | ;; or start `lua-mode' and type `\C-h m'.
  76 | ;; The keybindings may seem strange, since I prefer to use them with
  77 | ;; lua-prefix-key set to nil, but since those keybindings are already used
  78 | ;; the default for `lua-prefix-key' is `\C-c', which is the conventional
  79 | ;; prefix for major-mode commands.
  80 | 
  81 | ;; You can customise the keybindings either by setting `lua-prefix-key'
  82 | ;; or by putting the following in your .emacs
  83 | ;;      (setq lua-mode-map (make-sparse-keymap))
  84 | ;; and
  85 | ;;      (define-key lua-mode-map  )
  86 | ;; for all the functions you need.
  87 | 
  88 | 
  89 | ;;; Code:
  90 | (require 'comint)
  91 | 
  92 | ;; Local variables
  93 | (defgroup lua nil
  94 |   "Major mode for editing lua code."
  95 |   :prefix "lua-"
  96 |   :group 'languages)
  97 | 
  98 | (defcustom lua-indent-level 3
  99 |   "Amount by which Lua subexpressions are indented."
 100 |   :type 'integer
 101 |   :group 'lua)
 102 | 
 103 | (defcustom lua-comment-start "-- "
 104 |   "Default value of `comment-start'."
 105 |   :type 'string
 106 |   :group 'lua)
 107 | 
 108 | (defcustom lua-comment-start-skip "-- "
 109 |   "Default value of `comment-start-skip'."
 110 |   :type 'string
 111 |   :group 'lua)
 112 | 
 113 | (defcustom lua-default-application "lua"
 114 |   "Default application to run in lua subprocess."
 115 |   :type 'string
 116 |   :group 'lua)
 117 | 
 118 | (defcustom lua-default-command-switches (list "-i")
 119 |   "Command switches for `lua-default-application'.
 120 | Should be a list of strings."
 121 |   :type '(repeat string)
 122 |   :group 'lua)
 123 | 
 124 | (defcustom lua-always-show t
 125 |   "*Non-nil means display lua-process-buffer after sending a command."
 126 |   :type 'boolean
 127 |   :group 'lua)
 128 | 
 129 | (defcustom lua-search-url-prefix "http://www.lua.org/manual/5.1/manual.html#pdf-"
 130 |   "*URL at which to search for documentation on a word"
 131 |   :type 'string
 132 |   :group 'lua)
 133 | 
 134 | (defvar lua-process nil
 135 |   "The active Lua subprocess")
 136 | 
 137 | (defvar lua-process-buffer nil
 138 |   "Buffer used for communication with Lua subprocess")
 139 | 
 140 | (defvar lua-mode-map nil
 141 |   "Keymap used with lua-mode.")
 142 | 
 143 | (defvar lua-electric-flag t
 144 |   "If t, electric actions (like automatic reindentation) will happen when an electric
 145 |  key like `{' is pressed")
 146 | (make-variable-buffer-local 'lua-electric-flag)
 147 | 
 148 | (defcustom lua-prefix-key "\C-c"
 149 |   "Prefix for all lua-mode commands."
 150 |   :type 'string
 151 |   :group 'lua)
 152 | 
 153 | (defcustom lua-prompt-regexp "[^\n]*\\(>[\t ]+\\)+$"
 154 |   "Regexp which matches the Lua program's prompt."
 155 |   :type  'regexp
 156 |   :group 'lua)
 157 | 
 158 | (defcustom lua-traceback-line-re
 159 |   "^\\(?:[\t ]*\\|.*>[\t ]+\\)\\([^\n\t ]+\\):\\([0-9]+\\):"
 160 |   "Regular expression that describes tracebacks and errors."
 161 |   :type 'regexp
 162 |   :group 'lua)
 163 | 
 164 | (defcustom lua-jump-on-traceback t
 165 |   "*Jump to innermost traceback location in *lua* buffer.  When this
 166 | variable is non-nil and a traceback occurs when running Lua code in a
 167 | subprocess, jump immediately to the source code of the innermost
 168 | traceback location."
 169 |   :type 'boolean
 170 |   :group 'lua)
 171 | 
 172 | (defvar lua-mode-hook nil
 173 |   "Hooks called when Lua mode fires up.")
 174 | 
 175 | (defvar lua-region-start (make-marker)
 176 |   "Start of special region for Lua communication.")
 177 | 
 178 | (defvar lua-region-end (make-marker)
 179 |   "End of special region for Lua communication.")
 180 | 
 181 | (defvar lua-mode-menu (make-sparse-keymap "Lua")
 182 |   "Keymap for lua-mode's menu.")
 183 | 
 184 | (defvar lua-emacs-menu
 185 |   '(["Restart With Whole File" lua-restart-with-whole-file t]
 186 |     ["Kill Process" lua-kill-process t]
 187 |     ["Hide Process Buffer" lua-hide-process-buffer t]
 188 |     ["Show Process Buffer" lua-show-process-buffer t]
 189 |     ["Beginning Of Proc" lua-beginning-of-proc t]
 190 |     ["End Of Proc" lua-end-of-proc t]
 191 |     ["Set Lua-Region Start" lua-set-lua-region-start t]
 192 |     ["Set Lua-Region End" lua-set-lua-region-end t]
 193 |     ["Send Lua-Region" lua-send-lua-region t]
 194 |     ["Send Current Line" lua-send-current-line t]
 195 |     ["Send Region" lua-send-region t]
 196 |     ["Send Proc" lua-send-proc t]
 197 |     ["Send Buffer" lua-send-buffer t]
 198 |     ["Search Documentation" lua-search-documentation t])
 199 |   "Emacs menu for Lua mode.")
 200 | 
 201 | (defvar lua-font-lock-keywords
 202 |   (eval-when-compile
 203 |     (list
 204 |      ;; Handle variable names
 205 |      ;;  local blalba =
 206 |      ;;        ^^^^^^
 207 |      '("\\(local[ \t]+\\(\\sw+\\)[ \t]*=\\)"
 208 |        (2 font-lock-variable-name-face))
 209 | 
 210 |      ;; Function name declarations.
 211 |      '("^[ \t]*\\_<\\(\\(local[ \t]+\\)?function\\)\\_>[ \t]+\\(\\(\\sw:\\|\\sw\\.\\|\\sw_\\|\\sw\\)+\\)"
 212 |        (1 font-lock-keyword-face) (3 font-lock-function-name-face nil t))
 213 | 
 214 |      ;; Handle function names in assignments
 215 |      '("\\(\\(\\sw:\\|\\sw\\.\\|\\sw_\\|\\sw\\)+\\)[ \t]*=[ \t]*\\(function\\)\\_>"
 216 |        (1 font-lock-function-name-face nil t) (3 font-lock-keyword-face))
 217 | 
 218 |      ;; Multi-line string literals.
 219 |      '("[^-]\\[=*\\[\\(\\([^]]\\|][^]]\\|]=+[^]]\\)*?\\)]=*]"
 220 |        (1 font-lock-string-face t))
 221 | 
 222 |      ;; Keywords.
 223 |      (concat "\\_<"
 224 |              (regexp-opt '("and" "break" "do" "else" "elseif" "end" "false"
 225 |                            "for" "function" "if" "in" "local" "nil" "not"
 226 |                            "or" "repeat" "return" "then" "true" "until"
 227 |                            "while") t)
 228 |              "\\_>")
 229 | 
 230 |      "Default expressions to highlight in Lua mode.")))
 231 | 
 232 | (defvar lua-imenu-generic-expression
 233 |   '((nil "^[ \t]*\\(?:local[ \t]+\\)?function[ \t]+\\(\\(\\sw:\\|\\sw_\\|\\sw\\.\\|\\sw\\)+\\)" 1))
 234 |   "Imenu generic expression for lua-mode.  See `imenu-generic-expression'.")
 235 | 
 236 | (defvar lua-mode-abbrev-table nil
 237 |   "Abbreviation table used in lua-mode buffers.")
 238 | 
 239 | (defvar lua-sexp-alist '(("then" . "end")
 240 |                          ("function" . "end")
 241 |                          ("do" . "end")))
 242 | 
 243 | (define-abbrev-table 'lua-mode-abbrev-table
 244 |   '(
 245 |     ("end" "end" lua-indent-line 0)
 246 |     ("else" "else" lua-indent-line 0)
 247 |     ("elseif" "elseif" lua-indent-line 0)
 248 |     ))
 249 | 
 250 | (defconst lua-indent-whitespace " \t"
 251 |   "Character set that constitutes whitespace for indentation in lua.")
 252 | 
 253 | (eval-and-compile
 254 |   (defalias 'lua-make-temp-file
 255 |     (if (fboundp 'make-temp-file)
 256 |         'make-temp-file
 257 |       (lambda (prefix &optional dir-flag) ;; Simple implementation
 258 |         (expand-file-name
 259 |          (make-temp-name prefix)
 260 |          (if (fboundp 'temp-directory)
 261 |              (temp-directory)
 262 |            temporary-file-directory))))))
 263 | 
 264 | ;;;###autoload
 265 | (defun lua-mode ()
 266 |   "Major mode for editing Lua code.
 267 | The following keys are bound:
 268 | \\{lua-mode-map}
 269 | "
 270 |   (interactive)
 271 |   (let ((switches nil)
 272 |         s)
 273 |     (kill-all-local-variables)
 274 |     (setq major-mode 'lua-mode)
 275 |     (setq mode-name "Lua")
 276 |     (setq comint-prompt-regexp lua-prompt-regexp)
 277 |     (make-local-variable 'lua-default-command-switches)
 278 |     (set (make-local-variable 'indent-line-function) 'lua-indent-line)
 279 |     (set (make-local-variable 'comment-start) lua-comment-start)
 280 |     (set (make-local-variable 'comment-start-skip) lua-comment-start-skip)
 281 |     (set (make-local-variable 'font-lock-defaults)
 282 |          '(lua-font-lock-keywords
 283 |            nil nil ((?_ . "w"))))
 284 |     (set (make-local-variable 'imenu-generic-expression)
 285 |          lua-imenu-generic-expression)
 286 |     (setq local-abbrev-table lua-mode-abbrev-table)
 287 |     (abbrev-mode 1)
 288 |     (make-local-variable 'lua-default-eval)
 289 |     (or lua-mode-map
 290 |         (lua-setup-keymap))
 291 |     (use-local-map lua-mode-map)
 292 |     (set-syntax-table (copy-syntax-table))
 293 |     (modify-syntax-entry ?+ ".")
 294 |     (modify-syntax-entry ?- ". 12")
 295 |     (modify-syntax-entry ?* ".")
 296 |     (modify-syntax-entry ?/ ".")
 297 |     (modify-syntax-entry ?^ ".")
 298 |     ;; This might be better as punctuation, as for C, but this way you
 299 |     ;; can treat table index as symbol.
 300 |     (modify-syntax-entry ?. "_")	; e.g. `io.string'
 301 |     (modify-syntax-entry ?> ".")
 302 |     (modify-syntax-entry ?< ".")
 303 |     (modify-syntax-entry ?= ".")
 304 |     (modify-syntax-entry ?~ ".")
 305 |     (modify-syntax-entry ?\n ">")
 306 |     (modify-syntax-entry ?\' "\"")
 307 |     (modify-syntax-entry ?\" "\"")
 308 |     (if (and (featurep 'menubar)
 309 |              current-menubar
 310 |              (not (assoc "Lua" current-menubar)))
 311 |         (progn
 312 |           (set-buffer-menubar (copy-sequence current-menubar))
 313 |           (add-menu nil "Lua" lua-emacs-menu)))
 314 |     ;; Append Lua menu to popup menu for Emacs.
 315 |     (if (boundp 'mode-popup-menu)
 316 |         (setq mode-popup-menu
 317 |               (cons (concat mode-name " Mode Commands") lua-emacs-menu)))
 318 | 
 319 |     ;; hideshow setup
 320 |     (unless (assq 'lua-mode hs-special-modes-alist)
 321 |       (add-to-list 'hs-special-modes-alist
 322 |                    `(lua-mode
 323 |                      ,(regexp-opt (mapcar 'car lua-sexp-alist) 'words) ;start
 324 |                      ,(regexp-opt (mapcar 'cdr lua-sexp-alist) 'words) ;end
 325 |                      nil lua-forward-sexp)))
 326 |     (run-hooks 'lua-mode-hook)))
 327 | 
 328 | ;;;###autoload
 329 | (add-to-list 'auto-mode-alist '("\\.lua$" . lua-mode))
 330 | 
 331 | (defun lua-setup-keymap ()
 332 |   "Set up keymap for Lua mode.
 333 | If the variable `lua-prefix-key' is nil, the bindings go directly
 334 | to `lua-mode-map', otherwise they are prefixed with `lua-prefix-key'."
 335 |   (setq lua-mode-map (make-sparse-keymap))
 336 |   (define-key lua-mode-map [menu-bar lua-mode]
 337 |     (cons "Lua" lua-mode-menu))
 338 |   (define-key lua-mode-map "}" 'lua-electric-match)
 339 |   (define-key lua-mode-map "]" 'lua-electric-match)
 340 |   (define-key lua-mode-map ")" 'lua-electric-match)
 341 |   (define-key lua-mode-map (kbd "C-M-a") 'lua-beginning-of-proc)
 342 |   (define-key lua-mode-map (kbd "C-M-e") 'lua-end-of-proc)
 343 |   (define-key lua-mode-map (kbd "C-M-") 'lua-beginning-of-proc)
 344 |   (define-key lua-mode-map (kbd "C-M-") 'lua-end-of-proc)
 345 |   (let ((map (if lua-prefix-key
 346 |                  (make-sparse-keymap)
 347 |                lua-mode-map)))
 348 | 
 349 |     ;; communication
 350 |     (define-key map "\C-l" 'lua-send-buffer)
 351 |     (define-key map "\C-f" 'lua-search-documentation)
 352 |     (if lua-prefix-key
 353 |         (define-key lua-mode-map lua-prefix-key map))
 354 |     ))
 355 | 
 356 | (defun lua-electric-match (arg)
 357 |   "Insert character and adjust indentation."
 358 |   (interactive "P")
 359 |   (insert-char last-command-char (prefix-numeric-value arg))
 360 |   (if lua-electric-flag
 361 |       (lua-indent-line))
 362 |   (blink-matching-open))
 363 | 
 364 | ;; private functions
 365 | (defun lua-syntax-status ()
 366 |   "Returns the syntactic status of the character after the point."
 367 |   (parse-partial-sexp (save-excursion (beginning-of-line) (point))
 368 |                       (point)))
 369 | 
 370 | 
 371 | (defun lua-string-p ()
 372 |   "Returns true if the point is in a string."
 373 |   (elt (lua-syntax-status) 3))
 374 | 
 375 | (defun lua-comment-p ()
 376 |   "Returns true if the point is in a comment."
 377 |   (elt (lua-syntax-status) 4))
 378 | 
 379 | (defun lua-comment-or-string-p ()
 380 |   "Returns true if the point is in a comment or string."
 381 |   (let ((parse-result (lua-syntax-status)))
 382 |     (or (elt parse-result 3) (elt parse-result 4))))
 383 | 
 384 | (defun lua-indent-line ()
 385 |   "Indent current line for Lua mode.
 386 | Return the amount the indentation changed by."
 387 |   (let ((indent (max 0 (- (lua-calculate-indentation nil)
 388 |                           (lua-calculate-indentation-left-shift))))
 389 |         beg shift-amt
 390 |         (case-fold-search nil)
 391 |         (pos (- (point-max) (point))))
 392 |     (beginning-of-line)
 393 |     (setq beg (point))
 394 |     (skip-chars-forward lua-indent-whitespace)
 395 |     (setq shift-amt (- indent (current-column)))
 396 |     (when (not (zerop shift-amt))
 397 |       (delete-region beg (point))
 398 |       (indent-to indent))
 399 |     ;; If initial point was within line's indentation,
 400 |     ;; position after the indentation.  Else stay at same point in text.
 401 |     (if (> (- (point-max) pos) (point))
 402 |         (goto-char (- (point-max) pos)))
 403 |     shift-amt
 404 |     indent))
 405 | 
 406 | (defun lua-find-regexp (direction regexp &optional limit ignore-p)
 407 |   "Searches for a regular expression in the direction specified.
 408 | Direction is one of 'forward and 'backward.
 409 | By default, matches in comments and strings are ignored, but what to ignore is
 410 | configurable by specifying ignore-p. If the regexp is found, returns point
 411 | position, nil otherwise.
 412 | ignore-p returns true if the match at the current point position should be
 413 | ignored, nil otherwise."
 414 |   (let ((ignore-func (or ignore-p 'lua-comment-or-string-p))
 415 |         (search-func (if (eq direction 'forward)
 416 |                          're-search-forward 're-search-backward))
 417 |         (case-fold-search nil))
 418 |     (catch 'found
 419 |       (while (funcall search-func regexp limit t)
 420 |         (if (not (funcall ignore-func))
 421 |             (throw 'found (point)))))))
 422 | 
 423 | (defun lua-backwards-to-block-begin-or-end ()
 424 |   "Move backwards to nearest block begin or end.  Returns nil if not successful."
 425 |   (interactive)
 426 |   (lua-find-regexp 'backward lua-block-regexp))
 427 | 
 428 | (defconst lua-block-regexp
 429 |   (eval-when-compile
 430 |     (concat
 431 |      "\\(\\_<"
 432 |      (regexp-opt '("do" "function" "repeat" "then"
 433 |                    "else" "elseif" "end" "until") t)
 434 |      "\\_>\\)\\|"
 435 |      (regexp-opt '("{" "(" "[" "]" ")" "}") t))
 436 | 
 437 |     ))
 438 | 
 439 | (defconst lua-block-token-alist
 440 |   ;; The absence of "else" is deliberate. This construct in a way both
 441 |   ;; opens and closes a block. As a result, it is difficult to handle
 442 |   ;; cleanly. It is also ambiguous - if we are looking for the match
 443 |   ;; of "else", should we look backward for "then/elseif" or forward
 444 |   ;; for "end"?
 445 |   ;; Maybe later we will find a way to handle it.
 446 |   '(("do"       "\\_"                                 open)
 447 |     ("function" "\\_"                                 open)
 448 |     ("repeat"   "\\_"                               open)
 449 |     ("then"     "\\_<\\(e\\(lseif\\|nd\\)\\)\\_>"             open)
 450 |     ("{"        "}"                                           open)
 451 |     ("["        "]"                                           open)
 452 |     ("("        ")"                                           open)
 453 |     ("elseif"   "\\_"                                close)
 454 |     ("end"      "\\_<\\(do\\|function\\|then\\)\\_>"          close)
 455 |     ("until"    "\\_"                              close)
 456 |     ("}"        "{"                                           close)
 457 |     ("]"        "\\["                                         close)
 458 |     (")"        "("                                           close)))
 459 | 
 460 | 
 461 | (defconst lua-indentation-modifier-regexp
 462 |   ;; The absence of else is deliberate, since it does not modify the
 463 |   ;; indentation level per se. It only may cause the line, in which the
 464 |   ;; else is, to be shifted to the left.
 465 |   (concat
 466 |    "\\(\\_<"
 467 |    ;; n.b. "local function" is a bit of a hack, allowing only a single space
 468 |    (regexp-opt '("do" "local function" "function" "repeat" "then") t)
 469 |    "\\_>\\|"
 470 |    (regexp-opt '("{" "(" "["))
 471 |    "\\)\\|\\(\\_<"
 472 |    (regexp-opt '("elseif" "end" "until") t)
 473 |    "\\_>\\|"
 474 |    (regexp-opt '("]" ")" "}"))
 475 |    "\\)")
 476 | 
 477 |   )
 478 | 
 479 | (defun lua-find-matching-token-word (token search-start)
 480 |   (let* ((token-info (assoc token lua-block-token-alist))
 481 |          (match (car (cdr token-info)))
 482 |          (match-type (car (cdr (cdr token-info))))
 483 |          (search-direction (if (eq match-type 'open) 'forward 'backward)))
 484 |     ;; if we are searching forward from the token at the current point
 485 |     ;; (i.e. for a closing token), need to step one character forward
 486 |     ;; first, or the regexp will match the opening token.
 487 |     (if (eq match-type 'open) (forward-char 1))
 488 |     (if search-start (goto-char search-start))
 489 |     (catch 'found
 490 |       (while (lua-find-regexp search-direction lua-indentation-modifier-regexp)
 491 |         ;; have we found a valid matching token?
 492 |         (let ((found-token (match-string 0))
 493 |               (found-pos (match-beginning 0)))
 494 |           (if (string-match match found-token)
 495 |               (throw 'found found-pos))
 496 |           ;; no - then there is a nested block. If we were looking for
 497 |           ;; a block begin token, found-token must be a block end
 498 |           ;; token; likewise, if we were looking for a block end token,
 499 |           ;; found-token must be a block begin token, otherwise there
 500 |           ;; is a grammatical error in the code.
 501 |           (if (not (and
 502 |                     (eq (car (cdr (cdr (assoc found-token lua-block-token-alist))))
 503 |                         match-type)
 504 |                     (lua-find-matching-token-word found-token nil)))
 505 |               (throw 'found nil)))))))
 506 | 
 507 | (defun lua-goto-matching-block-token (&optional search-start parse-start)
 508 |   "Find block begion/end token matching the one at the point.
 509 | This function moves the point to the token that matches the one
 510 | at the current point. Returns the point position of the first character of
 511 | the matching token if successful, nil otherwise."
 512 |   (if parse-start (goto-char parse-start))
 513 |   (let ((case-fold-search nil))
 514 |     (if (looking-at lua-indentation-modifier-regexp)
 515 |         (let ((position (lua-find-matching-token-word (match-string 0)
 516 |                                                       search-start)))
 517 |           (and position
 518 |                (goto-char position))))))
 519 | 
 520 | (defun lua-goto-matching-block (&optional noreport)
 521 |   "Go to the keyword balancing the one under the point.
 522 | If the point is on a keyword/brace that starts a block, go to the
 523 | matching keyword that ends the block, and vice versa."
 524 |   (interactive)
 525 |   ;; search backward to the beginning of the keyword if necessary
 526 |   (if (eq (char-syntax (following-char)) ?w)
 527 |       (re-search-backward "\\_<" nil t))
 528 |   (let ((position (lua-goto-matching-block-token)))
 529 |     (if (and (not position)
 530 |              (not noreport))
 531 |         (error "Not on a block control keyword or brace.")
 532 |       position)))
 533 | 
 534 | (defun lua-goto-nonblank-previous-line ()
 535 |   "Puts the point at the first previous line that is not blank.
 536 | Returns the point, or nil if it reached the beginning of the buffer"
 537 |   (catch 'found
 538 |     (beginning-of-line)
 539 |     (while t
 540 |       (if (bobp) (throw 'found nil))
 541 |       (forward-char -1)
 542 |       (beginning-of-line)
 543 |       (if (not (looking-at "\\s *\\(--.*\\)?$")) (throw 'found (point))))))
 544 | 
 545 | (defun lua-goto-nonblank-next-line ()
 546 |   "Puts the point at the first next line that is not blank.
 547 | Returns the point, or nil if it reached the end of the buffer"
 548 |   (catch 'found
 549 |     (end-of-line)
 550 |     (while t
 551 |       (forward-line)
 552 |       (if (eobp) (throw 'found nil))
 553 |       (beginning-of-line)
 554 |       (if (not (looking-at "\\s *\\(--.*\\)?$")) (throw 'found (point))))))
 555 | 
 556 | (eval-when-compile
 557 |   (defconst lua-operator-class
 558 |     "-+*/^.=<>~"))
 559 | 
 560 | (defconst lua-cont-eol-regexp
 561 |   (eval-when-compile
 562 |     (concat
 563 |      "\\(\\_<"
 564 |      (regexp-opt '("and" "or" "not" "in" "for" "while"
 565 |                    "local" "function") t)
 566 |      "\\_>\\|"
 567 |      "\\(^\\|[^" lua-operator-class "]\\)"
 568 |      (regexp-opt '("+" "-" "*" "/" "^" ".." "==" "=" "<" ">" "<=" ">=" "~=") t)
 569 |      "\\)"
 570 |      "\\s *\\=")
 571 |     ))
 572 | 
 573 | 
 574 | (defconst lua-cont-bol-regexp
 575 |   (eval-when-compile
 576 |     (concat
 577 |      "\\=\\s *"
 578 |      "\\(\\_<"
 579 |      (regexp-opt '("and" "or" "not") t)
 580 |      "\\_>\\|"
 581 |      (regexp-opt '("+" "-" "*" "/" "^" ".." "==" "=" "<" ">" "<=" ">=" "~=") t)
 582 |      "\\($\\|[^" lua-operator-class "]\\)"
 583 |      "\\)")
 584 | 
 585 |     ))
 586 | 
 587 | (defun lua-last-token-continues-p ()
 588 |   "Returns true if the last token on this line is a continuation token."
 589 |   (let (line-begin
 590 |         line-end)
 591 |     (save-excursion
 592 |       (beginning-of-line)
 593 |       (setq line-begin (point))
 594 |       (end-of-line)
 595 |       (setq line-end (point))
 596 |       ;; we need to check whether the line ends in a comment and
 597 |       ;; skip that one.
 598 |       (while (lua-find-regexp 'backward "-" line-begin 'lua-string-p)
 599 |         (if (looking-at "--")
 600 |             (setq line-end (point))))
 601 |       (goto-char line-end)
 602 |       (re-search-backward lua-cont-eol-regexp line-begin t))))
 603 | 
 604 | (defun lua-first-token-continues-p ()
 605 |   "Returns true if the first token on this line is a continuation token."
 606 |   (let (line-end)
 607 |     (save-excursion
 608 |       (end-of-line)
 609 |       (setq line-end (point))
 610 |       (beginning-of-line)
 611 |       (re-search-forward lua-cont-bol-regexp line-end t))))
 612 | 
 613 | (defun lua-is-continuing-statement-p (&optional parse-start)
 614 |   "Return non-nil if the line continues a statement.
 615 | More specifically, return the point in the line that is continued.
 616 | The criteria for a continuing statement are:
 617 | 
 618 | * the last token of the previous line is a continuing op,
 619 |   OR the first token of the current line is a continuing op
 620 | 
 621 | "
 622 |   (let ((prev-line nil))
 623 |     (save-excursion
 624 |       (if parse-start (goto-char parse-start))
 625 |       (save-excursion (setq prev-line (lua-goto-nonblank-previous-line)))
 626 |       (and prev-line
 627 |            (or (lua-first-token-continues-p)
 628 |                (and (goto-char prev-line)
 629 |                     ;; check last token of previous nonblank line
 630 |                     (lua-last-token-continues-p)))))))
 631 | 
 632 | (defun lua-make-indentation-info-pair ()
 633 |   "This is a helper function to lua-calculate-indentation-info. Don't
 634 | use standalone."
 635 |   (cond ((string-equal found-token "function")
 636 |          ;; this is the location where we need to start searching for the
 637 |          ;; matching opening token, when we encounter the next closing token.
 638 |          ;; It is primarily an optimization to save some searching time.
 639 |          (cons 'absolute (+ (save-excursion (goto-char found-pos)
 640 |                                             (current-column))
 641 |                             lua-indent-level)))
 642 |         ((or (string-equal found-token "{")
 643 |              (string-equal found-token "("))
 644 |          (save-excursion
 645 |            ;; expression follows -> indent at start of next expression
 646 |            (if (and (not (search-forward-regexp "[[:space:]]--" (line-end-position) t))
 647 |                     (search-forward-regexp "[^[:space:]]" (line-end-position) t))
 648 |                (cons 'absolute (1- (current-column)))
 649 |              (cons 'relative lua-indent-level))))
 650 |         ;; closing tokens follow
 651 |         ((string-equal found-token "end")
 652 |          (save-excursion
 653 |            (lua-goto-matching-block-token nil found-pos)
 654 |            (if (looking-at "\\_")
 655 |                (cons 'absolute
 656 |                      (+ (current-indentation)
 657 |                         (lua-calculate-indentation-block-modifier
 658 |                          nil (point))))
 659 |              (cons 'relative (- lua-indent-level)))))
 660 |         ((or (string-equal found-token ")")
 661 |              (string-equal found-token "}"))
 662 |          (save-excursion
 663 |            (lua-goto-matching-block-token nil found-pos)
 664 |            (cons 'absolute
 665 |                  (+ (current-indentation)
 666 |                     (lua-calculate-indentation-block-modifier
 667 |                      nil (point))))))
 668 |         (t
 669 |          (cons 'relative (if (nth 2 (match-data))
 670 |                              ;; beginning of a block matched
 671 |                              lua-indent-level
 672 |                            ;; end of a block matched
 673 |                            (- lua-indent-level))))))
 674 | 
 675 | 
 676 | (defun lua-calculate-indentation-info (&optional parse-start parse-end)
 677 |   "For each block token on the line, computes how it affects the indentation.
 678 | The effect of each token can be either a shift relative to the current
 679 | indentation level, or indentation to some absolute column. This information
 680 | is collected in a list of indentation info pairs, which denote absolute
 681 | and relative each, and the shift/column to indent to."
 682 |   (let* ((line-end (save-excursion (end-of-line) (point)))
 683 |          (search-stop (if parse-end (min parse-end line-end) line-end))
 684 |          (indentation-info nil))
 685 |     (if parse-start (goto-char parse-start))
 686 |     (save-excursion
 687 |       (beginning-of-line)
 688 |       (while (lua-find-regexp 'forward lua-indentation-modifier-regexp
 689 |                               search-stop)
 690 |         (let ((found-token (match-string 0))
 691 |               (found-pos (match-beginning 0))
 692 |               (found-end (match-end 0))
 693 |               (data (match-data)))
 694 |           (setq indentation-info
 695 |                 (cons (lua-make-indentation-info-pair) indentation-info)))))
 696 |     indentation-info))
 697 | 
 698 | (defun lua-accumulate-indentation-info (info)
 699 |   "Accumulates the indentation information previously calculated by
 700 | lua-calculate-indentation-info. Returns either the relative indentation
 701 | shift, or the absolute column to indent to."
 702 |   (let ((info-list (reverse info))
 703 |         (type 'relative)
 704 |         (accu 0))
 705 |     (mapcar (lambda (x)
 706 |               (setq accu (if (eq 'absolute (car x))
 707 |                              (progn (setq type 'absolute)
 708 |                                     (cdr x))
 709 |                            (+ accu (cdr x)))))
 710 |             info-list)
 711 |     (cons type accu)))
 712 | 
 713 | (defun lua-calculate-indentation-block-modifier (&optional parse-start
 714 |                                                            parse-end)
 715 |   "Return amount by which this line modifies the indentation.
 716 | Beginnings of blocks add lua-indent-level once each, and endings
 717 | of blocks subtract lua-indent-level once each. This function is used
 718 | to determine how the indentation of the following line relates to this
 719 | one."
 720 |   (if parse-start (goto-char parse-start))
 721 |   (let ((case-fold-search nil)
 722 |         (indentation-info (lua-accumulate-indentation-info
 723 |                            (lua-calculate-indentation-info nil parse-end))))
 724 |     (if (eq (car indentation-info) 'absolute)
 725 |         (- (cdr indentation-info)
 726 |            (current-indentation)
 727 |            ;; reduce indentation if this line also starts new continued statement
 728 |            ;; or next line cont. this line
 729 |            ;;This is for aesthetic reasons: the indentation should be
 730 |            ;;dosomething(d +
 731 |            ;;   e + f + g)
 732 |            ;;not
 733 |            ;;dosomething(d +
 734 |            ;;      e + f + g)"
 735 |            (save-excursion
 736 |              (or (and (lua-last-token-continues-p) lua-indent-level)
 737 |                  (and (lua-goto-nonblank-next-line) (lua-first-token-continues-p) lua-indent-level)
 738 |                  0)))
 739 |       (+ (lua-calculate-indentation-left-shift)
 740 |          (cdr indentation-info)
 741 |          (if (lua-is-continuing-statement-p) (- lua-indent-level) 0)))))
 742 | 
 743 | (defconst lua-left-shift-regexp-1
 744 |   (concat "\\("
 745 |           "\\(\\_<" (regexp-opt '("else" "elseif" "until") t)
 746 |           "\\_>\\)\\($\\|\\s +\\)"
 747 |           "\\)"))
 748 | 
 749 | (defconst lua-left-shift-regexp-2
 750 |   (concat "\\(\\_<"
 751 |           (regexp-opt '("end") t)
 752 |           "\\_>\\)"))
 753 | 
 754 | (defconst lua-left-shift-regexp
 755 |   ;; "else", "elseif", "until" followed by whitespace, or "end"/closing
 756 |   ;; brackets followed by
 757 |   ;; whitespace, punctuation, or closing parentheses
 758 |   (concat lua-left-shift-regexp-1
 759 |           "\\|\\(\\("
 760 |           lua-left-shift-regexp-2
 761 |           "\\|\\("
 762 |           (regexp-opt '("]" "}" ")"))
 763 |           "\\)\\)\\($\\|\\(\\s \\|\\s.\\)*\\)"
 764 |           "\\)"))
 765 | 
 766 | (defconst lua-left-shift-pos-1
 767 |   2)
 768 | 
 769 | (defconst lua-left-shift-pos-2
 770 |   (+ 3 (regexp-opt-depth lua-left-shift-regexp-1)))
 771 | 
 772 | (defconst lua-left-shift-pos-3
 773 |   (+ lua-left-shift-pos-2
 774 |      (regexp-opt-depth lua-left-shift-regexp-2)))
 775 | 
 776 | (defun lua-calculate-indentation-left-shift (&optional parse-start)
 777 |   "Return amount, by which this line should be shifted left.
 778 | Look for an uninterrupted sequence of block-closing tokens that starts
 779 | at the beginning of the line. For each of these tokens, shift indentation
 780 | to the left by the amount specified in lua-indent-level."
 781 |   (let (line-begin
 782 |         (indentation-modifier 0)
 783 |         (case-fold-search nil)
 784 |         (block-token nil))
 785 |     (save-excursion
 786 |       (if parse-start (goto-char parse-start))
 787 |       (beginning-of-line)
 788 |       (setq line-begin (point))
 789 |       ;; Look for the block-closing token sequence
 790 |       (skip-chars-forward lua-indent-whitespace)
 791 |       (catch 'stop
 792 |         (while (and (looking-at lua-left-shift-regexp)
 793 |                     (not (lua-comment-or-string-p)))
 794 |           (let ((last-token (or (match-string lua-left-shift-pos-1)
 795 |                                 (match-string lua-left-shift-pos-2)
 796 |                                 (match-string lua-left-shift-pos-3))))
 797 |             (if (not block-token) (setq block-token last-token))
 798 |             (if (not (string-equal block-token last-token)) (throw 'stop nil))
 799 |             (setq indentation-modifier (+ indentation-modifier
 800 |                                           lua-indent-level))
 801 |             (forward-char (length (match-string 0))))))
 802 |       indentation-modifier)))
 803 | 
 804 | (defun lua-calculate-indentation (&optional parse-start)
 805 |   "Return appropriate indentation for current line as Lua code.
 806 | In usual case returns an integer: the column to indent to."
 807 |   (let ((pos (point))
 808 |         shift-amt)
 809 |     (save-excursion
 810 |       (if parse-start (setq pos (goto-char parse-start)))
 811 |       (beginning-of-line)
 812 |       (setq shift-amt (if (lua-is-continuing-statement-p) lua-indent-level 0))
 813 |       (if (bobp)          ; If we're at the beginning of the buffer, no change.
 814 |           (+ (current-indentation) shift-amt)
 815 |         ;; This code here searches backwards for a "block beginning/end"
 816 |         ;; It snarfs the indentation of that, plus whatever amount the
 817 |         ;; line was shifted left by, because of block end tokens. It
 818 |         ;; then adds the indentation modifier of that line to obtain the
 819 |         ;; final level of indentation.
 820 |         ;; Finally, if this line continues a statement from the
 821 |         ;; previous line, add another level of indentation.
 822 |         (if (lua-backwards-to-block-begin-or-end)
 823 |             ;; now we're at the line with block beginning or end.
 824 |             (max (+ (current-indentation)
 825 |                     (lua-calculate-indentation-block-modifier)
 826 |                     shift-amt)
 827 |                  0)
 828 |           ;; Failed to find a block begin/end.
 829 |           ;; Just use the previous line's indent.
 830 |           (goto-char pos)
 831 |           (beginning-of-line)
 832 |           (forward-line -1)
 833 |           (+ (current-indentation) shift-amt))))))
 834 | 
 835 | (defun lua-beginning-of-proc (&optional arg)
 836 |   "Move backward to the beginning of a lua proc (or similar).
 837 | With argument, do it that many times.  Negative arg -N
 838 | means move forward to Nth following beginning of proc.
 839 | Returns t unless search stops due to beginning or end of buffer."
 840 |   (interactive "P")
 841 |   (or arg
 842 |       (setq arg 1))
 843 |   (let ((found nil)
 844 |         (ret t))
 845 |     (while (< arg 0)
 846 |       (if (re-search-forward "^function[ \t]" nil t)
 847 |           (setq arg (1+ arg)
 848 |                 found t)
 849 |         (setq ret nil
 850 |               arg 0)))
 851 |     (if found
 852 |         (beginning-of-line))
 853 |     (if (> arg 0)
 854 |         (if (re-search-forward "^function[ \t]" nil t)
 855 |             (setq arg (1+ arg))
 856 |           (goto-char (point-max))))
 857 |     (while (> arg 0)
 858 |       (if (re-search-backward "^function[ \t]" nil t)
 859 |           (setq arg (1- arg))
 860 |         (setq ret nil
 861 |               arg 0)))
 862 |     ret))
 863 | 
 864 | (defun lua-end-of-proc (&optional arg)
 865 |   "Move forward to next end of lua proc (or similar).
 866 | With argument, do it that many times.  Negative argument -N means move
 867 | back to Nth preceding end of proc.
 868 | 
 869 | This function just searches for a `end' at the beginning of a line."
 870 |   (interactive "P")
 871 |   (or arg
 872 |       (setq arg 1))
 873 |   (let ((found nil)
 874 |         (ret t))
 875 |     (if (and (< arg 0)
 876 |              (not (bolp))
 877 |              (save-excursion
 878 |                (beginning-of-line)
 879 |                (eq (following-char) ?})))
 880 |         (forward-char -1))
 881 |     (while (> arg 0)
 882 |       (if (re-search-forward "^end" nil t)
 883 |           (setq arg (1- arg)
 884 |                 found t)
 885 |         (setq ret nil
 886 |               arg 0)))
 887 |     (while (< arg 0)
 888 |       (if (re-search-backward "^end" nil t)
 889 |           (setq arg (1+ arg)
 890 |                 found t)
 891 |         (setq ret nil
 892 |               arg 0)))
 893 |     (if found
 894 |         (progn
 895 |           (beginning-of-line)
 896 |           (forward-line)))
 897 |     ret))
 898 | 
 899 | (defun lua-start-process (name &optional program startfile &rest switches)
 900 |   "Start a lua process named NAME, running PROGRAM."
 901 |   (or switches
 902 |       (setq switches lua-default-command-switches))
 903 |   (setq program (or program name))
 904 |   (setq lua-process-buffer (apply 'make-comint name program startfile switches))
 905 |   (setq lua-process (get-buffer-process lua-process-buffer))
 906 |   ;; wait for prompt
 907 |   (with-current-buffer lua-process-buffer
 908 |     (while (not (lua-prompt-line))
 909 |       (accept-process-output (get-buffer-process (current-buffer)))
 910 |       (goto-char (point-max)))))
 911 | 
 912 | (defun lua-kill-process ()
 913 |   "Kill lua subprocess and its buffer."
 914 |   (interactive)
 915 |   (if lua-process-buffer
 916 |       (kill-buffer lua-process-buffer)))
 917 | 
 918 | (defun lua-set-lua-region-start (&optional arg)
 919 |   "Set start of region for use with `lua-send-lua-region'."
 920 |   (interactive)
 921 |   (set-marker lua-region-start (or arg (point))))
 922 | 
 923 | (defun lua-set-lua-region-end (&optional arg)
 924 |   "Set end of region for use with `lua-send-lua-region'."
 925 |   (interactive)
 926 |   (set-marker lua-region-end (or arg (point))))
 927 | 
 928 | (defun lua-send-current-line ()
 929 |   "Send current line to lua subprocess, found in `lua-process'.
 930 | If `lua-process' is nil or dead, start a new process first."
 931 |   (interactive)
 932 |   (let ((start (save-excursion (beginning-of-line) (point)))
 933 |         (end (save-excursion (end-of-line) (point))))
 934 |     (lua-send-region start end)))
 935 | 
 936 | (defun lua-send-region (start end)
 937 |   "Send region to lua subprocess."
 938 |   (interactive "r")
 939 |   ;; make temporary lua file
 940 |   (let ((tempfile (lua-make-temp-file "lua-"))
 941 |         (last-prompt nil)
 942 |         (prompt-found nil)
 943 |         (lua-stdin-line-offset (count-lines (point-min) start))
 944 |         (lua-stdin-buffer (current-buffer))
 945 |         current-prompt )
 946 |     (write-region start end tempfile)
 947 |     (or (and lua-process
 948 |              (comint-check-proc lua-process-buffer))
 949 |         (lua-start-process lua-default-application))
 950 |     ;; kill lua process without query
 951 |     (if (fboundp 'process-kill-without-query)
 952 |         (process-kill-without-query lua-process))
 953 |     ;; send dofile(tempfile)
 954 |     (with-current-buffer lua-process-buffer
 955 |       (goto-char (point-max))
 956 |       (setq last-prompt (point-max))
 957 |       (comint-simple-send (get-buffer-process (current-buffer))
 958 |                           (format "dofile(\"%s\")"
 959 |                                   (replace-regexp-in-string "\\\\" "\\\\\\\\" tempfile)))
 960 |       ;; wait for prompt
 961 |       (while (not prompt-found)
 962 |         (accept-process-output (get-buffer-process (current-buffer)))
 963 |         (goto-char (point-max))
 964 |         (setq prompt-found (and (lua-prompt-line) (< last-prompt (point-max)))))
 965 |       ;; remove temp. lua file
 966 |       (delete-file tempfile)
 967 |       (lua-postprocess-output-buffer lua-process-buffer last-prompt lua-stdin-line-offset)
 968 |       (if lua-always-show
 969 |           (display-buffer lua-process-buffer)))))
 970 | 
 971 | (defun lua-postprocess-output-buffer (buf start &optional lua-stdin-line-offset)
 972 |   "Highlight tracebacks found in buf. If an traceback occurred return
 973 | t, otherwise return nil.  BUF must exist."
 974 |   (let ((lua-stdin-line-offset (or lua-stdin-line-offset 0))
 975 |         line file bol err-p)
 976 |     (save-excursion
 977 |       (set-buffer buf)
 978 |       (goto-char start)
 979 |       (beginning-of-line)
 980 |       (if (re-search-forward lua-traceback-line-re nil t)
 981 |           (setq file (match-string 1)
 982 |                 line (string-to-number (match-string 2)))))
 983 |     (when (and lua-jump-on-traceback line)
 984 |       (beep)
 985 |       ;; FIXME: highlight
 986 |       (lua-jump-to-traceback file line lua-stdin-line-offset)
 987 |       (setq err-p t))
 988 |     err-p))
 989 | 
 990 | (defun lua-jump-to-traceback (file line lua-stdin-line-offset)
 991 |   "Jump to the Lua code in FILE at LINE."
 992 |   ;; sanity check: temporary-file-directory
 993 |   (if (string= (substring file 0 3)  "...")
 994 |       (message "Lua traceback output truncated: customize 'temporary-file-directory' or increase 'LUA_IDSIZE' in 'luaconf.h'.")
 995 |     (let ((buffer (cond ((or (string-equal file tempfile) (string-equal file "stdin"))
 996 |                          (setq line (+ line lua-stdin-line-offset))
 997 |                          lua-stdin-buffer)
 998 |                         (t (find-file-noselect file)))))
 999 |       (pop-to-buffer buffer)
1000 |       ;; Force Lua mode
1001 |       (if (not (eq major-mode 'lua-mode))
1002 |           (lua-mode))
1003 |       ;; FIXME: fix offset when executing region
1004 |       (goto-line line)
1005 |       (message "Jumping to error in file %s on line %d" file line))))
1006 | 
1007 | (defun lua-prompt-line ()
1008 |   (save-excursion
1009 |     (save-match-data
1010 |       (forward-line 0)
1011 |       (if (looking-at comint-prompt-regexp)
1012 |           (match-end 0)))))
1013 | 
1014 | (defun lua-send-lua-region ()
1015 |   "Send preset lua region to lua subprocess."
1016 |   (interactive)
1017 |   (or (and lua-region-start lua-region-end)
1018 |       (error "lua-region not set"))
1019 |   (or (and lua-process
1020 |            (comint-check-proc lua-process-buffer))
1021 |       (lua-start-process lua-default-application))
1022 |   (comint-simple-send lua-process
1023 |                       (buffer-substring lua-region-start lua-region-end)
1024 |                       )
1025 |   (if lua-always-show
1026 |       (display-buffer lua-process-buffer)))
1027 | 
1028 | (defun lua-send-proc ()
1029 |   "Send proc around point to lua subprocess."
1030 |   (interactive)
1031 |   (let (beg end)
1032 |     (save-excursion
1033 |       (lua-beginning-of-proc)
1034 |       (setq beg (point))
1035 |       (lua-end-of-proc)
1036 |       (setq end (point)))
1037 |     (or (and lua-process
1038 |              (comint-check-proc lua-process-buffer))
1039 |         (lua-start-process lua-default-application))
1040 |     (comint-simple-send lua-process
1041 |                         (buffer-substring beg end))
1042 |     (if lua-always-show
1043 |         (display-buffer lua-process-buffer))))
1044 | 
1045 | ;; FIXME: This needs work... -Bret
1046 | (defun lua-send-buffer ()
1047 |   "Send whole buffer to lua subprocess."
1048 |   (interactive)
1049 |   (lua-send-region (point-min) (point-max)))
1050 | 
1051 | (defun lua-restart-with-whole-file ()
1052 |   "Restart lua subprocess and send whole file as input."
1053 |   (interactive)
1054 |   (lua-kill-process)
1055 |   (lua-start-process lua-default-application)
1056 |   (lua-send-buffer))
1057 | 
1058 | (defun lua-show-process-buffer ()
1059 |   "Make sure `lua-process-buffer' is being displayed."
1060 |   (interactive)
1061 |   (display-buffer lua-process-buffer))
1062 | 
1063 | (defun lua-hide-process-buffer ()
1064 |   "Delete all windows that display `lua-process-buffer'."
1065 |   (interactive)
1066 |   (delete-windows-on lua-process-buffer))
1067 | 
1068 | (defun lua-search-documentation ()
1069 |   "Search Lua documentation for the word at the point."
1070 |   (interactive)
1071 |   (browse-url (concat lua-search-url-prefix (current-word t))))
1072 | 
1073 | (defun lua-calculate-state (arg prevstate)
1074 |   ;; Calculate the new state of PREVSTATE, t or nil, based on arg. If
1075 |   ;; arg is nil or zero, toggle the state. If arg is negative, turn
1076 |   ;; the state off, and if arg is positive, turn the state on
1077 |   (if (or (not arg)
1078 |           (zerop (setq arg (prefix-numeric-value arg))))
1079 |       (not prevstate)
1080 |     (> arg 0)))
1081 | 
1082 | (defun lua-toggle-electric-state (&optional arg)
1083 |   "Toggle the electric indentation feature.
1084 | Optional numeric ARG, if supplied, turns on electric indentation when
1085 | positive, turns it off when negative, and just toggles it when zero or
1086 | left out."
1087 |   (interactive "P")
1088 |   (setq lua-electric-flag (lua-calculate-state arg lua-electric-flag)))
1089 | 
1090 | (defun lua-forward-sexp (&optional count)
1091 |   "Forward to block end"
1092 |   (interactive "p")
1093 |   (save-match-data
1094 |     (let* ((count (or count 1))
1095 |            (stackheight 0)
1096 |            (block-start (mapcar 'car lua-sexp-alist))
1097 |            (block-end (mapcar 'cdr lua-sexp-alist))
1098 |            (block-regex (regexp-opt (append  block-start block-end) 'words))
1099 |            current-exp
1100 |            )
1101 |       (while (> count 0)
1102 |         ;; skip whitespace
1103 |         (skip-chars-forward " \t\n")
1104 |         (if (looking-at (regexp-opt block-start 'words))
1105 |             (let ((keyword (match-string 1)))
1106 |               (lua-find-matching-token-word keyword nil))
1107 |           ;; If the current keyword is not a "begin" keyword, then just
1108 |           ;; perform the normal forward-sexp.
1109 |           (forward-sexp 1))
1110 |         (setq count (1- count))))))
1111 | 
1112 | 
1113 | ;; menu bar
1114 | 
1115 | (define-key lua-mode-menu [restart-with-whole-file]
1116 |   '("Restart With Whole File" .  lua-restart-with-whole-file))
1117 | (define-key lua-mode-menu [kill-process]
1118 |   '("Kill Process" . lua-kill-process))
1119 | 
1120 | (define-key lua-mode-menu [hide-process-buffer]
1121 |   '("Hide Process Buffer" . lua-hide-process-buffer))
1122 | (define-key lua-mode-menu [show-process-buffer]
1123 |   '("Show Process Buffer" . lua-show-process-buffer))
1124 | 
1125 | (define-key lua-mode-menu [end-of-proc]
1126 |   '("End Of Proc" . lua-end-of-proc))
1127 | (define-key lua-mode-menu [beginning-of-proc]
1128 |   '("Beginning Of Proc" . lua-beginning-of-proc))
1129 | 
1130 | (define-key lua-mode-menu [send-lua-region]
1131 |   '("Send Lua-Region" . lua-send-lua-region))
1132 | (define-key lua-mode-menu [set-lua-region-end]
1133 |   '("Set Lua-Region End" . lua-set-lua-region-end))
1134 | (define-key lua-mode-menu [set-lua-region-start]
1135 |   '("Set Lua-Region Start" . lua-set-lua-region-start))
1136 | 
1137 | (define-key lua-mode-menu [send-current-line]
1138 |   '("Send Current Line" . lua-send-current-line))
1139 | (define-key lua-mode-menu [send-region]
1140 |   '("Send Region" . lua-send-region))
1141 | (define-key lua-mode-menu [send-proc]
1142 |   '("Send Proc" . lua-send-proc))
1143 | (define-key lua-mode-menu [send-buffer]
1144 |   '("Send Buffer" . lua-send-buffer))
1145 | (define-key lua-mode-menu [search-documentation]
1146 |   '("Search Documentation" . lua-search-documentation))
1147 | 
1148 | (provide 'lua-mode)
1149 | 
1150 | 
1151 | ;;; lua-mode.el ends here
1152 | 


--------------------------------------------------------------------------------