summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorGravatar Andrew J Cosgriff2010-10-14 20:13:07 +1100
committerGravatar Andrew J Cosgriff2010-10-14 20:13:07 +1100
commit9fc6ef251ef93b6b8e4f6083b00937670d394e94 (patch)
treeae9d050c7e212f1d0759ed8a3aa9ef17cda9d7c4
downloadnginx-mode-9fc6ef251ef93b6b8e4f6083b00937670d394e94.tar.gz
nginx-mode-9fc6ef251ef93b6b8e4f6083b00937670d394e94.zip
initial checkin of working code
-rw-r--r--README11
-rw-r--r--nginx-mode.el184
2 files changed, 195 insertions, 0 deletions
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 <andrew@cosgriff.name>
+
+;; 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