From: Andreas Gerler Date: Sun, 26 Nov 2023 15:23:59 +0000 (+0100) Subject: update puppet-mode X-Git-Url: http://git.bundesbrandschatzamt.de/?a=commitdiff_plain;h=b06085e4709ceffa15eefc30e877028b2055b358;p=emacsconfig.git update puppet-mode Signed-off-by: Andreas Gerler --- diff --git a/elpa/puppet-mode-20180813.1947/puppet-mode-autoloads.el b/elpa/puppet-mode-20180813.1947/puppet-mode-autoloads.el deleted file mode 100644 index 3861c66d..00000000 --- a/elpa/puppet-mode-20180813.1947/puppet-mode-autoloads.el +++ /dev/null @@ -1,29 +0,0 @@ -;;; puppet-mode-autoloads.el --- automatically extracted autoloads -;; -;;; Code: - -(add-to-list 'load-path (directory-file-name - (or (file-name-directory #$) (car load-path)))) - - -;;;### (autoloads nil "puppet-mode" "puppet-mode.el" (0 0 0 0)) -;;; Generated autoloads from puppet-mode.el - -(autoload 'puppet-mode "puppet-mode" "\ - - -\(fn)" t nil) - -(add-to-list 'auto-mode-alist '("\\.pp\\'" . puppet-mode)) - -(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "puppet-mode" '("puppet-"))) - -;;;*** - -;; Local Variables: -;; version-control: never -;; no-byte-compile: t -;; no-update-autoloads: t -;; coding: utf-8 -;; End: -;;; puppet-mode-autoloads.el ends here diff --git a/elpa/puppet-mode-20180813.1947/puppet-mode-pkg.el b/elpa/puppet-mode-20180813.1947/puppet-mode-pkg.el deleted file mode 100644 index cb6732da..00000000 --- a/elpa/puppet-mode-20180813.1947/puppet-mode-pkg.el +++ /dev/null @@ -1,2 +0,0 @@ -;;; -*- no-byte-compile: t -*- -(define-package "puppet-mode" "20180813.1947" "Major mode for Puppet manifests" '((emacs "24.1") (pkg-info "0.4")) :commit "7dee1b5a5debac6e56f9107492a413b6c0edb94d" :keywords '("languages") :authors '(("Bozhidar Batsov" . "bozhidar@batsov.com") ("Sebastian Wiesner" . "swiesner@lunaryorn.com") ("Russ Allbery" . "rra@stanford.edu")) :maintainer '("Bozhidar Batsov" . "bozhidar@batsov.com") :url "https://github.com/voxpupuli/puppet-mode") diff --git a/elpa/puppet-mode-20180813.1947/puppet-mode.el b/elpa/puppet-mode-20180813.1947/puppet-mode.el deleted file mode 100644 index d50fffe9..00000000 --- a/elpa/puppet-mode-20180813.1947/puppet-mode.el +++ /dev/null @@ -1,1269 +0,0 @@ -;;; puppet-mode.el --- Major mode for Puppet manifests -*- lexical-binding: t; -*- - -;; Copyright (C) 2013-2014, 2016 Sebastian Wiesner -;; Copyright (C) 2013, 2014 Bozhidar Batsov -;; Copyright (C) 2011 Puppet Labs Inc - -;; Author: Bozhidar Batsov -;; Sebastian Wiesner -;; Russ Allbery -;; Maintainer: Bozhidar Batsov -;; Sebastian Wiesner -;; URL: https://github.com/voxpupuli/puppet-mode -;; Package-Version: 20180813.1947 -;; Keywords: languages -;; Version: 0.4-cvs -;; Package-Requires: ((emacs "24.1") (pkg-info "0.4")) - -;; This file is not part of GNU Emacs. - -;; 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 3 of the License, 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 . - -;; This file incorporates work covered by the following copyright and -;; permission notice: - -;; Licensed under the Apache License, Version 2.0 (the "License"); you may not -;; use this file except in compliance with the License. You may obtain a copy -;; of the License at -;; -;; http://www.apache.org/licenses/LICENSE-2.0 -;; -;; Unless required by applicable law or agreed to in writing, software -;; distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -;; WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -;; License for the specific language governing permissions and limitations -;; under the License. - -;;; Commentary: - -;; GNU Emacs 24 major mode for editing Puppet manifests. - -;; Provides syntax highlighting, indentation, alignment, movement, Imenu and -;; code checking. - -;; Syntax highlighting: Fontification supports all of Puppet 3 syntax, including -;; variable expansion in strings. - -;; Indentation: Indent expressions automatically. - -;; Alignment: Provide alignment rules for common Puppet expressions, and align -;; the current block with `puppet-align-block' on C-c C-a. - -;; Movement: Move to the beginning or end of the current block with -;; `beginning-of-defun' (C-M-a) and `end-of-defun' (C-M-e) respectively. - -;; Imenu: Jump to a tag in the current buffer with `imenu' on C-c C-j. Index -;; variables, resource defaults, classes, nodes, defined types and resource -;; declarations. - -;; Code checking: Validate the syntax of the current buffer with -;; `puppet-validate' on C-c C-v. Lint the current buffer for semantic errors -;; with `puppet-lint' on C-c C-l. Apply the current buffer with `puppet-apply' -;; on C-c C-c. - -;; Syntax checking: Flymake support is _not_ provided. See Flycheck at -;; http://www.flycheck.org for on-the-fly validation and liniting of Puppet -;; manifests. - -;;; Code: - - -;;; Compatibility -(eval-and-compile - ;; `defvar-local' for Emacs 24.2 and below - (unless (fboundp 'defvar-local) - (defmacro defvar-local (var val &optional docstring) - "Define VAR as a buffer-local variable with default value VAL. -Like `defvar' but additionally marks the variable as being automatically -buffer-local wherever it is set." - (declare (debug defvar) (doc-string 3)) - `(progn - (defvar ,var ,val ,docstring) - (make-variable-buffer-local ',var)))) - - ;; `setq-local' for Emacs 24.2 and below - (unless (fboundp 'setq-local) - (defmacro setq-local (var val) - "Set variable VAR to value VAL in current buffer." - `(set (make-local-variable ',var) ,val)))) - - -;;; Requirements -(declare-function pkg-info-version-info "pkg-info" (library)) - -(eval-when-compile - (require 'rx)) - -(require 'align) -(require 'ansi-color) -(require 'comint) - - -;;; Customization -(defgroup puppet nil - "Puppet mastering in Emacs" - :prefix "puppet-" - :group 'languages - :link '(url-link :tag "Github" "https://github.com/voxpupuli/puppet-mode") - :link '(emacs-commentary-link :tag "Commentary" "puppet-mode")) - -(defcustom puppet-indent-level 2 - "Indentation of Puppet statements." - :type 'integer - :group 'puppet - :safe 'integerp) - -(defcustom puppet-include-indent 2 - "Indentation of continued Puppet include statements." - :type 'integer - :group 'puppet - :safe 'integerp) - -(defcustom puppet-indent-tabs-mode nil - "Indentation can insert tabs in puppet mode if this is non-nil." - :type 'boolean - :group 'puppet - :safe 'booleanp) - -(defcustom puppet-comment-column 32 - "Indentation column of comments." - :type 'integer - :group 'puppet - :safe 'integerp) - -(defcustom puppet-fontify-variables-in-comments nil - "When non-nil, fontify variable references in comments." - :type 'boolean - :group 'puppet - :safe 'booleanp - :package-version '(puppet-mode . "0.3")) - -(defcustom puppet-validate-command "puppet parser validate --color=false" - "Command to validate the syntax of a Puppet manifest." - :type 'string - :group 'puppet) - -(defcustom puppet-lint-command - (concat - "puppet-lint --with-context " - "--log-format \"%{path}:%{line}: %{kind}: %{message} (%{check})\"") - "Command to lint a Puppet manifest." - :type 'string - :group 'puppet - :package-version '(puppet-mode . "0.3")) - -(defcustom puppet-apply-command "puppet apply --verbose --noop" - "Command to apply a Puppet manifest." - :type 'string - :group 'puppet - :package-version '(puppet-mode . "0.3")) - -(defcustom puppet-repl-command "puppet debugger" - "The Puppet REPL command used to interact with code." - :type 'string - :group 'puppet - :package-version '(puppet-mode . "0.4")) - -(defcustom puppet-repl-args '() - "The arguments to pass to `puppet-repl-command' to start a REPL." - :group 'puppet - :type '(repeat string) - :package-version '(puppet-mode . "0.4")) - -(defcustom puppet-repl-buffer "*Puppet-REPL*" - "The name of the Puppet REPL buffer." - :group 'puppet - :type 'string - :package-version '(puppet-mode . "0.4")) - -(defface puppet-regular-expression-literal - '((t :inherit font-lock-constant-face)) - "Face for regular expression literals in Puppet." - :group 'puppet - :package-version '(puppet-mode . "0.3")) - -(defface puppet-escape-sequence - '((t :inherit font-lock-constant-face)) - "Face for escape sequences in double-quoted strings-consed literals in Puppet." - :group 'puppet - :package-version '(puppet-mode . "0.3")) - - -;;; Version information -(defun puppet-version (&optional show-version) - "Get the Puppet Mode version as string. - -If called interactively or if SHOW-VERSION is non-nil, show the -version in the echo area and the messages buffer. - -The returned string includes both, the version from package.el -and the library version, if both a present and different. - -If the version number could not be determined, signal an error, -if called interactively, or if SHOW-VERSION is non-nil, otherwise -just return nil." - (interactive (list t)) - (let ((version (pkg-info-version-info 'puppet-mode))) - (when show-version - (message "Puppet Mode version: %s" version)) - version)) - - -;;; Utilities - -(defun puppet-syntax-context (&optional pos) - "Determine the syntax context at POS, defaulting to point. - -Return nil, if there is no special context at POS, or one of - -`comment' - POS is inside a comment - -`single-quoted' - POS is inside a single-quoted string - -`double-quoted' - POS is inside a double-quoted string" - (let ((state (save-excursion (syntax-ppss pos)))) - (if (nth 4 state) - 'comment - (pcase (nth 3 state) - (`?\' 'single-quoted) - (`?\" 'double-quoted))))) - -(defun puppet-in-string-or-comment-p (&optional pos) - "Determine whether POS is inside a string or comment." - (not (null (puppet-syntax-context pos)))) - -(defun puppet-get-repl-proc () - (unless (comint-check-proc puppet-repl-buffer) - (puppet-repl)) - (get-buffer-process puppet-repl-buffer)) - -(defun puppet-repl-send-region (start end) - "Send the current region to the inferior Puppet REPL process." - (interactive "r") - (deactivate-mark t) - (let* ((string (buffer-substring-no-properties start end)) - (proc (puppet-get-repl-proc))) - (comint-simple-send proc string))) - -(defun puppet-repl-send-line () - "Send the current line to the inferior Puppet REPL process." - (interactive) - (puppet-repl-send-region (line-beginning-position) (line-end-position))) - -(defun puppet-repl-send-buffer () - "Send the current buffer to the inferior Puppet REPL process." - (interactive) - (puppet-repl-send-region (point-min) (point-max))) - -(defun puppet-comint-filter (string) - (ansi-color-apply string)) - -(defun puppet-repl () - "Launch a Puppet REPL using `puppet-repl-command' as an inferior mode." - (interactive) - - ;; the command (at least for now) is 'puppet debugger' - ;; but really it is 'puppet' with args 'debugger' + puppet-repl-args - ;; Even if it changes, we need to not break on multi-word commands - (unless (comint-check-proc puppet-repl-buffer) - (let* ((command-list (split-string puppet-repl-command)) - (real-puppet-repl-command (car command-list)) - (real-puppet-repl-args (append (cdr command-list) - puppet-repl-args))) - (set-buffer - (apply 'make-comint "Puppet-REPL" - real-puppet-repl-command - nil - real-puppet-repl-args))) - ;; Workaround for ansi colors - (add-hook 'comint-preoutput-filter-functions 'puppet-comint-filter nil t)) - - (pop-to-buffer puppet-repl-buffer)) - -;;; Specialized rx - -(eval-when-compile - (defun puppet-rx-symbol (form) - "Translate FORM into a regular expression." - (let ((body (cdr form))) - (rx-to-string `(and symbol-start ,@body symbol-end) 'no-group))) - - (defconst puppet-rx-constituents - `((symbol puppet-rx-symbol 0 nil) - ;; http://docs.puppetlabs.com/puppet/3/reference/lang_datatypes.html#regular-expressions - (regexp-literal . ,(rx (zero-or-more - (or - ;; Not the end of a regexp - (not (any "/" "\\" "\n")) - ;; Any escaped character - (and "\\" not-newline))))) - ;; http://docs.puppetlabs.com/puppet/latest/reference/lang_reserved.html#reserved-words - (keyword . ,(rx (or "and" "application" "attr" "case" "class" "consumes" - "default" "define" "else" "elsif" "environment" - "false" "function" "if" "import" "in" "inherits" - "node" "or" "private" "produces" "site" "true" - "type" "undef" "unless" - ;; Bolt - ;; https://puppet.com/docs/bolt/0.x/writing_plans.html - "plan" - ))) - ;; http://docs.puppetlabs.com/references/latest/function.html - (builtin-function . ,(rx (or "alert" "assert_type" "binary_file" "break" - "contain" "create_resources" "crit" "debug" - "defined" "dig" "digest" "each" "emerg" - "epp" "err" "fail" "file" "filter" - "find_file" "fqdn_rand" "generate" "hiera" - "hiera_array" "hiera_hash" "hiera_include" - "include" "info" "inline_epp" - "inline_template" "lest" "lookup" "map" - "match" "md5" "new" "next" "notice" - "realize" "reduce" "regsubst" "require" - "return" "reverse_each" "scanf" "sha1" - "shellquote" "slice" "split" "sprintf" - "step" "strftime" "tag" "tagged" "template" - "then" "type" "versioncmp" "warning" "with" - ;; Bolt - ;; https://puppet.com/docs/bolt/0.x/plan_functions.html - ;; https://puppet.com/docs/bolt/0.x/writing_plans.html#concept-4926 - "apply" "apply_prep" "add_facts" "facts" - "fail_plan" "file_upload" "get_targets" - "puppetdb_fact" "puppetdb_query" - "run_command" "run_plan" "run_script" - "run_task" "set_feature" "set_var" "vars" - "without_default_logging" - ))) - ;; http://docs.puppetlabs.com/references/latest/type.html - (builtin-type . ,(rx (or "augeas" "computer" "cron" "exec" "file" - "filebucket" "group" "host" "interface" "k5login" - "macauthorization" "mailalias" "maillist" "mcx" - "mount" "nagios_command" "nagios_contact" - "nagios_contactgroup" "nagios_host" - "nagios_hostdependency" "nagios_hostescalation" - "nagios_hostextinfo" "nagios_hostgroup" - "nagios_service" "nagios_servicedependency" - "nagios_serviceescalation" "nagios_serviceextinfo" - "nagios_servicegroup" "nagios_timeperiod" "notify" - "package" "resources" "router" "schedule" - "scheduled_task" "selboolean" "selmodule" - "service" "ssh_authorized_key" "sshkey" "stage" - "tidy" "user" "vlan" "yumrepo" "zfs" "zone" - "zpool"))) - ;; http://docs.puppetlabs.com/references/stable/metaparameter.html. - ;; Strictly speaking, this is no meta parameter, but it's so common that - ;; it got a mention in the docs, see - ;; http://docs.puppetlabs.com/puppet/latest/reference/lang_resources.html#ensure, - ;; so we'll consider it as metaparameter anyway - (builtin-metaparam . ,(rx (or "alias" "audit" "before" "consume" "export" - "loglevel" "noop" "notify" "require" - "schedule" "stage" "subscribe" "tag" - ;; Because it's so common and important - "ensure"))) - ;; https://github.com/puppetlabs/puppet-specifications/blob/master/language/types_values_variables.md - (data-type . ,(rx (or - ;; Data Types - "Array" "Binary" "Hash" - ;; Scalar Types - "Boolean" "Float" "Integer" "Regexp" "SemVer" "String" - "Timespan" "Timestamp" - ;; Catalog Types - "Class" "Resource" - ;; Abstract Types - "Any" "CatalogEntry" "Collection" "Data" "Enum" - "Iterable" "Iterator" "NotUndef" "Numeric" "Optional" - "Pattern" "RichData" "Scalar" "ScalarData" - "SemVerRange" "Struct" "Tuple" "Variant" - ;; Platform Types: - "Callable" "Default" "Runtime" "Sensitive" "Type" - "Undef" - ;; Bolt types: - ;; https://puppet.com/docs/bolt/0.x/writing_plans.html - "Error" "PlanResult" "Result" "ResultSet" "Target" - "TargetSpec" - ))) - ;; http://docs.puppetlabs.com/puppet/latest/reference/lang_reserved.html#classes-and-types - (resource-name . ,(rx - ;; Optional top-level scope - (optional "::") - (zero-or-more (any "a-z") - (zero-or-more (any "a-z" "0-9" "_")) - "::") - ;; Nested sub-scopes - (any "a-z") - (zero-or-more (any "a-z" "0-9" "_")))) - (cap-resource-name . ,(rx - ;; Top-scope indicator - (optional "::") - (zero-or-more (any "A-Z") - (zero-or-more - (any "a-z" "0-9" "_")) - "::") - ;; Nested sub-scopes - (any "A-Z") - (zero-or-more (any "a-z" "0-9" "_")))) - ;; http://docs.puppetlabs.com/puppet/latest/reference/lang_reserved.html#nodes - (node-name . ,(rx (one-or-more (any "a-z" "0-9" ?. ?_ ?-)))) - ;; http://docs.puppetlabs.com/puppet/latest/reference/lang_reserved.html#variables - (simple-variable-name . ,(rx (one-or-more (any "A-Z" "a-z" "0-9" "_")))) - (variable-name . ,(rx - ;; The optional scope designation - (optional "::") - (zero-or-more (any "a-z") - (zero-or-more - (any "A-Z" "a-z" "0-9" "_")) - "::") - ;; The final variable name - (one-or-more (any "A-Z" "a-z" "0-9" "_")))) - ;; http://docs.puppetlabs.com/puppet/latest/reference/lang_datatypes.html#double-quoted-strings - (dq-escape . ,(rx (or line-start (not (any "\\"))) - (zero-or-more "\\\\") - ;; We do not include \n and \', because these are - ;; available in single-quoted strings as well - (group "\\" (any ?\" ?$ ?n ?r ?t ?s))))) - "Additional special sexps for `puppet-rx'") - - (defmacro puppet-rx (&rest sexps) - "Specialized `rx' variant for Puppet Mode. - -In addition to the standard forms of `rx', the following forms -are available: - -`(symbol SEXP …)' - Match SEXPs inside symbol boundaries only - -`regexp-literal' - A Puppet regexp literal, *without* surrounding slashes - -`keyword' - Any valid Puppet keyword - -`builtin-function' - Any built-in Puppet function - -`builtin-type' - Any built-in Puppet type - -`builtin-metaparam' - Any built-in meta-parameter, and `ensure' - -`data-type' - Any Puppet data type - -`resource-name' - Any valid resource name, including scopes - -`cap-resource-name' - Any capitalized resource name, including capitalized scopes - -`node-name' - Any valid node name - -`simple-variable-name' - Any variable name without scopes, without leading dollar sign - -`variable-name' - Any variable name including scopes, without a leading dollar sign - -`dq-escape' - Special escape sequences for double-quoted strings" - (let ((rx-constituents (append puppet-rx-constituents rx-constituents))) - (cond ((null sexps) - (error "No regexp")) - ((cdr sexps) - (rx-to-string `(and ,@sexps) t)) - (t - (rx-to-string (car sexps) t)))))) - - -;;; Checking - -(defvar-local puppet-last-validate-command nil - "The last command used for validation.") - -(defvar-local puppet-last-lint-command nil - "The last command used for linting.") - -(defvar-local puppet-last-apply-command nil - "The last command used to apply a manifest.") - -(defun puppet-run-check-command (command buffer-name-template) - "Run COMMAND to check the current buffer." - (save-some-buffers (not compilation-ask-about-save) nil) - (compilation-start command nil (lambda (_) - (format buffer-name-template command)))) - -(defun puppet-read-command (prompt previous-command default-command) - "Read a command from minibuffer with PROMPT." - (let* ((buffer-file-name (or (buffer-file-name) "")) - (filename (or (file-remote-p buffer-file-name 'localname) - buffer-file-name))) - (read-string prompt (or previous-command - (concat default-command " " - (shell-quote-argument filename)))))) - -(defun puppet-validate (command) - "Validate the syntax of the current buffer with COMMAND. - -When called interactively, prompt for COMMAND." - (interactive (list (puppet-read-command "Validate command: " - puppet-last-validate-command - puppet-validate-command))) - (setq puppet-last-validate-command command) - (puppet-run-check-command command "*Puppet Validate: %s*")) - -(defun puppet-lint (command) - "Lint the current buffer with COMMAND. - -When called interactively, prompt for COMMAND." - (interactive (list (puppet-read-command "Lint command: " - puppet-last-lint-command - puppet-lint-command))) - (setq puppet-last-lint-command command) - (puppet-run-check-command command "*Puppet Lint: %s*")) - -(defun puppet-apply (command) - "Apply the current manifest with COMMAND. - -When called interactively, prompt for COMMAND." - (interactive (list (puppet-read-command "Apply command: " - puppet-last-apply-command - puppet-apply-command))) - (setq puppet-last-apply-command command) - (puppet-run-check-command command "*Puppet Apply: %s*")) - - -;;; Navigation -;; TODO: Check which of these are still needed for SMIE - -(defun puppet-beginning-of-defun-function (&optional arg) - "Move to the ARG'th beginning of a block." - (let* ((arg (or arg 1)) - (search (if (< arg 0) #'search-forward #'search-backward)) - (steps (abs arg))) - (while (> steps 0) - (let ((pos (funcall search "{" nil 'no-error))) - ;; Skip over strings and comments - (while (and pos (puppet-in-string-or-comment-p pos)) - (setq pos (funcall search "{" nil 'no-error))) - (if pos - (setq steps (1- steps)) - ;; Drop out of outer loop - (setq steps 0)))) - (when (< arg 0) - (backward-char)))) - - -;;; Indentation code -(defun puppet-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 - (let ((opoint (nth 1 (syntax-ppss)))) - (when (and opoint - (progn - (goto-char opoint) - (looking-at-p "{"))) - (current-indentation))))) - -(defun puppet-in-argument-list () - "If point is in an argument list, return the position of the opening '('. -If point is not in an argument list, return nil." - (puppet--in-listlike "(")) - -(defun puppet-in-array () - "If point is in an array, return the position of the opening '[' of -that array, else return nil." - (puppet--in-listlike "\\[")) - -(defun puppet--in-listlike (openstring) - "If point is in a listlike, return the position of the opening character of -it, else return nil. -OPENSTRING is a regexp string matching the opening character." - (save-excursion - (let ((opoint (nth 1 (syntax-ppss)))) - (when (and opoint - (progn - (goto-char opoint) - (looking-at-p openstring))) - opoint)))) - -(defun puppet-in-include () - "If point is in a continued list of include statements, return the position -of the initial include plus puppet-include-indent." - (save-excursion - (save-match-data - (let ((include-column nil) - (not-found t)) - (while not-found - (forward-line -1) - (cond - ((bobp) - (setq not-found nil)) - ((looking-at "^\\s-*include\\s-+.*,\\s-*$") - (setq include-column - (+ (current-indentation) puppet-include-indent)) - (setq not-found nil)) - ((not (looking-at ".*,\\s-*$")) - (setq not-found nil)))) - include-column)))) - -(defun puppet-indent-listlike (listtype closing-regex list-start) - ;; This line starts with an element from an array or parameter list. - ;; Indent to the same indentation as the first element of the list: - ;; - ;; $example = ['string1', 'string2', - ;; 'string3', 'string4'] - ;; $example = example('string1', - ;; 'string2') - (save-excursion - (if (looking-at closing-regex) - ;; Closing bracket on a line by itself. Align with opening bracket. - (progn - (goto-char list-start) - (if (or (save-excursion (forward-char) (eolp)) - ;; closing class parameter list: - (and (eq listtype 'arglist) - (save-excursion - (backward-sexp 2) - (looking-at "class.*")))) - (current-indentation) - (current-column))) - ;; Use normal indentation if the point is at the end of the line. - ;; - ;; $example => [ - ;; 'foo', - ;; 'bar', - ;; ] - (goto-char list-start) - (forward-char 1) - (if (eolp) - (+ (current-indentation) puppet-indent-level) - ;; Otherwise, attempt to align as described above. - (re-search-forward "\\S-") - (forward-char -1) - (current-column))))) - -(defun puppet-indent-array (array-start) - (puppet-indent-listlike 'array "^\\s-*],*" array-start)) - -(defun puppet-indent-arglist (arglist-start) - (puppet-indent-listlike 'arglist "^\\s-*),*" arglist-start)) - -(defun puppet-indent-line () - "Indent current line as puppet code." - (interactive) - (beginning-of-line) - (if (bobp) - (indent-line-to 0) ; First line is always non-indented - (let ((not-indented t) - (arglist-start (puppet-in-argument-list)) - (array-start (puppet-in-array)) - (include-start (puppet-in-include)) - (block-indent (puppet-block-indent)) - cur-indent) - (cond - (array-start (setq cur-indent (puppet-indent-array array-start))) - (arglist-start (setq cur-indent (puppet-indent-arglist arglist-start))) - (include-start - (setq cur-indent include-start)) - - ((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)) - (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. - ((or (eq (puppet-syntax-context) 'comment) - (save-excursion (end-of-line) - (eq (puppet-syntax-context) 'comment))) - (if (bobp) - (setq not-indented nil))) - - ;; Closing paren. Use indentation based on start of - ;; argument list - ((or (looking-at "^\\s-*\)\\s-*$") - (looking-at "^[^\n\(]*[\)],?\\s-*$")) - (goto-char (puppet-in-argument-list)) - (setq cur-indent (current-indentation)) - (setq not-indented nil)) - - ;; Brace (possibly followed by a comma) 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-*[-~]>\\)?\\s-*\s?$") - (setq cur-indent (current-indentation)) - (setq not-indented nil)) - - ;; Brace (possibly followed by a comma) or paren not on a line by - ;; itself will be indented one level too much, but don't catch - ;; cases where the block is started and closed on the same line. - ((looking-at "^[^\n\({]*[\)}],?\\s-*$") - (setq cur-indent (- (current-indentation) puppet-indent-level)) - (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) puppet-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) puppet-indent-level)) - (setq not-indented nil)) - - ;; Semicolon ends a block for a resource when multiple resources - ;; are defined in the same block, but try not to get the case of - ;; a complete resource on a single line wrong. - ((looking-at "^\\([^'\":\n]\\|\"[^\n\"]*\"\\|'[^\n']*'\\)*;\\s-*$") - (setq cur-indent (- (current-indentation) puppet-indent-level)) - (setq not-indented nil)) - - ;; Indent an extra level after : since it introduces a resource. - ((looking-at "^.*:\\s-*$") - (setq cur-indent (+ (current-indentation) puppet-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 puppet-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))))) - - -;;; Font locking - -(defvar puppet-mode-syntax-table - (let ((table (make-syntax-table))) - ;; Our strings - (modify-syntax-entry ?\' "\"'" table) - (modify-syntax-entry ?\" "\"\"" table) - ;; C-style comments. Yes, Puppet has these! - (modify-syntax-entry ?/ ". 14b" table) - (modify-syntax-entry ?* ". 23b" table) - ;; Line comments - (modify-syntax-entry ?# "<" table) - (modify-syntax-entry ?\n ">" table) - ;; The backslash is our escape character - (modify-syntax-entry ?\\ "\\" table) - ;; The dollar sign is an expression prefix for variables - (modify-syntax-entry ?$ "'" table) - ;; Fix various operators and punctionation. - (modify-syntax-entry ?< "." table) - (modify-syntax-entry ?> "." table) - (modify-syntax-entry ?& "." table) - (modify-syntax-entry ?| "." table) - (modify-syntax-entry ?% "." table) - (modify-syntax-entry ?= "." table) - (modify-syntax-entry ?+ "." table) - (modify-syntax-entry ?- "." table) - (modify-syntax-entry ?\; "." table) - ;; Our parenthesis, braces and brackets - (modify-syntax-entry ?\( "()" table) - (modify-syntax-entry ?\) ")(" table) - (modify-syntax-entry ?\{ "(}" table) - (modify-syntax-entry ?\} "){" table) - (modify-syntax-entry ?\[ "(]" table) - (modify-syntax-entry ?\] ")[" table) - table) - "Syntax table in use in `puppet-mode' buffers.") - -(defvar puppet-font-lock-keywords - `( - ;; Keywords - (,(puppet-rx (symbol keyword)) 0 font-lock-keyword-face) - ;; Data Types - (,(puppet-rx (symbol data-type)) 0 font-lock-type-face) - ;; Variables - (,(puppet-rx "$" (symbol variable-name)) 0 font-lock-variable-name-face) - ;; Class and type declarations - (,(puppet-rx (symbol (or "class" "define" "plan")) - (one-or-more space) - (group (symbol resource-name))) - 1 font-lock-type-face) - ;; Node declarations - (,(puppet-rx (symbol "node") - (one-or-more space) - (group node-name)) - 1 font-lock-type-face) - ;; Resource usage, see - ;; http://docs.puppetlabs.com/puppet/latest/reference/lang_resources.html - (,(puppet-rx (group (repeat 0 2 "@") ; Virtual and exported resources - (symbol resource-name)) - (zero-or-more space) "{") - 1 font-lock-type-face) - ;; Resource defaults, see - ;; http://docs.puppetlabs.com/puppet/latest/reference/lang_defaults.html - (,(puppet-rx (group (symbol cap-resource-name)) (zero-or-more space) "{") - 1 font-lock-type-face) - ;; Resource references, see - ;; http://docs.puppetlabs.com/puppet/latest/reference/lang_datatypes.html#resource-references - (,(puppet-rx (group (symbol cap-resource-name)) (zero-or-more space) "[") - 1 font-lock-type-face) - ;; Resource collectors, see - ;; http://docs.puppetlabs.com/puppet/latest/reference/lang_collectors.html - (,(puppet-rx (group (symbol cap-resource-name)) (zero-or-more space) - (optional "<") ; Exported collector - "<|") - 1 font-lock-type-face) - ;; Negation - ("!" 0 font-lock-negation-char-face) - ;; Builtin meta parameters - (,(puppet-rx (group (symbol builtin-metaparam)) (zero-or-more space) "=>") - 1 font-lock-builtin-face) - ;; Built-in functions - (,(puppet-rx (symbol builtin-function)) 0 font-lock-builtin-face) - ;; Type arguments to some special built-in functions - (,(puppet-rx (symbol (or "contain" "include" "require")) - (one-or-more space) - (group (symbol resource-name))) - 1 font-lock-type-face) - ;; Variable expansions in strings and comments - (puppet-match-valid-expansion 1 font-lock-variable-name-face t) - (puppet-match-invalid-expansion 1 font-lock-warning-face t) - ;; Escape sequences in strings - (puppet-match-valid-escape 1 'puppet-escape-sequence t) - ;; Regexp literals - (puppet-match-regexp-literal (1 'puppet-regular-expression-literal t) - (2 'puppet-regular-expression-literal t) - (3 'puppet-regular-expression-literal t))) - "Font lock keywords for Puppet Mode.") - -(defun puppet-match-property (property context limit) - "Match a PROPERTY in CONTEXT before LIMIT. - -PROPERTY is the text property to look for. CONTEXT is one of -`single-quoted', `double-quoted', `comment' or nil, or a list -with any of these symbols. The expansion will only match if it -is in any given CONTEXT. nil means no specific syntactic context." - (when (symbolp context) - (setq context (list context))) - (let* ((pos (next-single-char-property-change (point) property nil limit))) - (when (and pos (> pos (point))) - (goto-char pos) - (let* ((value (get-text-property pos property))) - (if (and value (memq (car value) context)) - (progn (set-match-data (cdr value)) t) - (puppet-match-property property context limit)))))) - -(defun puppet-match-valid-expansion (limit) - "Match a valid expansion before LIMIT. - -A valid expansion is a variable expansion in a double-quoted -string." - (let ((valid-contexts '(double-quoted))) - (when puppet-fontify-variables-in-comments - (push 'comment valid-contexts)) - (puppet-match-property 'puppet-expansion valid-contexts limit))) - -(defun puppet-match-invalid-expansion (limit) - "Match an invalid expansion before LIMIT. - -An invalid expansion is a variable expansion in a single-quoted -string." - (puppet-match-property 'puppet-expansion 'single-quoted limit)) - -(defun puppet-match-valid-escape (limit) - "Match a valid escape sequence before LIMIT." - (puppet-match-property 'puppet-escape 'double-quoted limit)) - -(defun puppet-match-regexp-literal (limit) - "Match a regular expression literal before LIMIT." - (puppet-match-property 'puppet-regexp-literal nil limit)) - -(defun puppet-syntax-propertize-match (property &optional group) - "Propertize a match with PROPERTY at GROUP's beginning. - -When in a special syntax context, add PROPERTY to the first -character of the given GROUP of the current `match-data'. GROUP -defaults to the first group. - -The value of PROPERTY is `(CONTEXT . MATCH-DATA)', where CONTEXT -is one of nil, `single-quoted', `double-quoted' or `comment' and -denotes the surrounding context, and MATCH-DATA is the original -match data from propertization." - (let* ((beg (match-beginning (or group 1))) - ;; Syntax functions can modify the match data, so we must preserve it - (context (save-match-data (puppet-syntax-context beg)))) - (put-text-property beg (1+ beg) property - (cons context (match-data))))) - -(defun puppet-syntax-propertize-scope-operator (beg end) - "Mark all scope operators between BEG and END as symbols." - (save-match-data - (save-excursion - (goto-char beg) - (while (search-forward "::" end 'no-error) - (put-text-property (match-beginning 0) (match-end 0) - 'syntax-table (string-to-syntax "_")))))) - -(defun puppet-syntax-propertize-function (start end) - "Propertize text between START and END. - -Used as `syntax-propertize-function' in Puppet Mode." - (let ((case-fold-search nil)) - (goto-char start) - (remove-text-properties start end '(puppet-expansion - puppet-escape - puppet-regexp-literal)) - (funcall - (syntax-propertize-rules - ;; Make double colons part of the surrounding symbol. We can't put the - ;; colon into symbol syntax, because the colon can appear as non-symbol - ;; character as well (e.g. "package { $foo:"), but we want the - ;; double-colon as part of the symbol to make symbol navigation move - ;; across it, and to make stuff like `thing-at-point' behave reasonably - ((rx "::" symbol-start) (0 "_")) - ;; Mark regular expression literals in proper contexts (nodes, cases, - ;; selectors and match operators) as strings, to make them play nicely - ;; with sexp navigation and SMIE. Also propertize them for use in font - ;; lock keywords, since we want to apply our own - ;; puppet-regular-expression-literal face instead of the generic string - ;; face. - ((puppet-rx (group "/") - (group regexp-literal) - (group "/") - (zero-or-more space) - (or ":" "=>")) - ;; We propertize the body of the regexp literal, not its delimiters, to - ;; make sure that font lock keywords kick in when the literal gets moved - ;; with point on separator. The separator is propertized by syntactic - ;; font lock (since we marked it as string delimiter), so font lock - ;; keywords will start in the body of the literal. If we'd propertize - ;; the separator, font lock keywords would miss the property - (0 (ignore (puppet-syntax-propertize-match 'puppet-regexp-literal 2))) - (1 "|") (3 "|")) - ((puppet-rx (or "=~" "!~" (symbol "node")) (zero-or-more space) - (group "/") - (group regexp-literal) - (group "/")) - (0 (ignore (puppet-syntax-propertize-match 'puppet-regexp-literal 2))) - (1 "|") (3 "|")) - ;; Find escape sequences and variable expansions. - ((puppet-rx dq-escape) - (1 (ignore (puppet-syntax-propertize-match 'puppet-escape)))) - ((puppet-rx (or line-start (not (any "\\"))) - (zero-or-more "\\\\") - ;; We can't use symbol boundaries here, because - ;; `syntax-propertize-rules' applies all rules at the same - ;; time, so the double-colon scope separator isn't yet part of - ;; the symbol at this point. - (group "$" (or (and "{" variable-name "}") variable-name))) - (1 (ignore (progn - (puppet-syntax-propertize-match 'puppet-expansion) - ;; Propertize all scope operators in the current variable - (puppet-syntax-propertize-scope-operator - (match-beginning 0) (match-end 0))))))) - start end))) - - -;;; Alignment - -;; Configure alignment -(add-to-list 'align-sq-string-modes 'puppet-mode) -(add-to-list 'align-dq-string-modes 'puppet-mode) -(add-to-list 'align-open-comment-modes 'puppet-mode) - -(defconst puppet-mode-align-rules - '((puppet-resource-arrow - (regexp . "\\(\\s-*\\)=>\\(\\s-*\\)") - (group . (1 2)) - (modes . '(puppet-mode)) - (separate . entire))) - "Align rules for Puppet Mode.") - -(defconst puppet-mode-align-exclude-rules - '((puppet-nested - (regexp . "\\s-*=>\\s-*\\({[^}]*}\\)") - (modes . '(puppet-mode)) - (separate . entire)) - (puppet-comment - (regexp . "^\\s-*\#\\(.*\\)") - (modes . '(puppet-mode)))) - "Rules for excluding lines from alignment for Puppet Mode.") - -(defun puppet-align-block () - "Align the current block." - (interactive) - (save-excursion - (backward-up-list) - (let ((beg (point))) - (forward-list) - (align beg (point))))) - - -;;; Dealing with strings -(defun puppet-looking-around (back at) - "Check if looking backwards at BACK and forward at AT." - (and (looking-at-p at) (looking-back back nil))) - -(defun puppet-string-at-point-p () - "Check if cursor is at a string or not." - (puppet-string-region)) - -(defun puppet-string-region () - "Return region for string at point." - (let ((orig-point (point)) (regex "'\\(\\(\\\\'\\)\\|[^']\\)*'\\|\"\\(\\(\\\\\"\\)\\|[^\"]\\)*\"") beg end) - (save-excursion - (goto-char (line-beginning-position)) - (while (and (re-search-forward regex (line-end-position) t) (not (and beg end))) - (let ((match-beg (match-beginning 0)) (match-end (match-end 0))) - (when (and - (> orig-point match-beg) - (< orig-point match-end)) - (setq beg match-beg) - (setq end match-end)))) - (and beg end (list beg end))))) - -(defun puppet-interpolate (suppress) - "Interpolate with ${} in double quoted strings. - -With a prefix argument SUPPRESS it simply inserts $." - (interactive "P") - (if (and mark-active (equal (point) (region-end))) - (exchange-point-and-mark)) - (insert "$") - (when (and - (not suppress) - (or - (puppet-looking-around "\"[^\"\n]*" "[^\"\n]*\"") - (puppet-looking-around "`[^`\n]*" "[^`\n]*`") - (puppet-looking-around "%([^(\n]*" "[^)\n]*)"))) - (cond (mark-active - (goto-char (region-beginning)) - (insert "{") - (goto-char (region-end)) - (insert "}")) - (t - (insert "{}") - (forward-char -1))))) - -(defun puppet-toggle-string-quotes () - "Toggle string literal quoting between single and double." - (interactive) - (when (puppet-string-at-point-p) - (let* ((region (puppet-string-region)) - (min (nth 0 region)) - (max (nth 1 region)) - (string-quote (puppet--inverse-string-quote (buffer-substring-no-properties min (1+ min)))) - (content - (buffer-substring-no-properties (1+ min) (1- max)))) - (setq content - (if (equal string-quote "\"") - (replace-regexp-in-string "\\\\\"" "\"" (replace-regexp-in-string "\\([^\\\\]\\)'" "\\1\\\\'" content)) - (replace-regexp-in-string "\\\\\'" "'" (replace-regexp-in-string "\\([^\\\\]\\)\"" "\\1\\\\\"" content)))) - (let ((orig-point (point))) - (delete-region min max) - (insert - (format "%s%s%s" string-quote content string-quote)) - (goto-char orig-point))))) - -(defun puppet--inverse-string-quote (string-quote) - "Get the inverse string quoting for STRING-QUOTE." - (if (equal string-quote "\"") "'" "\"")) - -(defun puppet-clear-string () - "Clear string at point." - (interactive) - (when (puppet-string-at-point-p) - (let* ((region (puppet-string-region)) - (min (nth 0 region)) - (max (nth 1 region))) - (delete-region (+ min 1) (- max 1))))) - - - -;;; Imenu - -(defun puppet-imenu-collect-entries (pattern) - "Collect all index entries matching PATTERN. - -The first matching group of PATTERN is used as title and position -for each entry." - (goto-char (point-min)) - (let ((case-fold-search nil) - entries) - (while (re-search-forward pattern nil 'no-error) - (let ((entry (cons (match-string 1) (match-beginning 1)))) - (unless (puppet-in-string-or-comment-p (match-beginning 0)) - ;; Skip this match if it's inside a string or comment - (push entry entries)))) - (nreverse entries))) - -(defun puppet-imenu-create-index () - "Create an IMenu index for the current buffer." - (let ((case-fold-search nil) - ;; Variable assignments - (variables (puppet-imenu-collect-entries - (puppet-rx (group "$" (symbol simple-variable-name)) - (zero-or-more space) "="))) - ;; Resource defaults - (defaults (puppet-imenu-collect-entries - (puppet-rx (group (symbol cap-resource-name)) - (zero-or-more space) "{"))) - ;; Nodes, classes and defines - (nodes (puppet-imenu-collect-entries - (puppet-rx (symbol "node") - (one-or-more space) - (group (symbol node-name))))) - (classes (puppet-imenu-collect-entries - (puppet-rx (symbol "class") - (one-or-more space) - (group (symbol resource-name))))) - (defines (puppet-imenu-collect-entries - (puppet-rx (symbol "define") - (one-or-more space) - (group (symbol resource-name))))) - resources) - ;; Resources are a little more complicated since we need to extract the type - ;; and the name - (goto-char (point-min)) - (while (re-search-forward - (puppet-rx (group (repeat 0 2 "@") ; Virtual and exported resources - (symbol resource-name)) - (zero-or-more space) "{" - ;; FIXME: Support condensed forms - (zero-or-more space) - (group (one-or-more not-newline)) ":") - nil 'no-error) - ;; FIXME: Doesn't work for any condensed forms, see - ;; http://docs.puppetlabs.com/puppet/latest/reference/lang_resources.html#condensed-forms - ;; We probably need to be more clever here - (push (cons (concat (match-string 1) " " (match-string 2)) - (match-beginning 1)) - resources)) - (let (index - ;; Keep this in reversed order, for `push' - (parts (list (cons "Variables" variables) - (cons "Defaults" defaults) - (cons "Definitions" defines) - (cons "Classes" classes) - (cons "Nodes" nodes)))) - (dolist (part parts) - (when (cdr part) - (push part index))) - (append index (nreverse resources))))) - - -;;; Major mode definition - -(defvar puppet-mode-map - (let ((map (make-sparse-keymap))) - ;; Editing - (define-key map (kbd "C-c C-a") #'puppet-align-block) - (define-key map (kbd "C-c C-'") #'puppet-toggle-string-quotes) - (define-key map (kbd "C-c C-;") #'puppet-clear-string) - (define-key map (kbd "$") #'puppet-interpolate) - ;; Navigation - (define-key map (kbd "C-c C-j") #'imenu) - ;; Apply manifests - (define-key map (kbd "C-c C-c") #'puppet-apply) - ;; REPL stuff - (define-key map (kbd "C-c C-z") #'puppet-repl) - (define-key map (kbd "C-c C-r") #'puppet-repl-send-region) - (define-key map (kbd "C-c C-b") #'puppet-repl-send-buffer) - ;; Linting and validation - (define-key map (kbd "C-c C-v") #'puppet-validate) - (define-key map (kbd "C-c C-l") #'puppet-lint) - ;; The menu bar - (easy-menu-define puppet-menu map "Puppet Mode menu" - `("Puppet" - :help "Puppet-specific Features" - ["Align the current block" puppet-align-block - :help "Align parameters in the current block"] - ["Clear string" puppet-clear-string - :help "Clear the string at point"] - ["Toggle string quotes" puppet-toggle-string-quotes - :help "Toggle the string at point quotes between single and double"] - "-" - ["Jump to resource/variable" imenu - :help "Jump to a resource or variable"] - "-" - ["Apply manifest" puppet-apply :help "Apply a Puppet manifest"] - "-" - ["Puppet REPL" puppet-repl :help "Start the Puppet REPL"] - ["Send Region to REPL" puppet-repl-send-region - :help "Send this region to the the Puppet REPL"] - ["Send Line to REPL" puppet-repl-send-line - :help "Send this line to the the Puppet REPL"] - ["Send Buffer to REPL" puppet-repl-send-buffer - :help "Send this buffer to the the Puppet REPL"] - "-" - ["Validate file syntax" puppet-validate - :help "Validate the syntax of this file"] - ["Lint file" puppet-lint - :help "Check the file for semantic issues"])) - map) - "Key map for Puppet Mode buffers.") - -;;;###autoload -(define-derived-mode puppet-mode prog-mode "Puppet" () - "Major mode for editing Puppet manifests. - -\\{puppet-mode-map}" - ;; Comment setup - (setq-local comment-start "# ") - (setq-local comment-start-skip "#+ *") - (setq-local comment-use-syntax t) - (setq-local comment-end "") - (setq-local comment-auto-fill-only-comments t) - (setq comment-column puppet-comment-column) - ;; Navigation (TODO: Will we still need this with SMIE?) - (setq-local beginning-of-defun-function #'puppet-beginning-of-defun-function) - ;; Indentation - (setq-local indent-line-function #'puppet-indent-line) - (setq indent-tabs-mode puppet-indent-tabs-mode) - ;; Paragaphs - (setq-local paragraph-ignore-fill-prefix t) - (setq-local paragraph-start "\f\\|[ \t]*$\\|#$") - (setq-local paragraph-separate "\\([ \t\f]*\\|#\\)$") - ;; Font locking - (setq font-lock-defaults '((puppet-font-lock-keywords) nil nil)) - (setq-local syntax-propertize-function #'puppet-syntax-propertize-function) - ;; Alignment - (setq align-mode-rules-list puppet-mode-align-rules) - (setq align-mode-exclude-rules-list puppet-mode-align-exclude-rules) - ;; IMenu - (setq imenu-create-index-function #'puppet-imenu-create-index)) - -;;;###autoload -(add-to-list 'auto-mode-alist '("\\.pp\\'" . puppet-mode)) - -(provide 'puppet-mode) - -;; Local Variables: -;; indent-tabs-mode: nil -;; End: - -;;; puppet-mode.el ends here diff --git a/elpa/puppet-mode-20210305.645/puppet-mode-autoloads.el b/elpa/puppet-mode-20210305.645/puppet-mode-autoloads.el new file mode 100644 index 00000000..a6a4625c --- /dev/null +++ b/elpa/puppet-mode-20210305.645/puppet-mode-autoloads.el @@ -0,0 +1,33 @@ +;;; puppet-mode-autoloads.el --- automatically extracted autoloads -*- lexical-binding: t -*- +;; +;;; Code: + +(add-to-list 'load-path (directory-file-name + (or (file-name-directory #$) (car load-path)))) + + +;;;### (autoloads nil "puppet-mode" "puppet-mode.el" (0 0 0 0)) +;;; Generated autoloads from puppet-mode.el + +(autoload 'puppet-mode "puppet-mode" "\ + + +\(fn)" t nil) + +(add-to-list 'auto-mode-alist '("\\.pp\\'" . puppet-mode)) + +(register-definition-prefixes "puppet-mode" '("puppet-")) + +;;;*** + +;;;### (autoloads nil nil ("puppet-mode-pkg.el") (0 0 0 0)) + +;;;*** + +;; Local Variables: +;; version-control: never +;; no-byte-compile: t +;; no-update-autoloads: t +;; coding: utf-8 +;; End: +;;; puppet-mode-autoloads.el ends here diff --git a/elpa/puppet-mode-20210305.645/puppet-mode-pkg.el b/elpa/puppet-mode-20210305.645/puppet-mode-pkg.el new file mode 100644 index 00000000..88cb8e83 --- /dev/null +++ b/elpa/puppet-mode-20210305.645/puppet-mode-pkg.el @@ -0,0 +1,18 @@ +(define-package "puppet-mode" "20210305.645" "Major mode for Puppet manifests" + '((emacs "24.1") + (pkg-info "0.4")) + :commit "ab25cf379236f4e1bd4bc9c1d77a93c95800e9bf" :authors + '(("Vox Pupuli" . "voxpupuli@groups.io") + ("Bozhidar Batsov" . "bozhidar@batsov.com") + ("Sebastian Wiesner" . "swiesner@lunaryorn.com") + ("Russ Allbery" . "rra@stanford.edu")) + :maintainers + '(("Vox Pupuli" . "voxpupuli@groups.io")) + :maintainer + '("Vox Pupuli" . "voxpupuli@groups.io") + :keywords + '("languages") + :url "https://github.com/voxpupuli/puppet-mode") +;; Local Variables: +;; no-byte-compile: t +;; End: diff --git a/elpa/puppet-mode-20210305.645/puppet-mode.el b/elpa/puppet-mode-20210305.645/puppet-mode.el new file mode 100644 index 00000000..a7b503b1 --- /dev/null +++ b/elpa/puppet-mode-20210305.645/puppet-mode.el @@ -0,0 +1,1293 @@ +;;; puppet-mode.el --- Major mode for Puppet manifests -*- lexical-binding: t; -*- + +;; Copyright (C) 2013-2014, 2016 Sebastian Wiesner +;; Copyright (C) 2013, 2014 Bozhidar Batsov +;; Copyright (C) 2011 Puppet Labs Inc + +;; Author: Vox Pupuli +;; Bozhidar Batsov +;; Sebastian Wiesner +;; Russ Allbery +;; Maintainer: Vox Pupuli +;; Bozhidar Batsov +;; Sebastian Wiesner +;; Tim Meusel +;; URL: https://github.com/voxpupuli/puppet-mode +;; Keywords: languages +;; Version: 0.4 +;; Package-Requires: ((emacs "24.1") (pkg-info "0.4")) + +;; This file is not part of GNU Emacs. + +;; 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 3 of the License, 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 . + +;; This file incorporates work covered by the following copyright and +;; permission notice: + +;; Licensed under the Apache License, Version 2.0 (the "License"); you may not +;; use this file except in compliance with the License. You may obtain a copy +;; of the License at +;; +;; http://www.apache.org/licenses/LICENSE-2.0 +;; +;; Unless required by applicable law or agreed to in writing, software +;; distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +;; WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +;; License for the specific language governing permissions and limitations +;; under the License. + +;;; Commentary: + +;; GNU Emacs 24 major mode for editing Puppet manifests. + +;; Provides syntax highlighting, indentation, alignment, movement, Imenu and +;; code checking. + +;; Syntax highlighting: Fontification supports all of Puppet 3 syntax, including +;; variable expansion in strings. + +;; Indentation: Indent expressions automatically. + +;; Alignment: Provide alignment rules for common Puppet expressions, and align +;; the current block with `puppet-align-block' on C-c C-a. + +;; Movement: Move to the beginning or end of the current block with +;; `beginning-of-defun' (C-M-a) and `end-of-defun' (C-M-e) respectively. + +;; Imenu: Jump to a tag in the current buffer with `imenu' on C-c C-j. Index +;; variables, resource defaults, classes, nodes, defined types and resource +;; declarations. + +;; Code checking: Validate the syntax of the current buffer with +;; `puppet-validate' on C-c C-v. Lint the current buffer for semantic errors +;; with `puppet-lint' on C-c C-l. Apply the current buffer with `puppet-apply' +;; on C-c C-c. + +;; Syntax checking: Flymake support is _not_ provided. See Flycheck at +;; http://www.flycheck.org for on-the-fly validation and liniting of Puppet +;; manifests. + +;;; Code: + + +;;; Compatibility +(eval-and-compile + ;; `defvar-local' for Emacs 24.2 and below + (unless (fboundp 'defvar-local) + (defmacro defvar-local (var val &optional docstring) + "Define VAR as a buffer-local variable with default value VAL. +Like `defvar' but additionally marks the variable as being automatically +buffer-local wherever it is set." + (declare (debug defvar) (doc-string 3)) + `(progn + (defvar ,var ,val ,docstring) + (make-variable-buffer-local ',var)))) + + ;; `setq-local' for Emacs 24.2 and below + (unless (fboundp 'setq-local) + (defmacro setq-local (var val) + "Set variable VAR to value VAL in current buffer." + `(set (make-local-variable ',var) ,val)))) + + +;;; Requirements +(declare-function pkg-info-version-info "pkg-info" (library)) + +(eval-when-compile + (require 'rx)) + +(require 'align) +(require 'ansi-color) +(require 'comint) + + +;;; Customization +(defgroup puppet nil + "Puppet mastering in Emacs" + :prefix "puppet-" + :group 'languages + :link '(url-link :tag "Github" "https://github.com/voxpupuli/puppet-mode") + :link '(emacs-commentary-link :tag "Commentary" "puppet-mode")) + +(defcustom puppet-indent-level 2 + "Indentation of Puppet statements." + :type 'integer + :group 'puppet + :safe 'integerp) + +(defcustom puppet-include-indent 2 + "Indentation of continued Puppet include statements." + :type 'integer + :group 'puppet + :safe 'integerp) + +(defcustom puppet-indent-tabs-mode nil + "Indentation can insert tabs in puppet mode if this is non-nil." + :type 'boolean + :group 'puppet + :safe 'booleanp) + +(defcustom puppet-comment-column 32 + "Indentation column of comments." + :type 'integer + :group 'puppet + :safe 'integerp) + +(defcustom puppet-fontify-variables-in-comments nil + "When non-nil, fontify variable references in comments." + :type 'boolean + :group 'puppet + :safe 'booleanp + :package-version '(puppet-mode . "0.4")) + +(defcustom puppet-validate-command "puppet parser validate --color=false" + "Command to validate the syntax of a Puppet manifest." + :type 'string + :group 'puppet) + +(defcustom puppet-lint-command + (concat + "puppet-lint --with-context " + "--log-format \"%{path}:%{line}: %{kind}: %{message} (%{check})\"") + "Command to lint a Puppet manifest." + :type 'string + :group 'puppet + :package-version '(puppet-mode . "0.4")) + +(defcustom puppet-apply-command "puppet apply --verbose --noop" + "Command to apply a Puppet manifest." + :type 'string + :group 'puppet + :package-version '(puppet-mode . "0.4")) + +(defcustom puppet-repl-command "puppet debugger" + "The Puppet REPL command used to interact with code." + :type 'string + :group 'puppet + :package-version '(puppet-mode . "0.4")) + +(defcustom puppet-repl-args '() + "The arguments to pass to `puppet-repl-command' to start a REPL." + :group 'puppet + :type '(repeat string) + :package-version '(puppet-mode . "0.4")) + +(defcustom puppet-repl-buffer "*Puppet-REPL*" + "The name of the Puppet REPL buffer." + :group 'puppet + :type 'string + :package-version '(puppet-mode . "0.4")) + +(defface puppet-regular-expression-literal + '((t :inherit font-lock-constant-face)) + "Face for regular expression literals in Puppet." + :group 'puppet + :package-version '(puppet-mode . "0.4")) + +(defface puppet-escape-sequence + '((t :inherit font-lock-constant-face)) + "Face for escape sequences in double-quoted strings-consed literals in Puppet." + :group 'puppet + :package-version '(puppet-mode . "0.4")) + + +;;; Version information +(defun puppet-version (&optional show-version) + "Get the Puppet Mode version as string. + +If called interactively or if SHOW-VERSION is non-nil, show the +version in the echo area and the messages buffer. + +The returned string includes both, the version from package.el +and the library version, if both a present and different. + +If the version number could not be determined, signal an error, +if called interactively, or if SHOW-VERSION is non-nil, otherwise +just return nil." + (interactive (list t)) + (let ((version (pkg-info-version-info 'puppet-mode))) + (when show-version + (message "Puppet Mode version: %s" version)) + version)) + + +;;; Utilities + +(defun puppet-syntax-context (&optional pos) + "Determine the syntax context at POS, defaulting to point. + +Return nil, if there is no special context at POS, or one of + +`comment' + POS is inside a comment + +`single-quoted' + POS is inside a single-quoted string + +`double-quoted' + POS is inside a double-quoted string" + (let ((state (save-excursion (syntax-ppss pos)))) + (if (nth 4 state) + 'comment + (pcase (nth 3 state) + (`?\' 'single-quoted) + (`?\" 'double-quoted))))) + +(defun puppet-in-string-or-comment-p (&optional pos) + "Determine whether POS is inside a string or comment." + (not (null (puppet-syntax-context pos)))) + +(defun puppet-get-repl-proc () + (unless (comint-check-proc puppet-repl-buffer) + (puppet-repl)) + (get-buffer-process puppet-repl-buffer)) + +(defun puppet-repl-send-region (start end) + "Send the current region to the inferior Puppet REPL process." + (interactive "r") + (deactivate-mark t) + (let* ((string (buffer-substring-no-properties start end)) + (proc (puppet-get-repl-proc))) + (comint-simple-send proc string))) + +(defun puppet-repl-send-line () + "Send the current line to the inferior Puppet REPL process." + (interactive) + (puppet-repl-send-region (line-beginning-position) (line-end-position))) + +(defun puppet-repl-send-buffer () + "Send the current buffer to the inferior Puppet REPL process." + (interactive) + (puppet-repl-send-region (point-min) (point-max))) + +(defun puppet-comint-filter (string) + (ansi-color-apply string)) + +(defun puppet-repl () + "Launch a Puppet REPL using `puppet-repl-command' as an inferior mode." + (interactive) + + ;; the command (at least for now) is 'puppet debugger' + ;; but really it is 'puppet' with args 'debugger' + puppet-repl-args + ;; Even if it changes, we need to not break on multi-word commands + (unless (comint-check-proc puppet-repl-buffer) + (let* ((command-list (split-string puppet-repl-command)) + (real-puppet-repl-command (car command-list)) + (real-puppet-repl-args (append (cdr command-list) + puppet-repl-args))) + (set-buffer + (apply 'make-comint "Puppet-REPL" + real-puppet-repl-command + nil + real-puppet-repl-args))) + ;; Workaround for ansi colors + (add-hook 'comint-preoutput-filter-functions 'puppet-comint-filter nil t)) + + (pop-to-buffer puppet-repl-buffer)) + +;;; Specialized rx + +(eval-when-compile + (defun puppet-rx-symbol (form) + "Translate FORM into a regular expression." + (let ((body (cdr form))) + (rx-to-string `(and symbol-start ,@body symbol-end) 'no-group))) + + (defconst puppet-rx-constituents + `((symbol puppet-rx-symbol 0 nil) + ;; http://docs.puppetlabs.com/puppet/3/reference/lang_datatypes.html#regular-expressions + (regexp-literal . ,(rx (zero-or-more + (or + ;; Not the end of a regexp + (not (any "/" "\\" "\n")) + ;; Any escaped character + (and "\\" not-newline))))) + ;; https://puppet.com/docs/puppet/latest/lang_reserved.html + (keyword . ,(rx (or "and" "application" "attr" "case" "class" "component" + "consumes" "default" "define" "else" "elsif" + "environment" "false" "function" "if" "import" "in" + "inherits" "node" "or" "private" "produces" "regexp" + "site" "true" "type" "undef" "unit" "unless" + ;; Bolt + ;; https://puppet.com/docs/bolt/0.x/writing_plans.html + "plan" + ))) + ;; https://puppet.com/docs/puppet/latest/function.html + (builtin-function . ,(rx (or "abs" "alert" "all" "annotate" "any" + "assert_type" "binary_file" "break" "call" + "camelcase" "capitalize" "ceiling" "chomp" + "chop" "compare" "contain" "convert_to" + "create_resources" "crit" "debug" "defined" + "dig" "digest" "downcase" "each" "emerg" + "empty" "epp" "err" "eyaml_lookup_key" + "fail" "file" "filter" "find_file" + "find_template" "flatten" "floor" + "fqdn_rand" "generate" "get" "getvar" + "group_by" "hiera" "hiera_array" + "hiera_hash" "hiera_include" "hocon_data" + "import" "include" "info" "inline_epp" + "inline_template" "join" "json_data" "keys" + "length" "lest" "lookup" "lstrip" "map" + "match" "max" "md5" "min" "new" "next" + "notice" "partition" "realize" "reduce" + "regsubst" "require" "return" "reverse_each" + "round" "rstrip" "scanf" "sha1" "sha256" + "shellquote" "size" "slice" "split" + "sprintf" "step" "strftime" "strip" "tag" + "tagged" "template" "tree_each" "then" + "type" "unique" "unwrap" "upcase" "values" + "versioncmp" "warning" "with" "yaml_data" + ;; Bolt + ;; https://puppet.com/docs/bolt/0.x/plan_functions.html + ;; https://puppet.com/docs/bolt/0.x/writing_plans.html#concept-4926 + "apply" "apply_prep" "add_facts" "facts" + "fail_plan" "file_upload" "get_targets" + "puppetdb_fact" "puppetdb_query" + "run_command" "run_plan" "run_script" + "run_task" "set_feature" "set_var" "vars" + "without_default_logging" + ))) + ;; http://docs.puppetlabs.com/references/latest/type.html + (builtin-type . ,(rx (or "augeas" "computer" "cron" "exec" "file" + "filebucket" "group" "host" "interface" "k5login" + "macauthorization" "mailalias" "maillist" "mcx" + "mount" "nagios_command" "nagios_contact" + "nagios_contactgroup" "nagios_host" + "nagios_hostdependency" "nagios_hostescalation" + "nagios_hostextinfo" "nagios_hostgroup" + "nagios_service" "nagios_servicedependency" + "nagios_serviceescalation" "nagios_serviceextinfo" + "nagios_servicegroup" "nagios_timeperiod" "notify" + "package" "resources" "router" "schedule" + "scheduled_task" "selboolean" "selmodule" + "service" "ssh_authorized_key" "sshkey" "stage" + "tidy" "user" "vlan" "yumrepo" "zfs" "zone" + "zpool"))) + ;; http://docs.puppetlabs.com/references/stable/metaparameter.html. + ;; Strictly speaking, this is no meta parameter, but it's so common that + ;; it got a mention in the docs, see + ;; http://docs.puppetlabs.com/puppet/latest/reference/lang_resources.html#ensure, + ;; so we'll consider it as metaparameter anyway + (builtin-metaparam . ,(rx (or "alias" "audit" "before" "consume" "export" + "loglevel" "noop" "notify" "require" + "schedule" "stage" "subscribe" "tag" + ;; Because it's so common and important + "ensure"))) + ;; https://github.com/puppetlabs/puppet-specifications/blob/master/language/types_values_variables.md + (data-type . ,(rx (or + ;; Data Types + "Array" "Binary" "Hash" + ;; Scalar Types + "Boolean" "Float" "Integer" "Regexp" "SemVer" "String" + "Timespan" "Timestamp" + ;; Catalog Types + "Class" "Resource" + ;; Abstract Types + "Any" "CatalogEntry" "Collection" "Data" "Enum" + "Iterable" "Iterator" "NotUndef" "Numeric" "Optional" + "Pattern" "RichData" "Scalar" "ScalarData" + "SemVerRange" "Struct" "Tuple" "Variant" + ;; Platform Types: + "Callable" "Default" "Runtime" "Sensitive" "Type" + "Undef" + ;; Bolt types: + ;; https://puppet.com/docs/bolt/0.x/writing_plans.html + "Error" "PlanResult" "Result" "ResultSet" "Target" + "TargetSpec" + ))) + ;; http://docs.puppetlabs.com/puppet/latest/reference/lang_reserved.html#classes-and-types + (resource-name . ,(rx + ;; Optional top-level scope + (optional "::") + (zero-or-more (any "a-z") + (zero-or-more (any "a-z" "0-9" "_")) + "::") + ;; Nested sub-scopes + (any "a-z") + (zero-or-more (any "a-z" "0-9" "_")))) + (cap-resource-name . ,(rx + ;; Top-scope indicator + (optional "::") + (zero-or-more (any "A-Z") + (zero-or-more + (any "a-z" "0-9" "_")) + "::") + ;; Nested sub-scopes + (any "A-Z") + (zero-or-more (any "a-z" "0-9" "_")))) + ;; http://docs.puppetlabs.com/puppet/latest/reference/lang_reserved.html#nodes + (node-name . ,(rx (one-or-more (any "a-z" "0-9" ?. ?_ ?-)))) + ;; http://docs.puppetlabs.com/puppet/latest/reference/lang_reserved.html#variables + (simple-variable-name . ,(rx (one-or-more (any "A-Z" "a-z" "0-9" "_")))) + (variable-name . ,(rx + ;; The optional scope designation + (optional "::") + (zero-or-more (any "a-z") + (zero-or-more + (any "A-Z" "a-z" "0-9" "_")) + "::") + ;; The final variable name + (one-or-more (any "A-Z" "a-z" "0-9" "_")))) + ;; http://docs.puppetlabs.com/puppet/latest/reference/lang_datatypes.html#double-quoted-strings + (dq-escape . ,(rx (or line-start (not (any "\\"))) + (zero-or-more "\\\\") + ;; We do not include \n and \', because these are + ;; available in single-quoted strings as well + (group "\\" (any ?\" ?$ ?n ?r ?t ?s))))) + "Additional special sexps for `puppet-rx'") + + (defmacro puppet-rx (&rest sexps) + "Specialized `rx' variant for Puppet Mode. + +In addition to the standard forms of `rx', the following forms +are available: + +`(symbol SEXP …)' + Match SEXPs inside symbol boundaries only + +`regexp-literal' + A Puppet regexp literal, *without* surrounding slashes + +`keyword' + Any valid Puppet keyword + +`builtin-function' + Any built-in Puppet function + +`builtin-type' + Any built-in Puppet type + +`builtin-metaparam' + Any built-in meta-parameter, and `ensure' + +`data-type' + Any Puppet data type + +`resource-name' + Any valid resource name, including scopes + +`cap-resource-name' + Any capitalized resource name, including capitalized scopes + +`node-name' + Any valid node name + +`simple-variable-name' + Any variable name without scopes, without leading dollar sign + +`variable-name' + Any variable name including scopes, without a leading dollar sign + +`dq-escape' + Special escape sequences for double-quoted strings" + (let ((rx-constituents (append puppet-rx-constituents rx-constituents))) + (cond ((null sexps) + (error "No regexp")) + ((cdr sexps) + (rx-to-string `(and ,@sexps) t)) + (t + (rx-to-string (car sexps) t)))))) + + +;;; Checking + +(defvar-local puppet-last-validate-command nil + "The last command used for validation.") + +(defvar-local puppet-last-lint-command nil + "The last command used for linting.") + +(defvar-local puppet-last-apply-command nil + "The last command used to apply a manifest.") + +(defun puppet-run-check-command (command buffer-name-template) + "Run COMMAND to check the current buffer." + (save-some-buffers (not compilation-ask-about-save) nil) + (compilation-start command nil (lambda (_) + (format buffer-name-template command)))) + +(defun puppet-read-command (prompt previous-command default-command) + "Read a command from minibuffer with PROMPT." + (let* ((buffer-file-name (or (buffer-file-name) "")) + (filename (or (file-remote-p buffer-file-name 'localname) + buffer-file-name))) + (read-string prompt (or previous-command + (concat default-command " " + (shell-quote-argument filename)))))) + +(defun puppet-validate (command) + "Validate the syntax of the current buffer with COMMAND. + +When called interactively, prompt for COMMAND." + (interactive (list (puppet-read-command "Validate command: " + puppet-last-validate-command + puppet-validate-command))) + (setq puppet-last-validate-command command) + (puppet-run-check-command command "*Puppet Validate: %s*")) + +(defun puppet-lint (command) + "Lint the current buffer with COMMAND. + +When called interactively, prompt for COMMAND." + (interactive (list (puppet-read-command "Lint command: " + puppet-last-lint-command + puppet-lint-command))) + (setq puppet-last-lint-command command) + (puppet-run-check-command command "*Puppet Lint: %s*")) + +(defun puppet-apply (command) + "Apply the current manifest with COMMAND. + +When called interactively, prompt for COMMAND." + (interactive (list (puppet-read-command "Apply command: " + puppet-last-apply-command + puppet-apply-command))) + (setq puppet-last-apply-command command) + (puppet-run-check-command command "*Puppet Apply: %s*")) + + +;;; Navigation +;; TODO: Check which of these are still needed for SMIE + +(defun puppet-beginning-of-defun-function (&optional arg) + "Move to the ARG'th beginning of a block." + (let* ((arg (or arg 1)) + (search (if (< arg 0) #'search-forward #'search-backward)) + (steps (abs arg))) + (while (> steps 0) + (let ((pos (funcall search "{" nil 'no-error))) + ;; Skip over strings and comments + (while (and pos (puppet-in-string-or-comment-p pos)) + (setq pos (funcall search "{" nil 'no-error))) + (if pos + (setq steps (1- steps)) + ;; Drop out of outer loop + (setq steps 0)))) + (when (< arg 0) + (backward-char)))) + + +;;; Indentation code +(defun puppet-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 + (let ((opoint (nth 1 (syntax-ppss)))) + (when (and opoint + (progn + (goto-char opoint) + (looking-at-p "{"))) + (current-indentation))))) + +(defun puppet-in-argument-list () + "If point is in an argument list, return the position of the opening '('. +If point is not in an argument list, return nil." + (puppet--in-listlike "(")) + +(defun puppet-in-array () + "If point is in an array, return the position of the opening '[' of +that array, else return nil." + (puppet--in-listlike "\\[")) + +(defun puppet--in-listlike (openstring) + "If point is in a listlike, return the position of the opening character of +it, else return nil. +OPENSTRING is a regexp string matching the opening character." + (save-excursion + (let ((opoint (nth 1 (syntax-ppss)))) + (when (and opoint + (progn + (goto-char opoint) + (looking-at-p openstring))) + opoint)))) + +(defun puppet-in-include () + "If point is in a continued list of include statements, return the position +of the initial include plus puppet-include-indent." + (save-excursion + (save-match-data + (let ((include-column nil) + (not-found t)) + (while not-found + (forward-line -1) + (cond + ((bobp) + (setq not-found nil)) + ((looking-at "^\\s-*include\\s-+.*,\\s-*$") + (setq include-column + (+ (current-indentation) puppet-include-indent)) + (setq not-found nil)) + ((not (looking-at ".*,\\s-*$")) + (setq not-found nil)))) + include-column)))) + +(defun puppet-indent-listlike (listtype closing-regex list-start) + ;; This line starts with an element from an array or parameter list. + ;; Indent to the same indentation as the first element of the list: + ;; + ;; $example = ['string1', 'string2', + ;; 'string3', 'string4'] + ;; $example = example('string1', + ;; 'string2') + (save-excursion + (if (looking-at closing-regex) + ;; Closing bracket on a line by itself. Align with opening bracket. + (progn + (goto-char list-start) + (if (or (save-excursion (forward-char) (eolp)) + ;; closing class parameter list: + (and (eq listtype 'arglist) + (save-excursion + (backward-sexp 2) + (looking-at "class.*")))) + (current-indentation) + (current-column))) + ;; Use normal indentation if the point is at the end of the line. + ;; + ;; $example => [ + ;; 'foo', + ;; 'bar', + ;; ] + (goto-char list-start) + (forward-char 1) + (if (eolp) + (+ (current-indentation) puppet-indent-level) + ;; Otherwise, attempt to align as described above. + (re-search-forward "\\S-") + (forward-char -1) + (current-column))))) + +(defun puppet-indent-array (array-start) + (puppet-indent-listlike 'array "^\\s-*],*" array-start)) + +(defun puppet-indent-arglist (arglist-start) + (puppet-indent-listlike 'arglist "^\\s-*),*" arglist-start)) + +(defun puppet-indent-line () + "Indent current line as puppet code." + (interactive) + (let ((pos (- (point-max) (point)))) + (beginning-of-line) + (if (bobp) + (indent-line-to 0) ; First line is always non-indented + (let ((not-indented t) + (arglist-start (puppet-in-argument-list)) + (array-start (puppet-in-array)) + (include-start (puppet-in-include)) + (block-indent (puppet-block-indent)) + cur-indent) + (cond + (array-start (setq cur-indent (puppet-indent-array array-start))) + (arglist-start (setq cur-indent (puppet-indent-arglist arglist-start))) + (include-start + (setq cur-indent include-start)) + + ((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)) + (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. + ((or (eq (puppet-syntax-context) 'comment) + (save-excursion (end-of-line) + (eq (puppet-syntax-context) 'comment))) + (if (bobp) + (setq not-indented nil))) + + ;; Closing paren. Use indentation based on start of + ;; argument list + ((or (looking-at "^\\s-*\)\\s-*$") + (looking-at "^[^\n\(]*[\)],?\\s-*$")) + (goto-char (puppet-in-argument-list)) + (setq cur-indent (current-indentation)) + (setq not-indented nil)) + + ;; Closing bracket. Use indentation based on start of + ;; array. + ((looking-at "^[^[\n]*],?\\s-*$") + (goto-char (puppet-in-array)) + (setq cur-indent (current-indentation)) + (setq not-indented nil)) + + ;; Brace, paren or bracket (possibly followed by a comma) + ;; on a line by itself will already be indented to the + ;; right level, so we can cheat and stop there. + ((looking-at "^\\s-*[])}]\\(,\\|\\s-*[-~]>\\)?\\s-*\s?$") + (setq cur-indent (current-indentation)) + (setq not-indented nil)) + + ;; Brace (possibly followed by a comma) or paren not on a line by + ;; itself will be indented one level too much, but don't catch + ;; cases where the block is started and closed on the same line. + ((looking-at "^[^\n\({]*[\)}],?\\s-*$") + (setq cur-indent (- (current-indentation) puppet-indent-level)) + (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) puppet-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) puppet-indent-level)) + (setq not-indented nil)) + + ;; Semicolon ends a block for a resource when multiple resources + ;; are defined in the same block, but try not to get the case of + ;; a complete resource on a single line wrong. + ((looking-at "^\\([^'\":\n]\\|\"[^\n\"]*\"\\|'[^\n']*'\\)*;\\s-*$") + (setq cur-indent (- (current-indentation) puppet-indent-level)) + (setq not-indented nil)) + + ;; Indent an extra level after : since it introduces a resource. + ((looking-at "^.*:\\s-*$") + (setq cur-indent (+ (current-indentation) puppet-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 puppet-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)))) + ;; If initial point was within line's indentation, + ;; position after the indentation. Else stay at same point in text. + (if (> (- (point-max) pos) (point)) + (goto-char (- (point-max) pos))))) + + +;;; Font locking + +(defvar puppet-mode-syntax-table + (let ((table (make-syntax-table))) + ;; Our strings + (modify-syntax-entry ?\' "\"'" table) + (modify-syntax-entry ?\" "\"\"" table) + ;; C-style comments. Yes, Puppet has these! + (modify-syntax-entry ?/ ". 14b" table) + (modify-syntax-entry ?* ". 23b" table) + ;; Line comments + (modify-syntax-entry ?# "<" table) + (modify-syntax-entry ?\n ">" table) + ;; The backslash is our escape character + (modify-syntax-entry ?\\ "\\" table) + ;; The dollar sign is an expression prefix for variables + (modify-syntax-entry ?$ "'" table) + ;; Fix various operators and punctionation. + (modify-syntax-entry ?< "." table) + (modify-syntax-entry ?> "." table) + (modify-syntax-entry ?& "." table) + (modify-syntax-entry ?| "." table) + (modify-syntax-entry ?% "." table) + (modify-syntax-entry ?= "." table) + (modify-syntax-entry ?+ "." table) + (modify-syntax-entry ?- "." table) + (modify-syntax-entry ?\; "." table) + ;; Our parenthesis, braces and brackets + (modify-syntax-entry ?\( "()" table) + (modify-syntax-entry ?\) ")(" table) + (modify-syntax-entry ?\{ "(}" table) + (modify-syntax-entry ?\} "){" table) + (modify-syntax-entry ?\[ "(]" table) + (modify-syntax-entry ?\] ")[" table) + table) + "Syntax table in use in `puppet-mode' buffers.") + +(defvar puppet-font-lock-keywords + `( + ;; Keywords + (,(puppet-rx (symbol keyword)) 0 font-lock-keyword-face) + ;; Data Types + (,(puppet-rx (symbol data-type)) 0 font-lock-type-face) + ;; Variables + (,(puppet-rx "$" (symbol variable-name)) 0 font-lock-variable-name-face) + ;; Class and type declarations + (,(puppet-rx (symbol (or "class" "define" "plan")) + (one-or-more space) + (group (symbol resource-name))) + 1 font-lock-type-face) + ;; Node declarations + (,(puppet-rx (symbol "node") + (one-or-more space) + (group node-name)) + 1 font-lock-type-face) + ;; Resource usage, see + ;; http://docs.puppetlabs.com/puppet/latest/reference/lang_resources.html + (,(puppet-rx (group (repeat 0 2 "@") ; Virtual and exported resources + (symbol resource-name)) + (zero-or-more space) "{") + 1 font-lock-type-face) + ;; Resource defaults, see + ;; http://docs.puppetlabs.com/puppet/latest/reference/lang_defaults.html + (,(puppet-rx (group (symbol cap-resource-name)) (zero-or-more space) "{") + 1 font-lock-type-face) + ;; Resource references, see + ;; http://docs.puppetlabs.com/puppet/latest/reference/lang_datatypes.html#resource-references + (,(puppet-rx (group (symbol cap-resource-name)) (zero-or-more space) "[") + 1 font-lock-type-face) + ;; Resource collectors, see + ;; http://docs.puppetlabs.com/puppet/latest/reference/lang_collectors.html + (,(puppet-rx (group (symbol cap-resource-name)) (zero-or-more space) + (optional "<") ; Exported collector + "<|") + 1 font-lock-type-face) + ;; Negation + ("!" 0 font-lock-negation-char-face) + ;; Builtin meta parameters + (,(puppet-rx (group (symbol builtin-metaparam)) (zero-or-more space) "=>") + 1 font-lock-builtin-face) + ;; Built-in functions + (,(puppet-rx (symbol builtin-function)) 0 font-lock-builtin-face) + ;; Type arguments to some special built-in functions + (,(puppet-rx (symbol (or "contain" "include" "require")) + (one-or-more space) + (group (symbol resource-name))) + 1 font-lock-type-face) + ;; Variable expansions in strings and comments + (puppet-match-valid-expansion 1 font-lock-variable-name-face t) + (puppet-match-invalid-expansion 1 font-lock-warning-face t) + ;; Escape sequences in strings + (puppet-match-valid-escape 1 'puppet-escape-sequence t) + ;; Regexp literals + (puppet-match-regexp-literal (1 'puppet-regular-expression-literal t) + (2 'puppet-regular-expression-literal t) + (3 'puppet-regular-expression-literal t))) + "Font lock keywords for Puppet Mode.") + +(defun puppet-match-property (property context limit) + "Match a PROPERTY in CONTEXT before LIMIT. + +PROPERTY is the text property to look for. CONTEXT is one of +`single-quoted', `double-quoted', `comment' or nil, or a list +with any of these symbols. The expansion will only match if it +is in any given CONTEXT. nil means no specific syntactic context." + (when (symbolp context) + (setq context (list context))) + (let* ((pos (next-single-char-property-change (point) property nil limit))) + (when (and pos (> pos (point))) + (goto-char pos) + (let* ((value (get-text-property pos property))) + (if (and value (memq (car value) context)) + (progn (set-match-data (cdr value)) t) + (puppet-match-property property context limit)))))) + +(defun puppet-match-valid-expansion (limit) + "Match a valid expansion before LIMIT. + +A valid expansion is a variable expansion in a double-quoted +string." + (let ((valid-contexts '(double-quoted))) + (when puppet-fontify-variables-in-comments + (push 'comment valid-contexts)) + (puppet-match-property 'puppet-expansion valid-contexts limit))) + +(defun puppet-match-invalid-expansion (limit) + "Match an invalid expansion before LIMIT. + +An invalid expansion is a variable expansion in a single-quoted +string." + (puppet-match-property 'puppet-expansion 'single-quoted limit)) + +(defun puppet-match-valid-escape (limit) + "Match a valid escape sequence before LIMIT." + (puppet-match-property 'puppet-escape 'double-quoted limit)) + +(defun puppet-match-regexp-literal (limit) + "Match a regular expression literal before LIMIT." + (puppet-match-property 'puppet-regexp-literal nil limit)) + +(defun puppet-syntax-propertize-match (property &optional group) + "Propertize a match with PROPERTY at GROUP's beginning. + +When in a special syntax context, add PROPERTY to the first +character of the given GROUP of the current `match-data'. GROUP +defaults to the first group. + +The value of PROPERTY is `(CONTEXT . MATCH-DATA)', where CONTEXT +is one of nil, `single-quoted', `double-quoted' or `comment' and +denotes the surrounding context, and MATCH-DATA is the original +match data from propertization." + (let* ((beg (match-beginning (or group 1))) + ;; Syntax functions can modify the match data, so we must preserve it + (context (save-match-data (puppet-syntax-context beg)))) + (put-text-property beg (1+ beg) property + (cons context (match-data))))) + +(defun puppet-syntax-propertize-scope-operator (beg end) + "Mark all scope operators between BEG and END as symbols." + (save-match-data + (save-excursion + (goto-char beg) + (while (search-forward "::" end 'no-error) + (put-text-property (match-beginning 0) (match-end 0) + 'syntax-table (string-to-syntax "_")))))) + +(defun puppet-syntax-propertize-function (start end) + "Propertize text between START and END. + +Used as `syntax-propertize-function' in Puppet Mode." + (let ((case-fold-search nil)) + (goto-char start) + (remove-text-properties start end '(puppet-expansion + puppet-escape + puppet-regexp-literal)) + (funcall + (syntax-propertize-rules + ;; Make double colons part of the surrounding symbol. We can't put the + ;; colon into symbol syntax, because the colon can appear as non-symbol + ;; character as well (e.g. "package { $foo:"), but we want the + ;; double-colon as part of the symbol to make symbol navigation move + ;; across it, and to make stuff like `thing-at-point' behave reasonably + ((rx "::" symbol-start) (0 "_")) + ;; Mark regular expression literals in proper contexts (nodes, cases, + ;; selectors and match operators) as strings, to make them play nicely + ;; with sexp navigation and SMIE. Also propertize them for use in font + ;; lock keywords, since we want to apply our own + ;; puppet-regular-expression-literal face instead of the generic string + ;; face. + ((puppet-rx (group "/") + (group regexp-literal) + (group "/") + (zero-or-more space) + (or ":" "=>")) + ;; We propertize the body of the regexp literal, not its delimiters, to + ;; make sure that font lock keywords kick in when the literal gets moved + ;; with point on separator. The separator is propertized by syntactic + ;; font lock (since we marked it as string delimiter), so font lock + ;; keywords will start in the body of the literal. If we'd propertize + ;; the separator, font lock keywords would miss the property + (0 (ignore (puppet-syntax-propertize-match 'puppet-regexp-literal 2))) + (1 "|") (3 "|")) + ((puppet-rx (or "=~" "!~" (symbol "node")) (zero-or-more space) + (group "/") + (group regexp-literal) + (group "/")) + (0 (ignore (puppet-syntax-propertize-match 'puppet-regexp-literal 2))) + (1 "|") (3 "|")) + ;; Find escape sequences and variable expansions. + ((puppet-rx dq-escape) + (1 (ignore (puppet-syntax-propertize-match 'puppet-escape)))) + ((puppet-rx (or line-start (not (any "\\"))) + (zero-or-more "\\\\") + ;; We can't use symbol boundaries here, because + ;; `syntax-propertize-rules' applies all rules at the same + ;; time, so the double-colon scope separator isn't yet part of + ;; the symbol at this point. + (group "$" (or (and "{" variable-name "}") variable-name))) + (1 (ignore (progn + (puppet-syntax-propertize-match 'puppet-expansion) + ;; Propertize all scope operators in the current variable + (puppet-syntax-propertize-scope-operator + (match-beginning 0) (match-end 0))))))) + start end))) + + +;;; Alignment + +;; Configure alignment +(add-to-list 'align-sq-string-modes 'puppet-mode) +(add-to-list 'align-dq-string-modes 'puppet-mode) +(add-to-list 'align-open-comment-modes 'puppet-mode) + +(defconst puppet-mode-align-rules + '((puppet-resource-arrow + (regexp . "\\(\\s-*\\)=>\\(\\s-*\\)") + (group . (1 2)) + (modes . '(puppet-mode)) + (separate . entire))) + "Align rules for Puppet Mode.") + +(defconst puppet-mode-align-exclude-rules + '((puppet-nested + (regexp . "\\s-*=>\\s-*\\({[^}]*}\\)") + (modes . '(puppet-mode)) + (separate . entire)) + (puppet-comment + (regexp . "^\\s-*\#\\(.*\\)") + (modes . '(puppet-mode)))) + "Rules for excluding lines from alignment for Puppet Mode.") + +(defun puppet-align-block () + "Align the current block." + (interactive) + (save-excursion + (backward-up-list) + (let ((beg (point))) + (forward-list) + (align beg (point))))) + + +;;; Dealing with strings +(defun puppet-looking-around (back at) + "Check if looking backwards at BACK and forward at AT." + (and (looking-at-p at) (looking-back back nil))) + +(defun puppet-string-at-point-p () + "Check if cursor is at a string or not." + (puppet-string-region)) + +(defun puppet-string-region () + "Return region for string at point." + (let ((orig-point (point)) (regex "'\\(\\(\\\\'\\)\\|[^']\\)*'\\|\"\\(\\(\\\\\"\\)\\|[^\"]\\)*\"") beg end) + (save-excursion + (goto-char (line-beginning-position)) + (while (and (re-search-forward regex (line-end-position) t) (not (and beg end))) + (let ((match-beg (match-beginning 0)) (match-end (match-end 0))) + (when (and + (> orig-point match-beg) + (< orig-point match-end)) + (setq beg match-beg) + (setq end match-end)))) + (and beg end (list beg end))))) + +(defun puppet-interpolate (suppress) + "Interpolate with ${} in double quoted strings. + +With a prefix argument SUPPRESS it simply inserts $." + (interactive "P") + (if (and mark-active (equal (point) (region-end))) + (exchange-point-and-mark)) + (insert "$") + (when (and + (not suppress) + (or + (puppet-looking-around "\"[^\"\n]*" "[^\"\n]*\"") + (puppet-looking-around "`[^`\n]*" "[^`\n]*`") + (puppet-looking-around "%([^(\n]*" "[^)\n]*)"))) + (cond (mark-active + (goto-char (region-beginning)) + (insert "{") + (goto-char (region-end)) + (insert "}")) + (t + (insert "{}") + (forward-char -1))))) + +(defun puppet-toggle-string-quotes () + "Toggle string literal quoting between single and double." + (interactive) + (when (puppet-string-at-point-p) + (let* ((region (puppet-string-region)) + (min (nth 0 region)) + (max (nth 1 region)) + (string-quote (puppet--inverse-string-quote (buffer-substring-no-properties min (1+ min)))) + (content + (buffer-substring-no-properties (1+ min) (1- max)))) + (setq content + (if (equal string-quote "\"") + (replace-regexp-in-string "\\\\\"" "\"" (replace-regexp-in-string "\\([^\\\\]\\)'" "\\1\\\\'" content)) + (replace-regexp-in-string "\\\\\'" "'" (replace-regexp-in-string "\\([^\\\\]\\)\"" "\\1\\\\\"" content)))) + (let ((orig-point (point))) + (delete-region min max) + (insert + (format "%s%s%s" string-quote content string-quote)) + (goto-char orig-point))))) + +(defun puppet--inverse-string-quote (string-quote) + "Get the inverse string quoting for STRING-QUOTE." + (if (equal string-quote "\"") "'" "\"")) + +(defun puppet-clear-string () + "Clear string at point." + (interactive) + (when (puppet-string-at-point-p) + (let* ((region (puppet-string-region)) + (min (nth 0 region)) + (max (nth 1 region))) + (delete-region (+ min 1) (- max 1))))) + + + +;;; Imenu + +(defun puppet-imenu-collect-entries (pattern) + "Collect all index entries matching PATTERN. + +The first matching group of PATTERN is used as title and position +for each entry." + (goto-char (point-min)) + (let ((case-fold-search nil) + entries) + (while (re-search-forward pattern nil 'no-error) + (let ((entry (cons (match-string 1) (match-beginning 1)))) + (unless (puppet-in-string-or-comment-p (match-beginning 0)) + ;; Skip this match if it's inside a string or comment + (push entry entries)))) + (nreverse entries))) + +(defun puppet-imenu-create-index () + "Create an IMenu index for the current buffer." + (let ((case-fold-search nil) + ;; Variable assignments + (variables (puppet-imenu-collect-entries + (puppet-rx (group "$" (symbol simple-variable-name)) + (zero-or-more space) "="))) + ;; Resource defaults + (defaults (puppet-imenu-collect-entries + (puppet-rx (group (symbol cap-resource-name)) + (zero-or-more space) "{"))) + ;; Nodes, classes and defines + (nodes (puppet-imenu-collect-entries + (puppet-rx (symbol "node") + (one-or-more space) + (group (symbol node-name))))) + (classes (puppet-imenu-collect-entries + (puppet-rx (symbol "class") + (one-or-more space) + (group (symbol resource-name))))) + (defines (puppet-imenu-collect-entries + (puppet-rx (symbol "define") + (one-or-more space) + (group (symbol resource-name))))) + resources) + ;; Resources are a little more complicated since we need to extract the type + ;; and the name + (goto-char (point-min)) + (while (re-search-forward + (puppet-rx (group (repeat 0 2 "@") ; Virtual and exported resources + (symbol resource-name)) + (zero-or-more space) "{" + ;; FIXME: Support condensed forms + (zero-or-more space) + (group (one-or-more not-newline)) ":") + nil 'no-error) + ;; FIXME: Doesn't work for any condensed forms, see + ;; http://docs.puppetlabs.com/puppet/latest/reference/lang_resources.html#condensed-forms + ;; We probably need to be more clever here + (push (cons (concat (match-string 1) " " (match-string 2)) + (match-beginning 1)) + resources)) + (let (index + ;; Keep this in reversed order, for `push' + (parts (list (cons "Variables" variables) + (cons "Defaults" defaults) + (cons "Definitions" defines) + (cons "Classes" classes) + (cons "Nodes" nodes)))) + (dolist (part parts) + (when (cdr part) + (push part index))) + (append index (nreverse resources))))) + + +;;; Major mode definition + +(defvar puppet-mode-map + (let ((map (make-sparse-keymap))) + ;; Editing + (define-key map (kbd "C-c C-a") #'puppet-align-block) + (define-key map (kbd "C-c C-'") #'puppet-toggle-string-quotes) + (define-key map (kbd "C-c C-;") #'puppet-clear-string) + (define-key map (kbd "$") #'puppet-interpolate) + ;; Navigation + (define-key map (kbd "C-c C-j") #'imenu) + ;; Apply manifests + (define-key map (kbd "C-c C-c") #'puppet-apply) + ;; REPL stuff + (define-key map (kbd "C-c C-z") #'puppet-repl) + (define-key map (kbd "C-c C-r") #'puppet-repl-send-region) + (define-key map (kbd "C-c C-b") #'puppet-repl-send-buffer) + ;; Linting and validation + (define-key map (kbd "C-c C-v") #'puppet-validate) + (define-key map (kbd "C-c C-l") #'puppet-lint) + ;; The menu bar + (easy-menu-define puppet-menu map "Puppet Mode menu" + `("Puppet" + :help "Puppet-specific Features" + ["Align the current block" puppet-align-block + :help "Align parameters in the current block"] + ["Clear string" puppet-clear-string + :help "Clear the string at point"] + ["Toggle string quotes" puppet-toggle-string-quotes + :help "Toggle the string at point quotes between single and double"] + "-" + ["Jump to resource/variable" imenu + :help "Jump to a resource or variable"] + "-" + ["Apply manifest" puppet-apply :help "Apply a Puppet manifest"] + "-" + ["Puppet REPL" puppet-repl :help "Start the Puppet REPL"] + ["Send Region to REPL" puppet-repl-send-region + :help "Send this region to the the Puppet REPL"] + ["Send Line to REPL" puppet-repl-send-line + :help "Send this line to the the Puppet REPL"] + ["Send Buffer to REPL" puppet-repl-send-buffer + :help "Send this buffer to the the Puppet REPL"] + "-" + ["Validate file syntax" puppet-validate + :help "Validate the syntax of this file"] + ["Lint file" puppet-lint + :help "Check the file for semantic issues"])) + map) + "Key map for Puppet Mode buffers.") + +;;;###autoload +(define-derived-mode puppet-mode prog-mode "Puppet" () + "Major mode for editing Puppet manifests. + +\\{puppet-mode-map}" + ;; Comment setup + (setq-local comment-start "# ") + (setq-local comment-start-skip "#+ *") + (setq-local comment-use-syntax t) + (setq-local comment-end "") + (setq-local comment-auto-fill-only-comments t) + (setq comment-column puppet-comment-column) + ;; Navigation (TODO: Will we still need this with SMIE?) + (setq-local beginning-of-defun-function #'puppet-beginning-of-defun-function) + ;; Indentation + (setq-local indent-line-function #'puppet-indent-line) + (setq indent-tabs-mode puppet-indent-tabs-mode) + ;; Paragaphs + (setq-local paragraph-ignore-fill-prefix t) + (setq-local paragraph-start "\f\\|[ \t]*$\\|#$") + (setq-local paragraph-separate "\\([ \t\f]*\\|#\\)$") + ;; Font locking + (setq font-lock-defaults '((puppet-font-lock-keywords) nil nil)) + (setq-local syntax-propertize-function #'puppet-syntax-propertize-function) + ;; Alignment + (setq align-mode-rules-list puppet-mode-align-rules) + (setq align-mode-exclude-rules-list puppet-mode-align-exclude-rules) + ;; IMenu + (setq imenu-create-index-function #'puppet-imenu-create-index)) + +;;;###autoload +(add-to-list 'auto-mode-alist '("\\.pp\\'" . puppet-mode)) + +(provide 'puppet-mode) + +;; Local Variables: +;; indent-tabs-mode: nil +;; End: + +;;; puppet-mode.el ends here