Skip to content

Instantly share code, notes, and snippets.

@UnwashedMeme
Created October 30, 2012 20:22
Show Gist options
  • Star 6 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save UnwashedMeme/3982757 to your computer and use it in GitHub Desktop.
Save UnwashedMeme/3982757 to your computer and use it in GitHub Desktop.
;;; vcl-mode.el - Syntax highlighting for Varnish Command Language
;;;
;;; Copyright (c) 2008-2009 Linpro AS
;;; All rights reserved.
;;;
;;; Author: Stig Sandbeck Mathisen <ssm@linpro.no>
;;;
;;; Redistribution and use in source and binary forms, with or without
;;; modification, are permitted provided that the following conditions
;;; are met:
;;; 1. Redistributions of source code must retain the above copyright
;;; notice, this list of conditions and the following disclaimer.
;;; 2. Redistributions in binary form must reproduce the above
;;; copyright notice, this list of conditions and the following
;;; disclaimer in the documentation and/or other materials provided
;;; with the distribution.
;;;
;;; THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS''
;;; AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
;;; TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
;;; PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR
;;; CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
;;; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
;;; LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
;;; USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
;;; AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
;;; LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
;;; ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
;;; POSSIBILITY OF SUCH DAMAGE.
;;;
;;; $Id$
;;;
;;; Based on
;;; https://www.varnish-cache.org/trac/browser/fragmentation/varnish-tools/emacs/vcl-mode.el?rev=72322230cfe73244bcf31e008a05a9c2c3867816
;;; Updated to work with varnish 3 a bit better; highlight more of the
;;; variable names and functions
(defgroup vcl nil
"Customizations for vcl-mode")
(defcustom vcl-indent-level 8
"*The level of indentation (number of space characters) in VCL-mode."
:type 'integer :group 'vcl)
(defcustom vcl-indent-tabs-mode nil
"*Allow tabs when indentation in vcl-mode if non-nil"
:type 'boolean :group 'vcl)
;; I just love standards, there are so many to choose from
(if (string-match "XEmacs\\|Lucid" emacs-version)
(require 'generic-mode)
(require 'generic))
;; Add a VCL major mode called "vcl-mode", based on generic-mode
(define-generic-mode 'vcl-mode
;; comments (defined in "vcl-mode-setup-function"
nil
;; keywords (defined under "others" instead)
nil
;; others
(list
;; Logic
(generic-make-keywords-list
(list
"else"
"elsif"
"if"
"remove"
)
'font-lock-keyword-face)
;; Types
(generic-make-keywords-list
(list
"set"
"unset"
"ban_url"
"ban"
"regsub"
"regsuball"
"hash_data"
"return"
"call"
"import"
)
'font-lock-builtin-face)
;; VCL Functions
(generic-make-keywords-list
(list
"acl"
"backend"
"sub"
"vcl_deliver"
"vcl_discard"
"vcl_fetch"
"vcl_hash"
"vcl_hit"
"vcl_miss"
"vcl_pass"
"vcl_pipe"
"vcl_recv"
"vcl_timeout"
)
'font-lock-function-name-face)
;; Actions
(generic-make-keywords-list
(list
"deliver"
"discard"
"error"
"fetch"
"hash"
"keep"
"lookup"
"pass"
"pipe"
"hit_for_pass"
)
'font-lock-function-name-face)
;; Variables
(generic-make-keywords-list
(list
"now"
".host"
".port"
"client.ip"
"client.identity"
"server.ip"
"server.port"
"server.hostname"
"server.identity"
"req.request"
"req.url"
"req.proto"
"req.backend"
"req.backend.healthy"
"req.hash_always_miss"
"req.hash_ignore_busy"
"req.can_gzip"
"req.restarts"
"req.esi"
"req.esi_level"
"req.grace"
"req.xid"
"bereq.request"
"bereq.url"
"bereq.proto"
"bereq.connect_timeout"
"bereq.first_byte_timeout"
"bereq.between_bytes_timeout"
"beresp.do_stream"
"beresp.do_esi"
"beresp.do_gzip"
"beresp.do_gunzip"
"beresp.proto"
"beresp.status"
"beresp.response"
"beresp.ttl"
"beresp.grace"
"beresp.saintmode"
"beresp.backend.name"
"beresp.backend.ip"
"beresp.backend.port"
"beresp.storage"
"obj.proto"
"obj.status"
"obj.response"
"obj.ttl"
"obj.lastuse"
"obj.hits"
"obj.grace"
"obj.http.header"
"req.hash"
"resp.proto"
"resp.status"
"resp.response"
"resp.http.header"
)
'font-lock-variable-name-face)
;; More variables
'("\\(\\(be\\)?\\(req\\|resp\\|obj\\)\\)\.http\.[A-Za-z-]+" .
font-lock-variable-name-face))
;; Filenames to highlight
'("\\.vcl\\'")
(list 'vcl-mode-setup-function)
"Mode for Varnish Command Language")
;; A function to modify syntax, add a hook if needed, and setup
;; indentation.
(defun vcl-mode-setup-function ()
;; These are "part of words"
(modify-syntax-entry ?_ "w")
(modify-syntax-entry ?. "w")
;; C++-style comments
(modify-syntax-entry ?/ ". 124")
(modify-syntax-entry ?* ". 23b")
;; Perl-style comments
(modify-syntax-entry ?# "<")
(modify-syntax-entry ?\n ">")
(run-hooks 'vcl-mode-hook)
(set (make-local-variable 'indent-line-function) 'vcl-indent-line)
(setq indent-tabs-mode vcl-indent-tabs-mode)
)
(defvar vcl-mode-hook nil)
(defun vcl-indent-line ()
"Indent the current VCL line according to syntax."
(interactive)
(indent-line-to
(max (vcl-calculate-indentation) 0)))
;; The function to calculate indentation level. This is a really
;; simple and naive function, and does not perform anything like a
;; syntax check.
(defun vcl-calculate-indentation ()
"Return the column to which the current line should be indented."
(interactive)
(save-excursion
; Do not indent the first line.
(if (vcl-first-line-p) 0
; Reduce indent level if we
; close a block on this line
(if (vcl-closing-tag-on-this-line-p)
(- (vcl-previous-line-indentation)
vcl-indent-level)
; Increase indent level if a
; block opened on the previous
; line
(if (vcl-opening-tag-on-previous-line-p)
(+ (vcl-previous-line-indentation)
vcl-indent-level)
; By default, indent to the
; level of the previous
; non-empty line
(vcl-previous-line-indentation))))))
(defun vcl-opening-tag-on-previous-line-p ()
"Checks if we have an opening tag on the previous line."
(interactive)
(save-excursion
(beginning-of-line)
(skip-chars-backward " \t\n")
(beginning-of-line)
(if (and (looking-at ".*{[ \t]*$")
(not (vcl-comment-p)))
t)))
(defun vcl-closing-tag-on-this-line-p ()
"Checks if we have a closing tag on this line."
(interactive)
(save-excursion
(back-to-indentation)
(looking-at "}")))
(defun vcl-previous-line-indentation ()
"Return the indent level of the previous line."
(interactive)
(save-excursion
(beginning-of-line)
(skip-chars-backward " \t\n")
(back-to-indentation)
(current-column)))
(defun vcl-comment-p ()
"Checks if we have a commented line."
(interactive)
(save-excursion
(beginning-of-line)
(looking-at "^[ \t]*#")))
(defun vcl-first-line-p ()
"Checks if we are on the first line."
(interactive)
(save-excursion
(beginning-of-line)
(eq (point) 1)))
(provide 'vcl-mode)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment