From 9fc6ef251ef93b6b8e4f6083b00937670d394e94 Mon Sep 17 00:00:00 2001 From: Andrew J Cosgriff Date: Thu, 14 Oct 2010 20:13:07 +1100 Subject: initial checkin of working code --- README | 11 ++++ nginx-mode.el | 184 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 195 insertions(+) create mode 100644 README create mode 100644 nginx-mode.el diff --git a/README b/README new file mode 100644 index 0000000..a035502 --- /dev/null +++ b/README @@ -0,0 +1,11 @@ +This is a quick mode for editing Nginx config files, as I didn't find +anything else around that did quite this much. + +Many thanks to the authors of puppet-mode.el, from where I found a +useful indentation function that I've modified to suit this situation. + +Syntax highlighting is currently rather(!) basic, but I'll extend it +as necessary. + +Cheers, + Cos. diff --git a/nginx-mode.el b/nginx-mode.el new file mode 100644 index 0000000..b8998c3 --- /dev/null +++ b/nginx-mode.el @@ -0,0 +1,184 @@ +;;; nginx-mode.el --- major mode for editing nginx config files + +;; Copyright 2010 Andrew J Cosgriff + +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 2, or (at your option) +;; any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with this program; if not, write to the Free Software +;; Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +;;; Commentary: + +;; indentation bits were nicked from puppet-mode.el (thanks!) and +;; modified to suit. + +;; Put this file into your load-path and the following into your ~/.emacs: +;; (require 'nginx-mode) + +;;; Code: + +(provide 'nginx-mode) + + +;;;;########################################################################## +;;;; User Options, Variables +;;;;########################################################################## + +(defcustom nginx-indent-level 4 + "*Indentation of Nginx statements." + :type 'integer :group 'nginx) + +(defcustom nginx-indent-tabs-mode nil + "*Indentation can insert tabs in nginx mode if this is non-nil." + :type 'boolean :group 'nginx) + + +(defvar nginx-font-lock-keywords + (list '("#.*" . font-lock-comment-face) + '("^\\([ ]+\\)?\\([A-Za-z09_]+\\)" 2 font-lock-keyword-face t))) + + +;;;;########################################################################## +;;;; Code +;;;;########################################################################## + +(defun nginx-block-indent () + "If point is in a block, return the indentation of the first line of that +block (the line containing the opening brace). Used to set the indentation +of the closing brace of a block." + (save-excursion + (save-match-data + (let ((opoint (point)) + (apoint (search-backward "{" nil t))) + (when apoint + ;; This is a bit of a hack and doesn't allow for strings. We really + ;; want to parse by sexps at some point. + (let ((close-braces (count-matches "}" apoint opoint)) + (open-braces 0)) + (while (and apoint (> close-braces open-braces)) + (setq apoint (search-backward "{" nil t)) + (when apoint + (setq close-braces (count-matches "}" apoint opoint)) + (setq open-braces (1+ open-braces))))) + (if apoint + (current-indentation) + nil)))))) + + +(defun nginx-comment-line-p () + "Return non-nil iff this line is a comment." + (save-excursion + (save-match-data + (beginning-of-line) + (looking-at (format "\\s-*%s" comment-start))))) + +(defun nginx-indent-line () + "Indent current line as nginx code." + (interactive) + (beginning-of-line) + (if (bobp) + (indent-line-to 0) ; First line is always non-indented + (let ((not-indented t) + (block-indent (nginx-block-indent)) + cur-indent) + (cond + ((and (looking-at "^\\s-*},?\\s-*$") block-indent) + ;; This line contains a closing brace or a closing brace followed by a + ;; comma and we're at the inner block, so we should indent it matching + ;; the indentation of the opening brace of the block. + (setq cur-indent block-indent)) + (t + ;; Otherwise, we did not start on a block-ending-only line. + (save-excursion + ;; Iterate backwards until we find an indentation hint + (while not-indented + (forward-line -1) + (cond + ;; Comment lines are ignored unless we're at the start of the + ;; buffer. + ((nginx-comment-line-p) + (if (bobp) + (setq not-indented nil))) + + ;; Brace or paren on a line by itself will already be indented to + ;; the right level, so we can cheat and stop there. + ((looking-at "^\\s-*[\)}]\\s-*") + (setq cur-indent (current-indentation)) + (setq not-indented nil)) + + ;; Indent by one level more than the start of our block. We lose + ;; if there is more than one block opened and closed on the same + ;; line but it's still unbalanced; hopefully people don't do that. + ((looking-at "^.*{[^\n}]*$") + (setq cur-indent (+ (current-indentation) nginx-indent-level)) + (setq not-indented nil)) + + ;; Indent by one level if the line ends with an open paren. + ((looking-at "^.*\(\\s-*$") + (setq cur-indent (+ (current-indentation) nginx-indent-level)) + (setq not-indented nil)) + + ;; Start of buffer. + ((bobp) + (setq not-indented nil))))) + + ;; If this line contains only a closing paren, we should lose one + ;; level of indentation. + (if (looking-at "^\\s-*\)\\s-*$") + (setq cur-indent (- cur-indent nginx-indent-level))))) + + ;; We've figured out the indentation, so do it. + (if (and cur-indent (> cur-indent 0)) + (indent-line-to cur-indent) + (indent-line-to 0))))) + + +(defvar nginx-mode-map + (let + ((map (make-sparse-keymap))) + (define-key map "\C-j" 'newline-and-indent) + (define-key map "\C-m" 'newline-and-indent) + map) + "Keymap for editing nginx config files.") + +;;;###autoload +(defun nginx-mode () + "Major mode for highlighting nginx config files. + +The variable nginx-indent-level controls the amount of indentation. +\\{nginx-mode-map}" + (interactive) + (kill-all-local-variables) + (use-local-map nginx-mode-map) + (setq mode-name "Nginx" + major-mode 'nginx-mode) + + (set (make-local-variable 'comment-start) "# ") + (set (make-local-variable 'comment-start-skip) "#+ *") + (set (make-local-variable 'comment-use-syntax) t) + (set (make-local-variable 'comment-end) "") + (set (make-local-variable 'comment-auto-fill-only-comments) t) + + (set (make-local-variable 'indent-line-function) 'nginx-indent-line) + (set (make-local-variable 'indent-tabs-mode) nginx-indent-tabs-mode) + (set (make-local-variable 'require-final-newline) t) + (set (make-local-variable 'paragraph-ignore-fill-prefix) t) + (set (make-local-variable 'paragraph-start) "\f\\|[ ]*$\\|#$") + (set (make-local-variable 'paragraph-separate) "\\([ \f]*\\|#\\)$") + + (set (make-local-variable 'font-lock-defaults) + '(nginx-font-lock-keywords nil)) + (run-hooks 'nginx-mode-hook)) + +(provide 'nginx-mode) + +;;; nginx-mode.el ends here -- cgit v1.2.3-54-g00ecf