Compare commits

..

106 Commits
v1.2 ... master

Author SHA1 Message Date
Mark Oteiza
8742607120 stop clobbering company-backends
* using add-hook to modify company-backends is bad juju
* there does not appear to be a sensible way for a mode to
  modify company-backends either in the variable docstring or the
  online documentation here

https://company-mode.github.io/manual/Backends.html

  so... we should not modify it.
* document the added effort to use the company backend
* the only additional fanciness to `systemd-company-backend' is that
  it will automatically insert an = after completing a directive, so
  it might be nice to work that into the capf completion somehow and
  trash the company-specific code
2023-01-31 22:02:07 -05:00
Mark Oteiza
964ec9d4e0 happy new year 2023-01-31 21:55:06 -05:00
Mark Oteiza
b6ae63a236 add specifiers (leave obsoleted ones in for now) 2021-02-09 15:52:26 -05:00
Mark Oteiza
0416fe454a drop some unneeded eval-when-compile 2021-02-09 15:52:05 -05:00
Mark Oteiza
20c9d97e24 happy new year 2021-02-09 15:51:44 -05:00
Mark Oteiza
ec8f6cfe9d happy new year 2020-01-30 13:29:39 -05:00
Mark Oteiza
51c148e09a update urls
drop mention of marmalade
2019-12-19 18:04:45 -05:00
Mark Oteiza
9265ef89ff update section lists
there are very many different specialized network sections now.  only
a subset of them have been added here
2019-12-19 18:03:47 -05:00
Mark Oteiza
077aedde23 systemd 244 directives
network stuff is getting split up across a bunch of different sections
which is annoying.  dnssec files are a thing now as well.  finding
a better way to do this would be nice
2019-12-19 18:01:39 -05:00
stardiviner
a9f82b1f8b add systemd-mode company backend buffer locally 2019-11-17 11:14:46 -05:00
Mark Oteiza
c6e06dfa93 happy new year 2019-01-01 04:23:36 -05:00
Lucas Werkmeister
401d71c2dd Add %E, %j, %J, %T, %V specifiers
These specifiers were added in systemd v239.
2018-06-29 17:06:22 -04:00
Lucas Werkmeister
21d50f27d8 Sort specifiers alphabetically
The systemd.unit(5) manpage sorts unit file specifiers alphabetically
since commit systemd/systemd@709f4c472c, and since the order in this
regular expression is even less relevant than in the manpage, let’s just
do the same to make it easy to compare the letter sets between the two.
2018-06-29 17:06:13 -04:00
Lucas Werkmeister
e97f78ee11 Add %S, %C, %L specifiers
These specifiers for the state, cache, and log directory root were added in systemd v236.
2018-04-14 14:11:36 -04:00
Mark Oteiza
228f0b99ca happy new year 2018-01-01 21:03:40 -05:00
Mark Oteiza
22f024fe8f systemd 235 2017-10-06 16:52:43 -04:00
Mark Oteiza
1e7567a997 prepare v1.6 2017-09-18 20:49:18 -04:00
Mark Oteiza
70c762072d add -pkg file to clean target 2017-09-18 20:47:03 -04:00
Mark Oteiza
23c0caf214 extend anchored matches past the current line if \ broken 2017-09-18 07:46:09 -04:00
Mark Oteiza
839094df0e use rx here 2017-09-17 15:37:16 -04:00
Mark Oteiza
16ba942afd rename tests directory 2017-09-17 15:08:47 -04:00
Mark Oteiza
47ae79aed0 Use syntax-propertize and font-lock-extend-region-functions 2017-09-17 14:50:12 -04:00
Mark Oteiza
a3d39214b7 extend multi-line matching to sections and keys 2017-09-11 09:25:09 -04:00
Mark Oteiza
5c9389dae3 move this matcher down with the other ones 2017-09-07 22:04:50 -04:00
Mark Oteiza
b0c1d64d62 add multi-line comment highlighting
between font-lock-keywords, the elisp manual, examples in the emacs
source (sh-mode is one) and the webernets, it is rather difficult to
find a way to properly deal with multi-line construct syntax
highlighting.  this is a way leveraging anchored matching and
jit-lock.
2017-09-07 22:03:17 -04:00
Mark Oteiza
3ff4f0f706 anchor some matchers to follow "=" 2017-09-07 21:59:33 -04:00
Mark Oteiza
a4f409641a moar keywords 2017-09-07 21:57:46 -04:00
Mark Oteiza
995ebbe3d5 add conventional environment variable highlighting 2017-09-03 04:33:37 -04:00
Mark Oteiza
4c0ec1e599 split font-lock-keywords into levels
more importantly, bind systemd-font-lock-keywords to a _symbol_.
this makes hacking font-lock-keywords on the fly a little easier, in
addition to adding to customization/granularity
(info "(elisp) Font Lock Basics")
2017-09-03 04:29:03 -04:00
Mark Oteiza
7bb8f0969d correct syntax? 2017-09-03 03:39:52 -04:00
Mark Oteiza
2c71ec5529 systemd 234.11 2017-07-27 08:04:54 -04:00
Mark Oteiza
9cfd315337 simplify 2017-07-08 18:34:46 -04:00
Mark Oteiza
28601d814f woops 2017-07-08 18:02:26 -04:00
Mark Oteiza
930e82e5fe font lock additional exec prefix 2017-07-07 21:33:41 -04:00
Mark Oteiza
9693935bdd nix extra newline 2017-07-06 22:39:05 -04:00
Mark Oteiza
6884c8f9c6 systemd 233? 2017-07-06 21:12:20 -04:00
Mark Oteiza
4c1b2befd0 bump 2017-02-02 21:44:22 -05:00
Mark Oteiza
a2c60f407a happy belated new year 2017-02-02 21:44:00 -05:00
Mark Oteiza
59ce8ad415 simpler while test 2017-02-02 21:43:08 -05:00
Mark Oteiza
bd94a2cb97 shim in support for nspawn settings files 2017-01-22 20:45:01 -05:00
Mark Oteiza
b561c6bce9 happy new year 2017-01-01 00:03:40 -05:00
Mark Oteiza
fa1277d1cd add reminder
The new regex is not too hard to generate with some set/combinatorics
fun, but perhaps going about this a different way would be better

  (let ((s (delq nil (powerset '("@" "-" "+")))))
    (concat "="
     (regexp-opt
      (mapcar (lambda (ls) (apply #'concat ls))
              (apply #'append (mapcar #'permutations s)))
     "\\(?1:")))
2016-12-02 01:17:46 -05:00
Mark Oteiza
4c073b0c04 missed one 2016-12-02 01:16:12 -05:00
Mark Oteiza
7874a102a5 future flycheck has a checker for units 2016-12-02 01:14:39 -05:00
Mark Oteiza
0a4b6c49d3 shrug 2016-12-02 01:14:06 -05:00
Mark Oteiza
bf7b281cdb nix unneeded arg 2016-12-02 01:11:04 -05:00
Mark Oteiza
f0b29ad130 systemd v232 directives 2016-12-02 00:35:50 -05:00
Mark Oteiza
7769000ba6 bump to 0.4.1 2016-09-28 22:56:56 -04:00
Mark Oteiza
a73c16aac0 nix LOCAL argument for adding to company-backends 2016-09-27 12:11:38 -04:00
Mark Oteiza
16be18350c don't indiscriminately use relative file name 2016-09-27 12:07:08 -04:00
Mark Oteiza
a1633c271d systemd 231 directives 2016-07-31 19:30:39 -04:00
Mark Oteiza
0e793b05e2 put the quotes back. faces are symbols
font-lock.el is an exception wrt defvar'ing faces, not the rule
2016-06-28 23:48:17 -04:00
Mark Oteiza
2e1f7394f1 update readme 2016-06-12 00:44:49 -04:00
Mark Oteiza
a08af4c52b systemd 230 directives 2016-06-12 00:43:45 -04:00
Mark Oteiza
b03e616f0d bump 2016-05-14 10:15:10 -04:00
Mark Oteiza
fe443ac8ca use font-lock-defaults to disable syntax highlighting 2016-05-12 20:25:07 -04:00
Mark Oteiza
378eb3642c nix some quotes. use some rx 2016-05-10 01:09:31 -04:00
Mark Oteiza
63d64ad4e6 generate directive lists from files 2016-05-07 15:49:25 -04:00
Mark Oteiza
f74f3c8520 add to buffer-local hooks 2016-05-02 13:36:10 -04:00
Mark Oteiza
921f8d0df8 nix systemd-use-company-p 2016-05-02 13:12:02 -04:00
Mark Oteiza
de5da7fce7 update Makefile 2016-05-02 13:06:16 -04:00
Mark Oteiza
bd1b86eecd woops! 2016-05-02 12:07:06 -04:00
Mark Oteiza
ff523bc3da woops 2016-05-01 15:18:56 -04:00
Mark Oteiza
6fd29c5c85 font lock keywords: comments and sections
* let comments be prefixed with whitespace
* match ignored "X-" section headers
2016-05-01 13:58:47 -04:00
Mark Oteiza
5cb70eb684 change dropin filename restrictions
* do not match in .d/ subdirectories
* there are no restrictions on dropin config file base names
2016-05-01 13:06:14 -04:00
Mark Oteiza
b004b3725a autoload sorcery 2016-05-01 13:05:08 -04:00
Mark Oteiza
35801910e7 add autoload regex tests 2016-05-01 12:48:59 -04:00
Mark Oteiza
f3066147a1 dang spaces 2016-05-01 00:40:10 -04:00
Mark Oteiza
cd22a2c250 use a-zA-Z0-9
the alphanum class matches multibyte characters, and matching only
alphanumeric ASCII is what is desired here
2016-04-30 22:15:24 -04:00
Mark Oteiza
4121a9a37b section names can be prefixed with X- 2016-04-30 18:07:27 -04:00
Mark Oteiza
a434645e76 improvements to autoload regexen
many thanks to @Lompik
* don't match empty unit names. AIUI unit names are alphanumeric with
  the exception of the group [-_.@], non ascii are backslash-escaped.
* more strictly match temp file names: .# prefix, [[:hexdigit:]]{16}
  suffix. the filenames are a unit name with a unit suffix (systemctl
  edit --full) or just override.conf (edit without --full option)
* add regex for dropin config files. This is just a file with ".conf"
  extension, with the added constraint that it's a file having some
  parent directory named "systemd"
2016-04-30 17:56:25 -04:00
Mark Oteiza
bf39be20e4 assimilate systemd-company.el into systemd.el
hopefully didn't break everything \o/
* eventual goal is to have the large lists generated at byte compile
  time from the text files now present in the repo.  updating the lists
  in lisp is very annoying
* capf completion now exists and draws from the same infrastructure
* added capability to add a "=" after company completion of a directive
* systemd-use-company-p still works, but does not need to exist
2016-04-30 00:09:57 -04:00
Mark Oteiza
9fc054586d move systemd-font-lock-keywords 2016-04-29 12:40:17 -04:00
Mark Oteiza
070e15e4c0 autoload temp files generated by sd's tempfn_random
* adds 16 random hex digits to the end of file name
* instead of a bunch of autoloads, draw regexp into a pair of defconst
* not sure how to splice a reusable list of extensions into an rx call,
  which would be nicer than duplicating it
2016-04-29 10:20:50 -04:00
Mark Oteiza
a86323e90b v229 2016-03-22 23:26:07 -04:00
Mark Oteiza
3eb93907de add lists of directives 2016-03-22 23:20:32 -04:00
Mark Oteiza
dbf78305d4 happy new year 2016-01-01 02:34:11 -05:00
Mark Oteiza
26de1dd6f4 don't turn on company by default 2015-11-28 00:32:24 -05:00
Mark Oteiza
a2ec338fa6 use loop 2015-11-27 23:48:13 -05:00
Mark Oteiza
1513dd0fa4 systemd 228 2015-11-27 23:47:33 -05:00
Mark Oteiza
aa9f4f64e9 update commentary 2015-09-28 09:09:41 -04:00
Mark Oteiza
0f2f9361e4 clarify parent mode hooks 2015-09-28 08:19:12 -04:00
Mark Oteiza
1a7af1239b no strings with single quotes either 2015-09-25 08:35:36 -04:00
Mark Oteiza
602d9d334d reword some commentary 2015-09-21 13:27:39 -04:00
Mark Oteiza
05dd16c861 systemd 226 2015-09-21 13:24:59 -04:00
Mark Oteiza
6f2e31ed7c add a mode menu 2015-09-20 23:12:40 -04:00
Mark Oteiza
175d45fee6 checkdoc 2015-09-20 23:05:39 -04:00
Mark Oteiza
6071c2349c version 1.3 2015-09-10 11:30:57 -04:00
Mark Oteiza
d7a9c1dd9f fontify "-" and "@" prefixes 2015-09-10 11:29:54 -04:00
Mark Oteiza
807c748e28 systemd 225 2015-09-05 00:24:56 -04:00
Mark Oteiza
d03b70c121 derive from conf-mode 2015-09-03 17:03:44 -04:00
Mark Oteiza
0c871fc508 Use four different candidate lists:
Section vs directive, normal unit vs network configuration
2015-09-03 17:03:40 -04:00
Mark Oteiza
57dcf5a90e for some reason, this directive is missing 2015-09-02 14:48:40 -04:00
Mark Oteiza
f69d903fee add missing network directives 2015-08-05 12:49:21 -04:00
Mark Oteiza
968ae5ee04 bump for bug fix 2015-05-30 09:55:35 -04:00
Mark Oteiza
8e6a8cec7f remove backslash escapes from doc completions 2015-05-30 09:36:35 -04:00
Mark Oteiza
ef2436044b spaces unneeded in syntax table modifications 2015-05-30 09:36:08 -04:00
Mark Oteiza
077b2946ab no change in systemd 220 2015-05-30 09:35:06 -04:00
Mark Oteiza
2b70f833fd these groups need not be nested 2015-05-30 09:34:34 -04:00
Mark Oteiza
cf435f40ef convolute sexp 2015-05-30 09:31:27 -04:00
Mark Oteiza
eaaf16f229 fix indentation 2015-05-30 09:22:07 -04:00
Mark Oteiza
7bdb35abc2 mention package archive in README 2015-05-12 22:42:27 -04:00
Mark Oteiza
347c157be3 lexical binding 2015-05-11 09:28:11 -04:00
Mark Oteiza
09bfb6791e explicitly require cl-lib 2015-05-11 09:27:40 -04:00
Mark Oteiza
ed00e3f620 require 24.4 (with-eval-after-load) 2015-05-11 09:20:09 -04:00
Mark Oteiza
00a2520f65 add Package-Requires for emacs 24.3 (setq-local) 2015-05-10 18:24:42 -04:00
8 changed files with 1130 additions and 205 deletions

View File

@ -1,4 +1,8 @@
SRC = systemd.el systemd-company.el
SRC = systemd.el
DATA = unit-directives.txt network-directives.txt nspawn-directives.txt
DISTFILES := Makefile $(SRC) $(DATA) LICENSE README systemd-pkg.el test
VERSION := $(shell awk '/^;; Version:/ {print $$3}' $(SRC))
PREFIX = /usr/local
datarootdir := $(PREFIX)/share
@ -8,14 +12,32 @@ EMACS = emacs
all: $(SRC:.el=.elc)
systemd-pkg.el: $(SRC)
printf "(define-package \"systemd\" \"%s\" " $(VERSION) > $@
echo "\"Major mode for editing systemd units\")" >> $@
systemd.elc: $(DATA)
check: test/systemd-tests.el systemd.elc
@$(EMACS) -Q --batch -L . --eval "(progn \
(load-file \"test/systemd-tests.el\") \
(ert-run-tests-batch-and-exit))"
clean:
$(RM) $(SRC:.el=.elc)
$(RM) $(SRC:.el=.elc) systemd-pkg.el
dist: clean systemd-pkg.el
mkdir systemd-$(VERSION)
cp -r $(DISTFILES) systemd-$(VERSION)
tar cf systemd-$(VERSION).tar systemd-$(VERSION)
rm -rf systemd-$(VERSION)
install:
install -d $(DESTDIR)$(emacsdir)/systemd
install -m644 $(SRC) $(SRC:.el=.elc) -t $(DESTDIR)$(emacsdir)/systemd
install -m644 $(DATA) -t $(DESTDIR)$(emacsdir)/systemd
.el.elc:
$(EMACS) -L . --batch -f batch-byte-compile $<
.PHONY: all clean install
.PHONY: all check clean dist install

6
README
View File

@ -7,9 +7,11 @@ in `systemd.el`.
Installation
------------
In Emacs 25 or later, one can locally install as a package with
Available as the `systemd` package on MELPA <https://melpa.org/>.
M-x package-install-file RET /path/to/systemd-mode RET
In Emacs, one can locally install as a package with `make dist` and
M-x package-install-file RET /path/to/systemd-VERSION.tar RET
Otherwise, for either installing into one's `load-path` or a system
install, do the usual

316
network-directives.txt Normal file
View File

@ -0,0 +1,316 @@
ARP
ARPAllTargets
ARPIPTargets
ARPIntervalSec
ARPValidate
Activate
ActiveSlave
AdActorSystem
AdActorSystemPriority
AdSelect
AdUserPortKey
Address
AddressAutoconfiguration
Advertise
AgeingTimeSec
Alias
AllMulticast
AllSlavesActive
AllowLocalRemote
AllowPortToBeRoot
AllowedIPs
Anonymize
Architecture
AssignToLoopback
AssociatedWith
AutoJoin
AutoNegotiation
BSSID
BindCarrier
BitRate
BitsPerSecond
BlackList
Bond
Bridge
Broadcast
ClientIdentifier
CombinedChannels
ConfigureWithoutCarrier
CopyDSCP
Cost
DHCP
DHCPServer
DNS
DNSDefaultRoute
DNSLifetimeSec
DNSOverTLS
DNSSEC
DNSSECNegativeTrustAnchors
DUIDRawData
DUIDType
DefaultLeaseTimeSec
DefaultPVID
DefaultRouteOnDevice
Description
Destination
DestinationPort
DiscoverPathMTU
Domains
DownDelaySec
Driver
Duplex
DuplicateAddressDetection
DynamicTransmitLoadBalancing
ERSPANIndex
EgressUntagged
EmitDNS
EmitDomains
EmitLLDP
EmitNTP
EmitRouter
EmitSIP
EmitTimezone
Encapsulation
EncapsulationLimit
EncapsulationType
Encrypt
Endpoint
FDBAgeingSec
FOUDestinationPort
FOUSourcePort
FailOverMACPolicy
Family
FastLeave
FastOpenNoCookie
FirewallMark
Flags
FlowLabel
FooOverUDP
ForceDHCPv6PDOtherInformation
ForwardDelaySec
From
GVRP
Gateway
GatewayOnLink
GenericProtocolExtension
GenericReceiveOffload
GenericSegmentationOffload
GratuitousARP
Group
GroupForwardMask
GroupPolicyExtension
HairPin
HelloTimeSec
HomeAddress
Host
Hostname
IAID
IPDoNotFragment
IPForward
IPMasquerade
IPProtocol
IPServiceType
IPVLAN
IPv4LLRoute
IPv4ProxyARP
IPv6AcceptRA
IPv6DuplicateAddressDetection
IPv6FlowLabel
IPv6HopLimit
IPv6MTUBytes
IPv6Preference
IPv6PrefixDelegation
IPv6PrivacyExtensions
IPv6ProxyNDP
IPv6ProxyNDPAddress
IPv6RapidDeploymentPrefix
IPv6Token
ISATAP
Id
IgnoreCarrierLoss
IncomingInterface
Independent
InitialAdvertisedReceiveWindow
InitialCongestionWindow
InputKey
InterfaceId
InvertRule
KeepConfiguration
KernelCommandLine
KernelVersion
Key
KeyFile
KeyId
Kind
L2MissNotification
L3MissNotification
LACPTransmitRate
LLDP
LLMNR
Label
LargeReceiveOffload
Layer2SpecificHeader
LearnPacketIntervalSec
Learning
LifetimeSec
LinkLayerAddress
LinkLocalAddressing
ListenPort
Local
LooseBinding
MACAddress
MACAddressPolicy
MACVLAN
MACsec
MIIMonitorSec
MTUBytes
MVRP
MacLearning
ManageTemporaryAddress
Managed
MaxAgeSec
MaxAttempts
MaxLeaseTimeSec
MaximumFDBEntries
Metric
MinLinks
Mode
MultiQueue
Multicast
MulticastDNS
MulticastFlood
MulticastIGMPVersion
MulticastQuerier
MulticastRouter
MulticastSnooping
MulticastToUnicast
NTP
Name
NamePolicy
NeighborSuppression
NetworkEmulatorDelayJitterSec
NetworkEmulatorDelaySec
NetworkEmulatorDuplicateRate
NetworkEmulatorLossRate
NetworkEmulatorPacketLimit
OnLink
OriginalName
OtherChannels
OtherInformation
OutgoingInterface
OutputKey
PVID
PacketInfo
PacketNumber
PacketsPerSlave
Parent
Path
Peer
PeerPort
PeerSessionId
PeerTunnelId
PersistentKeepalive
PoolOffset
PoolSize
Port
PortRange
PreferredLifetime
PreferredLifetimeSec
PreferredSource
Prefix
PrefixDelegationHint
PrefixRoute
PresharedKey
PresharedKeyFile
PrimaryReselectPolicy
PrimarySlave
Priority
PrivateKey
PrivateKeyFile
Property
Protocol
ProxyARP
ProxyARPWiFi
PublicKey
QuickAck
RapidCommit
ReduceARPProxy
Remote
RemoteChecksumRx
RemoteChecksumTx
ReorderHeader
RequestBroadcast
RequestOptions
RequiredForOnline
ResendIGMP
RestartSec
Route
RouteMetric
RouteShortCircuit
RouteTable
RouterLifetimeSec
RouterPreference
RoutesToDNS
RxBufferSize
RxChannels
SSID
STP
SamplePoint
Scope
SendHostname
SendOption
SendRelease
SerializeTunneledPackets
SessionId
Source
SourcePort
TCP6SegmentationOffload
TCPSegmentationOffload
TOS
TTL
TTLPropagate
Table
Timezone
To
TransmitHashPolicy
TripleSampling
Tunnel
TunnelId
TxBufferSize
TxChannels
Type
TypeOfService
UDP6ZeroChecksumRx
UDP6ZeroChecksumTx
UDPChecksum
UDPSourcePort
UnicastFlood
Unmanaged
UpDelaySec
UseAutonomousPrefix
UseBPDU
UseDNS
UseDomains
UseForEncoding
UseHostname
UseMTU
UseNTP
UseOnLinkPrefix
UseRoutes
UseSIP
UseTimezone
User
UserClass
VLAN
VLANFiltering
VLANId
VNI
VNetHeader
VRF
VXLAN
ValidLifetimeSec
VendorClassIdentifier
Virtualization
WLANInterfaceType
WakeOnLan
Xfrm

38
nspawn-directives.txt Normal file
View File

@ -0,0 +1,38 @@
Boot
Ephemeral
ProcessTwo
Parameters
Environment
User
WorkingDirectory
PivotRoot
Capability
NoNewPrivileges
KillSignal
Personality
MachineID
PrivateUsers
NotifyReady
SystemCallFilter
LimitCPU
OOMScoreAdjust
CPUAffinity
Hostname
ResolvConf
Timezone
LinkJournal
ReadOnly
Volatile
Bind
TemporaryFileSystem
Inaccessible
Overlay
PrivateUsersChown
Private
VirtualEthernet
VirtualEthernetExtra
Interface
MACVLAN
Bridge
Zone
Port

View File

@ -1,129 +0,0 @@
;;; systemd-company.el --- company backend for systemd unit directives
;; Copyright (C) 2015 Mark Oteiza <mvoteiza@udel.edu>
;; Author: Mark Oteiza <mvoteiza@udel.edu>
;; 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 <http://www.gnu.org/licenses/>.
;;; Commentary:
;;; Code:
(declare-function company-mode "company")
(declare-function company-begin-backend "company")
(declare-function company-grab-symbol "company")
(defconst systemd-company-directives
;; TODO: keep a script of sorts for generating this list. systemd
;; source has a python script in tools/ for parsing the
;; documentation xml for the unit directives.
;;
;; forcer on freenode threw together a curl monstrosity for achieving
;; the same:
;; curl -s http://www.freedesktop.org/software/systemd/man/systemd.directives.html | tr -d '\n' | sed 's/>/>\n/g' | sed -ne '/Unit directives/,/Options on the kernel/p' | sed -ne 's/.*<dt id="\([^-][^"]*\)=">.*/\1/p'
;; Quote, wrap with fill-column at 72, insert into list and indent
'("Accept" "AccuracySec" "After" "Alias" "AllowIsolate" "Also"
"AppArmorProfile" "AssertACPower" "AssertArchitecture"
"AssertCapability" "AssertDirectoryNotEmpty" "AssertFileIsExecutable"
"AssertFileNotEmpty" "AssertFirstBoot" "AssertHost"
"AssertKernelCommandLine" "AssertNeedsUpdate" "AssertPathExists"
"AssertPathExistsGlob" "AssertPathIsDirectory" "AssertPathIsMountPoint"
"AssertPathIsReadWrite" "AssertPathIsSymbolicLink" "AssertSecurity"
"AssertVirtualization" "Backlog" "Before" "BindIPv6Only" "BindToDevice"
"BindsTo" "BlockIOAccounting" "BlockIODeviceWeight"
"BlockIOReadBandwidth" "BlockIOWeight" "BlockIOWriteBandwidth"
"Broadcast" "BusName" "BusPolicy" "CPUAccounting" "CPUAffinity"
"CPUQuota" "CPUSchedulingPolicy" "CPUSchedulingPriority"
"CPUSchedulingResetOnFork" "CPUShares" "Capabilities"
"CapabilityBoundingSet" "ConditionACPower" "ConditionArchitecture"
"ConditionCapability" "ConditionDirectoryNotEmpty"
"ConditionFileIsExecutable" "ConditionFileNotEmpty" "ConditionFirstBoot"
"ConditionHost" "ConditionKernelCommandLine" "ConditionNeedsUpdate"
"ConditionPathExists" "ConditionPathExistsGlob"
"ConditionPathIsDirectory" "ConditionPathIsMountPoint"
"ConditionPathIsReadWrite" "ConditionPathIsSymbolicLink"
"ConditionSecurity" "ConditionVirtualization" "Conflicts"
"DefaultDependencies" "DefaultInstance" "DeferAcceptSec" "Delegate"
"Description" "DeviceAllow" "DevicePolicy" "DirectoryMode"
"DirectoryNotEmpty" "Documentation" "Environment" "EnvironmentFile"
"ExecReload" "ExecStart" "ExecStartPost" "ExecStartPre" "ExecStop"
"ExecStopPost" "ExecStopPre" "FailureAction" "FileDescriptorStoreMax"
"FreeBind" "Group" "GuessMainPID" "IOSchedulingClass"
"IOSchedulingPriority" "IPTOS" "IPTTL" "IgnoreOnIsolate"
"IgnoreOnSnapshot" "IgnoreSIGPIPE" "InaccessibleDirectories"
"JobTimeoutAction" "JobTimeoutRebootArgument" "JobTimeoutSec"
"JoinsNamespaceOf" "KeepAlive" "KeepAliveIntervalSec" "KeepAliveProbes"
"KeepAliveTimeSec" "KillMode" "KillSignal" "LimitAS" "LimitCORE"
"LimitCPU" "LimitDATA" "LimitFSIZE" "LimitLOCKS" "LimitMEMLOCK"
"LimitMSGQUEUE" "LimitNICE" "LimitNOFILE" "LimitNPROC" "LimitRSS"
"LimitRTPRIO" "LimitRTTIME" "LimitSIGPENDING" "LimitSTACK"
"ListenDatagram" "ListenFIFO" "ListenMessageQueue" "ListenNetlink"
"ListenSequentialPacket" "ListenSpecial" "ListenStream" "MakeDirectory"
"Mark" "MaxConnections" "MemoryAccounting" "MemoryLimit"
"MessageQueueMaxMessages" "MessageQueueMessageSize" "MountFlags" "Nice"
"NoDelay" "NoNewPrivileges" "NonBlocking" "NotifyAccess"
"OOMScoreAdjust" "OnActiveSec" "OnBootSec" "OnCalendar" "OnFailure"
"OnFailureJobMode" "OnStartupSec" "OnUnitActiveSec" "OnUnitInactiveSec"
"Options" "PAMName" "PIDFile" "PartOf" "PassCredentials" "PassSecurity"
"PathChanged" "PathExists" "PathExistsGlob" "PathModified"
"PermissionsStartOnly" "Persistent" "Personality" "PipeSize" "Priority"
"PrivateDevices" "PrivateNetwork" "PrivateTmp" "PropagatesReloadTo"
"ProtectHome" "ProtectSystem" "ReadOnlyDirectories"
"ReadWriteDirectories" "RebootArgument" "ReceiveBuffer"
"RefuseManualStart" "RefuseManualStop" "ReloadPropagatedFrom"
"RemainAfterExit" "RemoveOnStop" "RequiredBy" "Requires"
"RequiresMountsFor" "RequiresOverridable" "Requisite"
"RequisiteOverridable" "Restart" "RestartForceExitStatus"
"RestartPreventExitStatus" "RestartSec" "RestrictAddressFamilies"
"ReusePort" "RootDirectory" "RootDirectoryStartOnly" "RuntimeDirectory"
"RuntimeDirectoryMode" "SELinuxContext" "SELinuxContextFromNet"
"SecureBits" "SendBuffer" "SendSIGHUP" "SendSIGKILL" "Service" "Slice"
"SloppyOptions" "SmackLabel" "SmackLabelIPIn" "SmackLabelIPOut"
"SmackProcessLabel" "SocketGroup" "SocketMode" "SocketUser" "Sockets"
"SourcePath" "StandardError" "StandardInput" "StandardOutput"
"StartLimitAction" "StartLimitBurst" "StartLimitInterval"
"StartupBlockIOWeight" "StartupCPUShares" "StopWhenUnneeded"
"SuccessExitStatus" "SupplementaryGroups" "Symlinks" "SyslogFacility"
"SyslogIdentifier" "SyslogLevel" "SyslogLevelPrefix"
"SystemCallArchitectures" "SystemCallErrorNumber" "SystemCallFilter"
"TCPCongestion" "TTYPath" "TTYReset" "TTYVHangup" "TTYVTDisallocate"
"TimeoutIdleSec" "TimeoutSec" "TimeoutStartSec" "TimeoutStopSec"
"TimerSlackNSec" "Transparent" "Type" "UMask" "Unit" "User"
"UtmpIdentifier" "WakeSystem" "WantedBy" "Wants" "WatchdogSec" "What"
"Where" "WorkingDirectory")
"Configuration directives for systemd 219.")
(defun systemd-company--setup (enable)
(when (fboundp 'systemd-company--setup-company)
(systemd-company--setup-company enable)))
(with-eval-after-load "company"
(defun systemd-company-backend (command &optional arg &rest ignored)
(interactive (list 'interactive))
(cl-case command
(interactive (company-begin-backend 'systemd-company-backend))
(prefix (and (eq major-mode 'systemd-mode)
(company-grab-symbol)))
(candidates
(cl-remove-if-not (lambda (c) (string-prefix-p arg c))
systemd-company-directives))))
(defun systemd-company--setup-company (enable)
(when enable
(add-to-list (make-local-variable 'company-backends) 'systemd-company-backend))
(company-mode (if enable 1 -1))))
(provide 'systemd-company)
;;; systemd-company.el ends here

View File

@ -1,9 +1,10 @@
;;; systemd.el --- Major mode for editing systemd units
;;; systemd.el --- Major mode for editing systemd units -*- lexical-binding: t -*-
;; Copyright (C) 2014-2015 Mark Oteiza <mvoteiza@udel.edu>
;; Copyright (C) 2014-2023 Mark Oteiza <mvoteiza@udel.edu>
;; Author: Mark Oteiza <mvoteiza@udel.edu>
;; Version: 1.2
;; Version: 1.6.1
;; Package-Requires: ((emacs "24.4"))
;; Keywords: tools, unix
;; This file is free software; you can redistribute it and/or
@ -23,24 +24,33 @@
;; Major mode for editing systemd units.
;; Reflects a stripped down conf-mode, except with strict regex for
;; whitespace, and highlighting for special syntax, such as specifiers
;; and booleans. Features a facility for browsing documentation: use
;; C-c C-o to open links to documentation in a unit (cf. systemctl
;; help).
;; Similar to `conf-mode' but with enhanced highlighting; e.g. for
;; specifiers and booleans. Employs strict regex for whitespace.
;; Features a facility for browsing documentation: use C-c C-o to open
;; links to documentation in a unit (cf. systemctl help).
;; Supports completion of unit directives via `company-mode'.
;; Supports completion of directives and sections in either units or
;; network configuration. Both a completer for
;; `completion-at-point-functions' and a company backend are provided.
;; The latter can be enabled by adding `company-mode' to
;; `systemd-mode-hook' and adding `systemd-company-backend' to
;; `company-backends'.
;;; Code:
(require 'conf-mode)
(require 'thingatpt)
(require 'url-parse)
(require 'systemd-company)
(declare-function company-begin-backend "company")
(declare-function company-grab-symbol "company")
(defvar font-lock-beg)
(defvar font-lock-end)
(defgroup systemd ()
"Major mode for editing systemd units."
:link '(url-link "http://www.freedesktop.org/wiki/Software/systemd/")
:link '(url-link "https://www.freedesktop.org/wiki/Software/systemd/")
:group 'tools)
(defcustom systemd-browse-url-function 'browse-url
@ -64,46 +74,96 @@
(function :tag "Other function"))
:group 'systemd)
(defcustom systemd-use-company-p t
"Whether to use `company-mode' for completion, if available."
:type 'boolean
(defcustom systemd-mode-hook nil
"Hook run after entering `systemd-mode'."
:type 'hook
:options '(company-mode flycheck-mode)
:group 'systemd)
(defvar systemd-font-lock-keywords
`(("^\\([#;]\\(.*\\)\\)$"
(1 'font-lock-comment-delimiter-face)
(2 'font-lock-comment-face))
("\\\\$" 0 'font-lock-warning-face) ; line break
;; sections
("^\\(\\[[[:upper:]][[:alnum:]]+\\]\\)"
1 'font-lock-type-face)
;; keys
("^\\([[:upper:]][[:alnum:]]+\\)="
1 'font-lock-keyword-face)
;; boolean arguments
("=\\(1\\|yes\\|true\\|on\\|0\\|no\\|false\\|off\\)$"
1 'font-lock-constant-face)
;; specifiers
("%[nNpPiIfcrRtuUhsmbHv%]" 0 'font-lock-constant-face))
"Default expressions to highlight in `systemd-mode'. See systemd.unit(5)
for details on unit file syntax.")
(defconst systemd-unit-sections
'("Unit" "Install" "Service")
"Configuration sections for systemd 244.")
(defconst systemd-unit-directives
(eval-when-compile
(with-temp-buffer
(insert-file-contents
(let ((f "unit-directives.txt"))
(if (null load-file-name) f
(expand-file-name f (file-name-directory load-file-name)))))
(split-string (buffer-string))))
"Configuration directives for systemd.")
(defconst systemd-network-sections
'("Match" "Link" "NetDev" "VLAN" "MACVLAN" "MACVTAP" "IPVLAN" "IPVTAP" "VXLAN"
"GENEVE" "L2TP" "L2TPsession" "MACsec" "FooOverUDP"
"Tunnel" "Peer" "Tun" "Tap" "Bond" "Network" "Address" "Route" "DHCP"
"Neighbor" "IPv6AddressLabel" "RoutingPolicyRule" "NextHop" "DHCPv4"
"DHCPv6" "IPv6AcceptRA" "DHCPServer" "IPv6Prefix" "CAN"
"Bridge" "BridgeFDB" "BridgeVLAN" "VXCAN" "WireGuard" "WireGuardPeer")
"Network configuration sections for systemd 244 (not exhaustive).")
(defconst systemd-network-directives
(eval-when-compile
(with-temp-buffer
(insert-file-contents
(let ((f "network-directives.txt"))
(if (null load-file-name) f
(expand-file-name f (file-name-directory load-file-name)))))
(split-string (buffer-string))))
"Network configuration directives for systemd.")
(defconst systemd-nspawn-sections
'("Exec" "Files" "Network")
"Namespace container configuration sections for systemd 244.")
(defconst systemd-nspawn-directives
(eval-when-compile
(with-temp-buffer
(insert-file-contents
(let ((f "nspawn-directives.txt"))
(if (null load-file-name) f
(expand-file-name f (file-name-directory load-file-name)))))
(split-string (buffer-string))))
"Namespace container configuration directives for systemd.")
;;;###autoload
(defconst systemd-autoload-regexp
(rx (+? (any "a-zA-Z0-9-_.@\\")) "."
(or "automount" "busname" "mount" "service" "slice"
"socket" "swap" "target" "timer" "link" "netdev" "network")
string-end)
"Regexp for file buffers in which to autoload `systemd-mode'.")
;;;###autoload
(defconst systemd-tempfn-autoload-regexp
(rx ".#"
(or (and (+? (any "a-zA-Z0-9-_.@\\")) "."
(or "automount" "busname" "mount" "service" "slice"
"socket" "swap" "target" "timer" "link" "netdev" "network"))
"override.conf")
(= 16 (char hex-digit)) string-end)
"Regexp for temp file buffers in which to autoload `systemd-mode'.")
;;;###autoload
(defconst systemd-dropin-autoload-regexp
(rx "/systemd/" (+? anything) ".d/" (+? (not (any ?/))) ".conf" string-end)
"Regexp for dropin config file buffers in which to autoload `systemd-mode'.")
(defun systemd-get-value (start)
"Joins lines in the key value starting at buffer position START,
possibly broken by a backslash, and returns a string containing
the value."
(save-excursion
(let ((break "\\\\\n")
end)
(while (progn (goto-char (1- (line-end-position)))
(looking-at break))
"Return the value of the key whose value begins at position START.
Lines ending in a backslash are concatenated with the next
according to systemd.unit(5)."
(let (end)
(save-excursion
(while (= (char-before (line-end-position)) ?\\)
(forward-line))
(setq end (line-end-position))
(replace-regexp-in-string break " " (buffer-substring start end)))))
(replace-regexp-in-string "\\\\\n" " " (buffer-substring start end)))))
(defun systemd-doc-find ()
"Find the value of the unit's “Documentation” keys and return
as a list of strings, otherwise nil."
"Find the value of the unit's “Documentation” keys.
Return values in a list of strings, otherwise nil."
(let ((key "^Documentation=")
string)
(save-excursion
@ -111,18 +171,19 @@ as a list of strings, otherwise nil."
(while (re-search-forward key nil t)
(setq string (concat string " " (systemd-get-value (point))))))
(when string
(split-string string))))
(remove "\\" (split-string string)))))
(defun systemd-doc-man (page)
"Open a manual page with `systemd-man-function'."
"Open a manual page PAGE with `systemd-man-function'."
(pcase (symbol-name systemd-man-function)
("woman" (woman (replace-regexp-in-string "([[:alnum:]]+)" "" page)))
("man" (man page))
(_ (apply 'systemd-man-function page))))
(defun systemd-doc-open (url)
"Open URL. Interactively completes the documentation in the
current unit file, defaulting to the link under point, if any."
"Prompt to open URL.
Interactively completes the documentation in the current unit
file, defaulting to the link under point, if any."
(interactive
(let* ((completion-cycle-threshold t)
(collection (systemd-doc-find))
@ -141,15 +202,174 @@ current unit file, defaulting to the link under point, if any."
(_ (user-error "Invalid link")))))
(defun systemd-doc-directives ()
"Open systemd.directives(7)"
"Open systemd.directives(7)."
(interactive)
(systemd-doc-man "systemd.directives(7)"))
(defun systemd-buffer-section-p ()
"Return t if current line begins with \"[\", otherwise nil."
(= (char-after (line-beginning-position)) ?\[))
(defun systemd-file-network-p (filename)
"Return non-nil if FILENAME has a network-type extension, otherwise nil."
(string-match-p (rx "." (or "link" "netdev" "network") string-end)
filename))
(defun systemd-file-nspawn-p (filename)
"Return non-nil if FILENAME has an nspawn extension, otherwise nil."
(string-match-p (rx ".nspawn" string-end) filename))
(defun systemd-completion-table (&rest _ignore)
"Return a list of completion candidates."
(let ((sectionp (systemd-buffer-section-p))
(name (buffer-name)))
(cond
((systemd-file-nspawn-p name)
(if sectionp systemd-nspawn-sections systemd-nspawn-directives))
((systemd-file-network-p name)
(if sectionp systemd-network-sections systemd-network-directives))
(t (if sectionp systemd-unit-sections systemd-unit-directives)))))
(defun systemd-complete-at-point ()
"Complete the symbol at point."
(let ((bounds (bounds-of-thing-at-point 'symbol)))
(list (or (car bounds) (point))
(or (cdr bounds) (point))
(completion-table-dynamic #'systemd-completion-table))))
(defun systemd-company-backend (command &optional arg &rest _ignored)
"Backend for `company-mode' in `systemd-mode' buffers."
(interactive (list 'interactive))
(pcase command
(`interactive (company-begin-backend 'systemd-company-backend))
(`prefix (and (eq major-mode 'systemd-mode) (company-grab-symbol)))
(`candidates (all-completions arg (systemd-completion-table nil)))
(`post-completion (if (not (systemd-buffer-section-p)) (insert "=")))))
(defun systemd-construct-start-p ()
"Return non-nil if the current line is the first in a multi-line construct."
(let ((flag t))
(save-excursion
(while (and (zerop (forward-line -1))
(eq ?\\ (char-before (line-end-position)))
(skip-chars-forward " \t")
(setq flag (memq (following-char) '(?# ?\;))))))
flag))
(defun systemd-syntax-propertize (start end)
"`systemd-propertize-function' for `systemd-mode' buffers."
(let ((case-fold-search nil))
(goto-char start)
(funcall
(syntax-propertize-rules
("^[ \t]*\\([;#]\\)$?"
(1 (when (systemd-construct-start-p) (string-to-syntax "<")))))
start end)))
(defun systemd-value-extend-region ()
"Return the EOL position of the last line of the construct at point."
(while (and (= (char-before (line-end-position)) ?\\)
(skip-chars-forward " \t")
(not (memq (following-char) '(?# ?\;)))
(zerop (forward-line))))
(line-end-position))
(defun systemd-font-lock-extend-region ()
(goto-char font-lock-beg)
(while (and (zerop (forward-line -1))
(= (char-before (line-end-position)) ?\\)
(skip-chars-forward " \t")
(not (memq (following-char) '(?# ?\;)))))
(setq font-lock-beg (point-marker))
(goto-char font-lock-end)
(setq font-lock-end (systemd-value-extend-region)))
(defmacro define-systemd-matcher (name regexp &optional docstring)
"Define a new function NAME that matches REGEXP in a multi-line construct.
Only returns matches of REGEXP on lines passing `systemd-construct-start-p'."
(declare (debug (symbolp stringp &optional stringp))
(indent 2) (doc-string 3))
`(defun ,name (limit)
,docstring
(let (match)
(while (and (setq match (re-search-forward ,regexp limit t))
(not (systemd-construct-start-p))))
match)))
(define-systemd-matcher systemd-section-matcher
"^\\(\\[\\([[:upper:]][[:alnum:]]+\\|X-.*?\\)\\]\\)"
"Matcher for section titles.")
(define-systemd-matcher systemd-key-matcher "^\\([[:upper:]][[:alnum:]]+\\)="
"Matcher for keys (unit directives).")
(defun systemd-exec-prefix-anchored-matcher (limit)
"Matcher for the exec prefix in anchored font-lock rule.
See `font-lock-keywords' and (info \"(elisp) Search-based Fontification\")."
(let ((pos (car (match-data)))
(prefixes '(?- ?@ ?+))
char end res)
(while (and (memq (setq char (following-char)) prefixes)
(< (point) limit))
(forward-char)
(setq prefixes (remq char prefixes))
(setq end (point-marker)))
(when end
(prog1 (setq res (list (1+ pos) end))
(set-match-data res)))))
(defconst systemd-font-lock-keywords-1
'((systemd-section-matcher 1 'font-lock-type-face)
(systemd-key-matcher 1 'font-lock-keyword-face))
"Minimal expressions to highlight in `systemd-mode'.")
(defconst systemd-font-lock-keywords-2
`(,@systemd-font-lock-keywords-1
("\\\\$" 0 'font-lock-warning-face) ; line break
;; boolean arguments
(,(rx "=" (group (or "yes" "true" "on" "0" "no" "false" "off")) eol)
1 'font-lock-constant-face)
("="
;; exec prefixes
(systemd-exec-prefix-anchored-matcher
nil nil (0 'font-lock-negation-char-face))
;; environment variables
("\\$[A-Z_]+\\>"
(systemd-value-extend-region) nil (0 'font-lock-variable-name-face))
;; specifiers
("%[abBCEfgGhHiIjJlLmnNopPrRsStTuUvVw%]"
(systemd-value-extend-region) nil (0 'font-lock-constant-face))))
"Extended expressions to highlight in `systemd-mode'.")
(defconst systemd-font-lock-keywords-3
`(,@systemd-font-lock-keywords-2
("^Type=\\(simple\\|forking\\|oneshot\\|dbus\\|notify\\|idle\\)$"
1 'font-lock-builtin-face)
(,(rx bol "Restart="
(group (or "no" "on-success" "on-failure"
"on-abnormal" "on-watchdog" "on-abort" "always"))
eol)
1 'font-lock-builtin-face)
("^KillMode=\\(control-group\\|process\\|mixed\\|none\\)$"
1 'font-lock-builtin-face)
(,(rx bol "KillSignal="
(group
(or "SIGHUP" "SIGINT" "SIGQUIT" "SIGILL" "SIGABRT" "SIGFPE" "SIGKILL"
"SIGSEGV" "SIGPIPE" "SIGALRM" "SIGTERM" "SIGUSR1" "SIGUSR2"
"SIGCHLD" "SIGCONT" "SIGSTOP" "SIGTSTP" "SIGTTIN" "SIGTTOU"))
eol)
1 'font-lock-constant-face))
"Flamboyant expressions to highlight in `systemd-mode'.")
(defvar systemd-font-lock-keywords 'systemd-font-lock-keywords-2
"Default expressions to highlight in `systemd-mode'.
See systemd.unit(5) for details on unit file syntax.")
(defvar systemd-mode-syntax-table
(let ((table (make-syntax-table)))
(modify-syntax-entry ?\" ". " table)
(modify-syntax-entry ?\n "> " table)
(modify-syntax-entry ?\% "\\ " table)
(modify-syntax-entry ?% "/" table)
(modify-syntax-entry ?$ "'" table)
(modify-syntax-entry ?\; "." table)
table)
"Syntax table used in `systemd-mode' buffers.")
@ -160,31 +380,42 @@ current unit file, defaulting to the link under point, if any."
map)
"Keymap used in `systemd-mode' buffers.")
;;;###autoload (add-to-list 'auto-mode-alist '("\\.automount\\'" . systemd-mode))
;;;###autoload (add-to-list 'auto-mode-alist '("\\.busname\\'" . systemd-mode))
;;;###autoload (add-to-list 'auto-mode-alist '("\\.mount\\'" . systemd-mode))
;;;###autoload (add-to-list 'auto-mode-alist '("\\.service\\'" . systemd-mode))
;;;###autoload (add-to-list 'auto-mode-alist '("\\.slice\\'" . systemd-mode))
;;;###autoload (add-to-list 'auto-mode-alist '("\\.socket\\'" . systemd-mode))
;;;###autoload (add-to-list 'auto-mode-alist '("\\.target\\'" . systemd-mode))
;;;###autoload (add-to-list 'auto-mode-alist '("\\.timer\\'" . systemd-mode))
;;;###autoload (add-to-list 'auto-mode-alist '("\\.link\\'" . systemd-mode))
;;;###autoload (add-to-list 'auto-mode-alist '("\\.netdev\\'" . systemd-mode))
;;;###autoload (add-to-list 'auto-mode-alist '("\\.network\\'" . systemd-mode))
;;;###autoload (add-to-list 'auto-mode-alist '("\\.override\\.conf.*\\'" . systemd-mode))
(easy-menu-define systemd-mode-menu systemd-mode-map
"Menu used in `systemd-mode' buffers."
'("Systemd"
["Open Unit File help" systemd-doc-open
:help "Documentation referenced in current buffer"]
["Open systemd.directives(7)" systemd-doc-directives
:help "Index of configuration directives"]))
;;;###autoload (add-to-list 'auto-mode-alist '("\\.nspawn\\'" . systemd-mode))
;;;###autoload (add-to-list 'auto-mode-alist `(,systemd-autoload-regexp . systemd-mode))
;;;###autoload (add-to-list 'auto-mode-alist `(,systemd-tempfn-autoload-regexp . systemd-mode))
;;;###autoload (add-to-list 'auto-mode-alist `(,systemd-dropin-autoload-regexp . systemd-mode))
;;;###autoload
(define-derived-mode systemd-mode fundamental-mode "Systemd"
"Major mode for editing systemd unit files. See
http://www.freedesktop.org/wiki/Software/systemd/ for more
information about systemd. The hook `systemd-mode-hook' is run
at mode initialization.
(define-derived-mode systemd-mode conf-mode "Systemd"
"Major mode for editing systemd unit files.
See https://www.freedesktop.org/wiki/Software/systemd/ for more
information about systemd.
In addition to any hooks its parent mode might have run, this
mode runs the hook `systemd-mode-hook' at mode initialization.
Key bindings:
\\{systemd-mode-map}"
(systemd-company--setup systemd-use-company-p)
(setq-local comment-start systemd-comment-start)
(setq-local font-lock-defaults '(systemd-font-lock-keywords)))
(set-keymap-parent systemd-mode-map nil)
(conf-mode-initialize systemd-comment-start)
(setq-local auto-fill-inhibit-regexp "^[ \t]*?[^;#]")
(add-hook 'completion-at-point-functions #'systemd-complete-at-point nil t)
(add-hook 'font-lock-extend-region-functions
'systemd-font-lock-extend-region nil t)
(setq-local syntax-propertize-function #'systemd-syntax-propertize)
(setq font-lock-defaults
'((systemd-font-lock-keywords
systemd-font-lock-keywords-1
systemd-font-lock-keywords-2
systemd-font-lock-keywords-3))))
(provide 'systemd)

85
test/systemd-tests.el Normal file
View File

@ -0,0 +1,85 @@
;;; systemd-tests.el --- Tests for systemd.el -*- lexical-binding: t -*-
;; Copyright (C) 2016-2020 Mark Oteiza <mvoteiza@udel.edu>
;; Author: Mark Oteiza <mvoteiza@udel.edu>
;; This file 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 file 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 file. If not, see <http://www.gnu.org/licenses/>.
;;; Commentary:
;;; Code:
(require 'ert)
(require 'systemd)
(ert-deftest test-normal-autoloads ()
"Tests for `systemd-autoload-regexp'.
This should match unit names: alpha-numeric ascii base names,
with exceptions in the set [-_.@\\]. Extensions are a prescribed
list. Some from systemd.unit(5) are excluded intentionally;
e.g. scope files which are created programmatically."
(let ((re systemd-autoload-regexp))
(should (string-match-p re "70-snark-ethernet.link"))
(should-not (string-match-p re "abusname"))
(should-not (string-match-p re "busname"))
;; Do not match empty unit name
(should-not (string-match-p re ".service"))
;; Non-alphanumeric ASCII exceptions
(should (string-match-p re "-.mount"))
(should (string-match-p re "dev-dm\\x2d4.service"))
(should (string-match-p re "proc-sys-fs-binfmt_misc.automount"))
(should (string-match-p re "bitlbee@.service"))
(should (string-match-p re "org.freedesktop.timedate1.busname"))
;; Do not match non-ASCII
(should-not (string-match-p re "割り箸.service"))
;; Do not match non-alphanumeric ASCII
(should-not (string-match-p re "~.service"))))
(ert-deftest test-tempfile-autoloads ()
"Tests for `systemd-tempfn-autoload-regexp'.
Should match file names generated by \"tempfn_random\" in
src/basic/fileio.c which, to quote its comments, does the
transformation
/foo/bar/waldo => /foo/bar/.#<extra>waldobaa2a261115984a9
but not plain unit names. For temp files made from systemctl
edit, <extra> is NULL as of systemd 229."
(let ((re systemd-tempfn-autoload-regexp))
(should-not (string-match-p re "/foo/bar/.#waldobaa2a261115984a9"))
(should (string-match-p re ".#override.conf064d87263873e7f7"))
(should (string-match-p re ".#FOObar.timer064d87263873e7f7"))
;; Do not match just the conf extension or unit names
(should-not (string-match-p re "override.conf"))
(should-not (string-match-p re "mmmmm.mount"))))
(ert-deftest test-dropin-autoloads ()
"Tests for `systemd-dropin-autoload-regexp'.
It should match file names with the \".conf\" extension if and
only if in an appropriately named parent directory."
(let ((re systemd-dropin-autoload-regexp))
(should (string-match-p re "/systemd/dog.socket.d/woof.conf"))
(should-not (string-match-p re "foobar.conf"))
(should-not (string-match-p re "/etc/modprobe.d/bonding.conf"))
(should-not (string-match-p re "/etc/systemd/system.conf"))
;; No restrictions on the base name
(should (string-match-p re ".config/systemd/user/foo.timer.d/კულტის.conf"))
(should (string-match-p re "/etc/systemd/user/c.service.d/a\nb.conf"))
;; Do not match inside a subdirectory of foobar.d/
(should-not (string-match-p re ".config/systemd/user/foo.timer.d/a/b.conf"))))
(provide 'systemd-tests)
;;; systemd-tests.el ends here

360
unit-directives.txt Normal file
View File

@ -0,0 +1,360 @@
Accept
AccuracySec
After
Alias
AllowIsolate
AllowedCPUs
AllowedMemoryNodes
Also
AmbientCapabilities
AppArmorProfile
AssertACPower
AssertArchitecture
AssertCapability
AssertControlGroupController
AssertDirectoryNotEmpty
AssertFileIsExecutable
AssertFileNotEmpty
AssertFirstBoot
AssertGroup
AssertHost
AssertKernelCommandLine
AssertKernelVersion
AssertNeedsUpdate
AssertPathExists
AssertPathExistsGlob
AssertPathIsDirectory
AssertPathIsMountPoint
AssertPathIsReadWrite
AssertPathIsSymbolicLink
AssertSecurity
AssertUser
AssertVirtualization
Backlog
Before
BindIPv6Only
BindPaths
BindReadOnlyPaths
BindToDevice
BindsTo
BlockIOAccounting
BlockIODeviceWeight
BlockIOReadBandwidth
BlockIOWeight
BlockIOWriteBandwidth
Broadcast
BusName
CPUAccounting
CPUAffinity
CPUQuota
CPUQuotaPeriodSec
CPUSchedulingPolicy
CPUSchedulingPriority
CPUSchedulingResetOnFork
CPUShares
CPUWeight
CacheDirectory
CacheDirectoryMode
CapabilityBoundingSet
CollectMode
ConditionACPower
ConditionArchitecture
ConditionCPUs
ConditionCapability
ConditionControlGroupController
ConditionDirectoryNotEmpty
ConditionFileIsExecutable
ConditionFileNotEmpty
ConditionFirstBoot
ConditionGroup
ConditionHost
ConditionKernelCommandLine
ConditionKernelVersion
ConditionMemory
ConditionNeedsUpdate
ConditionPathExists
ConditionPathExistsGlob
ConditionPathIsDirectory
ConditionPathIsMountPoint
ConditionPathIsReadWrite
ConditionPathIsSymbolicLink
ConditionSecurity
ConditionUser
ConditionVirtualization
ConfigurationDirectory
ConfigurationDirectoryMode
Conflicts
DefaultDependencies
DefaultInstance
DeferAcceptSec
Delegate
Description
DeviceAllow
DevicePolicy
DirectoryMode
DirectoryNotEmpty
DisableControllers
Documentation
DynamicUser
Environment
EnvironmentFile
ExecCondition
ExecReload
ExecStart
ExecStartPost
ExecStartPre
ExecStop
ExecStopPost
ExecStopPre
FailureAction
FailureActionExitStatus
FileDescriptorName
FileDescriptorStoreMax
FinalKillSignal
ForceUnmount
FreeBind
Group
GuessMainPID
IOAccounting
IODeviceLatencyTargetSec
IODeviceWeight
IOReadBandwidthMax
IOReadIOPSMax
IOSchedulingClass
IOSchedulingPriority
IOWeight
IOWriteBandwidthMax
IOWriteIOPSMax
IPAccounting
IPAddressAllow
IPAddressDeny
IPEgressFilterPath
IPIngressFilterPath
IPTOS
IPTTL
IgnoreOnIsolate
IgnoreSIGPIPE
InaccessiblePaths
JobRunningTimeoutSec
JobTimeoutAction
JobTimeoutRebootArgument
JobTimeoutSec
JoinsNamespaceOf
KeepAlive
KeepAliveIntervalSec
KeepAliveProbes
KeepAliveTimeSec
KeyringMode
KillMode
KillSignal
LazyUnmount
LimitAS
LimitCORE
LimitCPU
LimitDATA
LimitFSIZE
LimitLOCKS
LimitMEMLOCK
LimitMSGQUEUE
LimitNICE
LimitNOFILE
LimitNPROC
LimitRSS
LimitRTPRIO
LimitRTTIME
LimitSIGPENDING
LimitSTACK
ListenDatagram
ListenFIFO
ListenMessageQueue
ListenNetlink
ListenSequentialPacket
ListenSpecial
ListenStream
ListenUSBFunction
LockPersonality
LogExtraFields
LogLevelMax
LogRateLimitBurst
LogRateLimitIntervalSec
LogsDirectory
LogsDirectoryMode
MakeDirectory
Mark
MaxConnections
MaxConnectionsPerSource
MemoryAccounting
MemoryDenyWriteExecute
MemoryHigh
MemoryLimit
MemoryLow
MemoryMax
MemoryMin
MemorySwapMax
MessageQueueMaxMessages
MessageQueueMessageSize
MountAPIVFS
MountFlags
NUMAMask
NUMAPolicy
NetworkNamespacePath
Nice
NoDelay
NoNewPrivileges
NonBlocking
NotifyAccess
OOMPolicy
OOMScoreAdjust
OnActiveSec
OnBootSec
OnCalendar
OnClockChange
OnFailure
OnFailureJobMode
OnStartupSec
OnTimezoneChange
OnUnitActiveSec
OnUnitInactiveSec
Options
PAMName
PIDFile
PartOf
PassCredentials
PassEnvironment
PassSecurity
PathChanged
PathExists
PathExistsGlob
PathModified
Persistent
Personality
PipeSize
Priority
PrivateDevices
PrivateMounts
PrivateNetwork
PrivateTmp
PrivateUsers
PropagatesReloadTo
ProtectControlGroups
ProtectHome
ProtectHostname
ProtectKernelLogs
ProtectKernelModules
ProtectKernelTunables
ProtectSystem
RandomizedDelaySec
ReadOnlyPaths
ReadWritePaths
RebootArgument
ReceiveBuffer
RefuseManualStart
RefuseManualStop
ReloadPropagatedFrom
RemainAfterElapse
RemainAfterExit
RemoveIPC
RemoveOnStop
RequiredBy
Requires
RequiresMountsFor
Requisite
Restart
RestartForceExitStatus
RestartKillSignal
RestartPreventExitStatus
RestartSec
RestrictAddressFamilies
RestrictNamespaces
RestrictRealtime
RestrictSUIDSGID
ReusePort
RootDirectory
RootDirectoryStartOnly
RootImage
RuntimeDirectory
RuntimeDirectoryMode
RuntimeDirectoryPreserve
RuntimeMaxSec
SELinuxContext
SELinuxContextFromNet
SecureBits
SendBuffer
SendSIGHUP
SendSIGKILL
Service
Slice
SloppyOptions
SmackLabel
SmackLabelIPIn
SmackLabelIPOut
SmackProcessLabel
SocketGroup
SocketMode
SocketProtocol
SocketUser
Sockets
SourcePath
StandardError
StandardInput
StandardInputData
StandardInputText
StandardOutput
StartLimitAction
StartLimitBurst
StartLimitIntervalSec
StartupBlockIOWeight
StartupCPUShares
StartupCPUWeight
StartupIOWeight
StateDirectory
StateDirectoryMode
StopWhenUnneeded
SuccessAction
SuccessActionExitStatus
SuccessExitStatus
SupplementaryGroups
Symlinks
SyslogFacility
SyslogIdentifier
SyslogLevel
SyslogLevelPrefix
SystemCallArchitectures
SystemCallErrorNumber
SystemCallFilter
TCPCongestion
TTYPath
TTYReset
TTYVHangup
TTYVTDisallocate
TasksAccounting
TasksMax
TemporaryFileSystem
TimeoutAbortSec
TimeoutCleanSec
TimeoutIdleSec
TimeoutSec
TimeoutStartSec
TimeoutStopSec
TimerSlackNSec
Transparent
TriggerLimitBurst
TriggerLimitIntervalSec
Type
UMask
USBFunctionDescriptors
USBFunctionStrings
Unit
UnsetEnvironment
User
UtmpIdentifier
UtmpMode
WakeSystem
WantedBy
Wants
WatchdogSec
WatchdogSignal
What
Where
WorkingDirectory
Writable