1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189
|
;;; nginx-mode.el --- major mode for editing nginx config files
;; Copyright 2010 Andrew J Cosgriff <andrew@cosgriff.name>
;; Author: Andrew J Cosgriff <andrew@cosgriff.name>
;; Maintainer: Andrew J Cosgriff <andrew@cosgriff.name>
;; Created: 15 Oct 2010
;; Version: 1.1.10
;; Keywords: languages, nginx
;; available from http://github.com/ajc/nginx-mode
;; 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, see <http://www.gnu.org/licenses/>.
;;; Commentary:
;; 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.
;; Put this file into your load-path and the following into your ~/.emacs:
;; (require 'nginx-mode)
;;
;; Now that nginx-mode is available via NonGNU ELPA, you could also:
;; (use-package nginx-mode
;; :commands nginx-mode)
;;; Code:
;;;;##########################################################################
;;;; 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-mode-syntax-table
(let ((table (make-syntax-table)))
(modify-syntax-entry ?# "< b" table)
(modify-syntax-entry ?\n "> b" table)
table)
"Syntax table for `nginx-mode'.")
(defvar nginx-font-lock-keywords
(list '("^\\([ \t]+\\)?\\([A-Za-z09_]+\\)" 2 font-lock-keyword-face t)
;; uncomment the next one if you want your eyes to bleed
;; (it'll highlight parentheses and curly braces)
;;'("\\(\{\\|\}\\|\(\\|\)\\)" . font-lock-pseudo-keyword-face)
'("^\\([ \t]+\\)?rewrite[ \t]+.+[ \t]+\\(permanent\\|redirect\\|break\\|last\\);$" 2 font-lock-function-name-face)
'("\\(\$[0-9]+\\)[^0-9]" 1 font-lock-constant-face)
'("\$[A-Za-z0-9_\-]+" . font-lock-variable-name-face)
'("[ \t]+\\(on\\|off\\);$" 1 font-lock-constant-face)
'("[A-Za-z0-9_\-]+\\([ \t]+[^ \t\n]+\\)?[ \t]+\\([^ \t\n]+\\)[ \t]+{" 2 font-lock-function-name-face)))
;;;;##########################################################################
;;;; 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."
(* (syntax-ppss-depth (syntax-ppss))
nginx-indent-level))
(defun nginx-comment-line-p ()
"Return non-nil iff this line is a comment."
(save-excursion
(save-match-data
(beginning-of-line)
(looking-at "^\\s-*#"))))
(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-*}") block-indent)
;; This line contains a closing brace 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 nginx-indent-level)))
(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))
;; Start of buffer.
((bobp)
(setq not-indented nil)))))))
;; 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
(define-derived-mode nginx-mode prog-mode "Nginx"
"Major mode for highlighting nginx config files.
The variable nginx-indent-level controls the amount of indentation.
\\{nginx-mode-map}"
:syntax-table nginx-mode-syntax-table
(use-local-map nginx-mode-map)
(set (make-local-variable 'comment-start) "# ")
(set (make-local-variable 'comment-start-skip) "#+ *")
(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)))
;;;###autoload
(add-to-list 'auto-mode-alist '("nginx\\.conf\\'" . nginx-mode))
;;;###autoload
(add-to-list 'auto-mode-alist '("/nginx/.+\\.conf\\'" . nginx-mode))
;;;###autoload
(add-to-list
'magic-fallback-mode-alist
'("\\(?:.*\n\\)*\\(?:http\\|server\\|location .+\\|upstream .+\\)[ \n\t]+{"
. nginx-mode))
(provide 'nginx-mode)
;;; nginx-mode.el ends here
|