X-Git-Url: https://code.delx.au/gnu-emacs-elpa/blobdiff_plain/00ef7a2273427aa71fe7f575dc1817e4fa9c2fca..2ea0c03243edbb585a376410d879c62a3036a946:/packages/systemd/systemd-mode.el diff --git a/packages/systemd/systemd-mode.el b/packages/systemd/systemd-mode.el new file mode 100644 index 000000000..f79966150 --- /dev/null +++ b/packages/systemd/systemd-mode.el @@ -0,0 +1,200 @@ +;;; systemd-mode.el --- Major modes for systemd unit files -*- lexical-binding: t; -*- + +;; Copyright (C) 2016 Free Software Foundation, Inc. + +;; Author: Mario Lang +;; Keywords: files + +;; 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 . + +;;; Todo: + +;; * Add support for systemd-networkd .link and .network files. + +;;; Code: + +(require 'conf-mode) + +(defvar systemd-unit-font-lock-keywords + '(;; [section] + ("^[ \t]*\\[\\(Unit\\|Service\\)\\]" + 1 'font-lock-type-face) + ;; var=val + ("^[ \t]*\\(.+?\\)[ \t]*=" + 1 'font-lock-variable-name-face)) + "Keywords to highlight in Conf mode.") + +(defvar-local systemd-unit-mode-sections '("Unit" "Install")) + +(defvar systemd-unit-mode-map + (let ((map (make-sparse-keymap))) + (define-key map "\t" #'completion-at-point) + map)) + +(define-derived-mode systemd-unit-mode conf-unix-mode "Systemd-Unit" + (conf-mode-initialize "#" systemd-unit-font-lock-keywords) + (add-hook 'completion-at-point-functions #'systemd-mode-completion-at-point + nil t) + (setq-local completion-ignore-case t)) + +;;;###autoload +(define-derived-mode systemd-automount-mode systemd-unit-mode "Systemd-AutoMount" + "Major mode for editing systemd .automount unit files" + (add-to-list 'systemd-unit-mode-sections "AutoMount")) + +;;;###autoload +(define-derived-mode systemd-mount-mode systemd-unit-mode "Systemd-Mount" + "Major mode for editing systemd .mount unit files" + (add-to-list 'systemd-unit-mode-sections "Mount")) + +;;;###autoload +(define-derived-mode systemd-path-mode systemd-unit-mode "Systemd-Path" + "Major mode for editing systemd .path unit files" + (add-to-list 'systemd-unit-mode-sections "Path")) + +;;;###autoload +(define-derived-mode systemd-service-mode systemd-unit-mode "Systemd-Service" + "Major mode for editing systemd .service unit files." + (add-to-list 'systemd-unit-mode-sections "Service")) + +;;;###autoload +(define-derived-mode systemd-socket-mode systemd-unit-mode "Systemd-Socket" + "Major mode for editing systemd .socket unit files." + (add-to-list 'systemd-unit-mode-sections "Socket")) + +;;;###autoload +(define-derived-mode systemd-swap-mode systemd-unit-mode "Systemd-Swap" + "Major mode for editing systemd .swap unit files." + (add-to-list 'systemd-unit-mode-sections "Swap")) + +;;;###autoload +(define-derived-mode systemd-timer-mode systemd-unit-mode "Systemd-Timer" + "Major mode for editing systemd .timer unit files." + (add-to-list 'systemd-unit-mode-sections "Timer")) + +(defvar systemd-mode-section-keywords-alist + '(("AutoMount" + "Where" "DirectoryMode" "TimeoutIdleSec") + ("Device") + ("Mount" + "What" "Where" "Type" "Options" "SloppyOptions" "DirectoryMode" + "TimeoutSec") + ("Path" + "PathExists" "PathExistsGlob" "PathChanged" "PathModified" + "DirectoryNotEmpty" "Unit" "MakeDirectory" "DirectoryMode") + ("Service" + "Type" "RemainAfterExit" "GuessMainPID" "PIDFile" "BusName" + "ExecStart" "ExecStartPre" "ExecStartPost" "ExecReload" + "ExecStop" "ExecStopPost" "RestartSec" "TimeoutStartSec" + "TimeoutStopSec" "TimeoutSec" "RuntimeMaxSec" "WatchdogSec" + "Restart" "SuccessExitStatus" "RestartPreventExitStatus" + "RestartForceExitStatus" "PermissionsStartOnly" + "RootDirectoryStartOnly" "NonBlocking" "NotifyAccess" "Sockets" + "FailureAction" "FileDescriptorStoreMax" "USBFunctionDescriptors" + "USBFunctionStrings") + ("Slice") + ("Socket" + "ListenStream" "ListenDatagram" "ListenSequentialPacket" + "ListenFIFO" "ListenSpecial" "ListenNetlink" "ListenMessageQueue" + "ListenUSBFunction" "SocketProtocol" "BindIPv6Only" + "Backlog" "BindToDevice" "SocketUser" "SocketGroup" + "SocketMode" "DirectoryMode" "Accept" "Writable" "MaxConnections" + "KeepAlive" "KeepAliveTimeSec" "KeepAliveIntervalSec" + "KeepAliveProbes" "NoDelay" "Priority" "DeferAcceptSec" + "ReceiveBuffer" "SendBuffer" "IPTOS" "IPTTL" "Mark" "ReusePort" + "SmackLabel" "SmackLabelIPIn" "SmackLabelIPOut" + "SELinuxContextFromNet" "PipeSize" "MessageQueueMaxMessages" + "MessageQueueMessageSize" "FreeBind" "Transparent" "Broadcast" + "PassCredentials" "PassSecurity" "TCPCongestion" "ExecStartPre" + "ExecStartPost" "ExecStopPre" "ExecStopPost" "TimeoutSec" + "Service" "RemoveOnStop" "Symlinks" "FileDescriptorName" + "TriggerLimitIntervalSec" "TriggerLimitBurst") + ("Swap" + "What" "Priority" "Options" "TimeoutSec") + ("Target") + ("Timer" + "OnActiveSec" "OnBootSec" "OnStartupSec" "OnUnitActiveSec" + "OnUnitInactiveSec" "OnCalendar" "AccuracySec" "RandomizedDelaySec" + "Unit" "Persistent" "WakeSystem" "RemainAfterElapse") + ("Unit" + "Description" "Documentation" "Requires" "Requisite" "Wants" "BindsTo" + "PartOf" "Conflicts" "Before" "After" "OnFailure" "PropagatesReloadTo" + "ReloadPropagatedFrom" "JoinsNamespaceOf" "RequiresMountsFor" + "OnFailureJobMode" "IgnoreOnIsolate" "StopWhenUnneeded" "RefuseManualStart" + "RefuseManualStop" "AllowIsolate" "DefaultDependencies" + "JobTimeoutSec" "JobTimeoutAction" "JobTimeoutRebootArgument" + "StartLimitIntervalSec" "StartLimitBurst" + "StartLimitAction" "RebootArgument" + "ConditionArchitecture" "ConditionVirtualization" "ConditionHost" + "ConditionKernelCommandLine" "ConditionSecurity" "ConditionCapability" + "ConditionACPower" "ConditionNeedsUpdate" "ConditionFirstBoot" + "ConditionPathExists" "ConditionPathExistsGlob" "ConditionPathIsDirectory" + "ConditionPathIsSymbolicLink" "ConditionPathIsMountPoint" + "ConditionPathIsReadWrite" "ConditionDirectoryNotEmpty" + "ConditionFileNotEmpty" "ConditionFileIsExecutable" + "AssertArchitecture" "AssertVirtualization" "AssertHost" + "AssertKernelCommandLine" "AssertSecurity" "AssertCapability" + "AssertACPower" "AssertNeedsUpdate" "AssertFirstBoot" "AssertPathExists" + "AssertPathExistsGlob" "AssertPathIsDirectory" "AssertPathIsSymbolicLink" + "AssertPathIsMountPoint" "AssertPathIsReadWrite" "AssertDirectoryNotEmpty" + "AssertFileNotEmpty" "AssertFileIsExecutable" + "SourcePath") + ("Install" + "Alias" "WantedBy" "RequiredBy" "Also" "DefaultInstance"))) + +(defvar systemd-mode-section-regexp "^[ \t]*\\[\\([[:alpha:]]+\\)]") + +(defun systemd-mode-completion-at-point () + (if (save-excursion (re-search-backward systemd-mode-section-regexp nil t)) + (let ((section (match-string-no-properties 1))) + (if (member-ignore-case section systemd-unit-mode-sections) + (let ((keywords (cdr (assoc-string + section systemd-mode-section-keywords-alist t)))) + (when keywords + (let ((end (point))) + (save-excursion + (skip-chars-backward "[:alpha:]") + (let ((start (point))) + (skip-chars-backward " \t") + (when (eq (line-beginning-position) (point)) + (list start end (mapcar (lambda (str) (concat str "=")) + keywords)))))))) + (display-warning major-mode + (format "Unexpected section [%s]." section) + :warning) + nil)))) + +;;;###autoload +(add-to-list 'auto-mode-alist '("\\.automount\\'" . systemd-automount-mode)) + +;;;###autoload +(add-to-list 'auto-mode-alist '("\\.mount\\'" . systemd-mount-mode)) + +;;;###autoload +(add-to-list 'auto-mode-alist '("\\.path\\'" . systemd-path-mode)) + +;;;###autoload +(add-to-list 'auto-mode-alist '("\\.service\\'" . systemd-service-mode)) + +;;;###autoload +(add-to-list 'auto-mode-alist '("\\.socket\\'" . systemd-socket-mode)) + +;;;###autoload +(add-to-list 'auto-mode-alist '("\\.swap\\'" . systemd-swap-mode)) + +;;;###autoload +(add-to-list 'auto-mode-alist '("\\.timer\\'" . systemd-timer-mode)) + +(provide 'systemd-mode) +;;; systemd-mode.el ends here