dotcli: Add dot kde save with schema-backed defaults and completion.
Introduces the dot kde subcommand family (fish dispatcher plus a Python helper under commands/kde/), a flat identifier=value manifest, and dot kde save in both its explicit-identifier and no-argument refresh modes. Settings resolve to KDE's KConfigXT schema-backed mechanism via a (rcfile -> [kcfg files]) mapping table auto-derived by scanning the system schema directory (overridable via DOT_KDE_KCFG_DIR), plus a hand-maintained exceptions list for schemas that only declare their target rc file at runtime. Also wires tab-completion for dot kde save identifiers, sourced live from that same mapping table.
This commit is contained in:
@@ -42,12 +42,22 @@ Add README rows for `dot kde help`, `dot kde save <identifier>`, and
|
||||
|
||||
## Acceptance criteria
|
||||
|
||||
- [ ] `dot kde` and `dot kde save` are discoverable via `dot help` and dispatch correctly
|
||||
- [ ] Manifest parsing splits correctly on the first `=` (values may contain `=`) and the first two `.`s of the identifier (keys may contain dots/spaces)
|
||||
- [ ] The `(rcfile → [kcfg files])` mapping table is derived by scanning a schema directory for `<kcfgfile name="...">`, plus the hand-maintained exceptions list for `arg="true">` schemas
|
||||
- [ ] The schema directory is overridable via an environment variable, defaulting to the real system path
|
||||
- [ ] `dot kde save <identifier>` reads the current live value via `kreadconfig6` and adds a new declared entry to the manifest
|
||||
- [ ] `dot kde save` with no arguments refreshes every already-declared manifest entry's stored value from the live system, leaving undeclared settings untouched
|
||||
- [ ] `dot kde help` and `dot kde save help` print usage without touching the manifest or invoking `kreadconfig6`/`kwriteconfig6`
|
||||
- [ ] Tests run against a scratch `$HOME` and a fixture `.kcfg` schema directory, exercising manifest read/write, identifier parsing, and mapping-table-driven default lookup, per the project's scratch-`$HOME`-plus-`fishtape` convention
|
||||
- [ ] README has rows for `dot kde help`, `dot kde save <identifier>`, and `dot kde save`
|
||||
- [x] `dot kde` and `dot kde save` are discoverable via `dot help` and dispatch correctly
|
||||
- [x] Manifest parsing splits correctly on the first `=` (values may contain `=`) and the first two `.`s of the identifier (keys may contain dots/spaces)
|
||||
- [x] The `(rcfile → [kcfg files])` mapping table is derived by scanning a schema directory for `<kcfgfile name="...">`, plus the hand-maintained exceptions list for `arg="true">` schemas
|
||||
- [x] The schema directory is overridable via an environment variable, defaulting to the real system path
|
||||
- [x] `dot kde save <identifier>` reads the current live value via `kreadconfig6` and adds a new declared entry to the manifest
|
||||
- [x] `dot kde save` with no arguments refreshes every already-declared manifest entry's stored value from the live system, leaving undeclared settings untouched
|
||||
- [x] `dot kde help` and `dot kde save help` print usage without touching the manifest or invoking `kreadconfig6`/`kwriteconfig6`
|
||||
- [x] Tests run against a scratch `$HOME` and a fixture `.kcfg` schema directory, exercising manifest read/write, identifier parsing, and mapping-table-driven default lookup, per the project's scratch-`$HOME`-plus-`fishtape` convention
|
||||
- [x] README has rows for `dot kde help`, `dot kde save <identifier>`, and `dot kde save`
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
- File layout: `commands/kde/kde.fish` (thin dispatcher: help-before-dispatch at the `dot kde` level, then hands off to the Python helper) plus `commands/kde/kde.py` (manifest parsing, mapping-table derivation, mechanism resolution, `kreadconfig6` invocation, and `save`'s own help-before-work check).
|
||||
- Manifest location: `~/.config/dot/kde-manifest`, a flat file directly under `~/.config/dot/` as specified.
|
||||
- Mechanism dispatch (`resolve_mechanism`) implements all three branches described in the parent spec (shortcuts / schema / freeform) even though only `schema` is wired to real behavior; `shortcuts` and `freeform` both currently raise a clear "not yet supported" error from `save_one`, so later tasks can fill them in without restructuring the dispatch.
|
||||
- Test fixtures added under `tests/fixtures/kcfg/`: `testrc.kcfg` (a plain `<kcfgfile name="...">` schema, including an entry whose ini `key=` differs from its schema `name=`, and one entry whose key contains dots and spaces), `kwin.kcfg` (an `arg="true"` schema resolved only via the hand-maintained exceptions list), and `unmapped.kcfg` (an `arg="true"` schema absent from that list, proving it's never guessed at from its own filename).
|
||||
- Per the project's testing convention, `kreadconfig6` is never mocked for the tests exercising actual `save` behavior — it runs for real against fixture rc files under a scratch `$HOME`. It's faked (via a `$PATH`-prepended logging stub) only for the two tests asserting that `dot kde help` / `dot kde save help` never invoke it.
|
||||
- Applied two small cleanups surfaced by `/review-uncommitted`'s Standards pass before closing out: extracted a shared `_parse_kcfg` helper (was duplicated between `build_kcfg_map` and `find_schema_default`), and introduced a `Setting = namedtuple("Setting", ["file", "group", "key"])` to stop threading those three strings as separate parameters across `resolve_mechanism`/`find_schema_default`/`read_live_value`/`save_one`.
|
||||
- The Spec pass caught that the `unmapped.kcfg` fixture was created but never actually exercised by a test; added a case asserting `dot kde save unmapped.Whatever.Setting` resolves to freeform rather than schema-backed.
|
||||
|
||||
27
.config/dot/commands/kde/kde.fish
Normal file
27
.config/dot/commands/kde/kde.fish
Normal file
@@ -0,0 +1,27 @@
|
||||
function _dot_kde_usage
|
||||
echo "usage: dot kde <command>
|
||||
|
||||
Commands:
|
||||
save write live KDE settings into the manifest
|
||||
help show this message
|
||||
|
||||
Run 'dot kde <command> help' for flags on a specific command."
|
||||
end
|
||||
|
||||
function _dot_kde
|
||||
if test "$argv[1]" = help
|
||||
_dot_kde_usage
|
||||
return 0
|
||||
end
|
||||
|
||||
set -l helper_dir (status dirname)
|
||||
|
||||
switch "$argv[1]"
|
||||
case save
|
||||
python3 $helper_dir/kde.py save $argv[2..-1]
|
||||
return $status
|
||||
case '*'
|
||||
_dot_kde_usage
|
||||
return 1
|
||||
end
|
||||
end
|
||||
205
.config/dot/commands/kde/kde.py
Normal file
205
.config/dot/commands/kde/kde.py
Normal file
@@ -0,0 +1,205 @@
|
||||
#!/usr/bin/env python3
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
import xml.etree.ElementTree as ET
|
||||
from collections import defaultdict, namedtuple
|
||||
from pathlib import Path
|
||||
|
||||
KCFG_NS = "{http://www.kde.org/standards/kcfg/1.0}"
|
||||
DEFAULT_SCHEMA_DIR = "/usr/share/config.kcfg"
|
||||
|
||||
# .kcfg files that only declare their target rc file at runtime
|
||||
# (<kcfgfile arg="true">), so it can't be discovered by scanning.
|
||||
ARG_TRUE_RCFILES = {
|
||||
"kwin.kcfg": "kwinrc",
|
||||
}
|
||||
|
||||
SAVE_USAGE = """usage: dot kde save [identifier]
|
||||
|
||||
identifier declare a new manifest entry, seeded from its current live value
|
||||
(no args) refresh every already-declared manifest entry from the live system
|
||||
help show this message"""
|
||||
|
||||
Setting = namedtuple("Setting", ["file", "group", "key"])
|
||||
|
||||
|
||||
def parse_identifier(identifier):
|
||||
parts = identifier.split(".", 2)
|
||||
if len(parts) != 3:
|
||||
raise ValueError(f"invalid identifier {identifier!r} (expected file.group.key)")
|
||||
return Setting(*parts)
|
||||
|
||||
|
||||
def load_manifest(path):
|
||||
entries = {}
|
||||
if not path.exists():
|
||||
return entries
|
||||
for line in path.read_text().splitlines():
|
||||
if not line.strip():
|
||||
continue
|
||||
identifier, _, value = line.partition("=")
|
||||
entries[identifier] = value
|
||||
return entries
|
||||
|
||||
|
||||
def write_manifest(path, entries):
|
||||
lines = [f"{identifier}={value}" for identifier, value in entries.items()]
|
||||
path.write_text("".join(f"{line}\n" for line in lines))
|
||||
|
||||
|
||||
def _parse_kcfg(path):
|
||||
try:
|
||||
return ET.parse(path).getroot()
|
||||
except ET.ParseError:
|
||||
return None
|
||||
|
||||
|
||||
def _kcfgfile_name(root):
|
||||
elem = root.find(f"{KCFG_NS}kcfgfile")
|
||||
if elem is None:
|
||||
return None
|
||||
return elem.get("name")
|
||||
|
||||
|
||||
def build_kcfg_map(schema_dir):
|
||||
mapping = defaultdict(list)
|
||||
if not schema_dir.is_dir():
|
||||
return mapping
|
||||
|
||||
for path in sorted(schema_dir.glob("*.kcfg")):
|
||||
root = _parse_kcfg(path)
|
||||
if root is None:
|
||||
continue
|
||||
|
||||
rcfile = _kcfgfile_name(root) or ARG_TRUE_RCFILES.get(path.name)
|
||||
if rcfile:
|
||||
mapping[rcfile].append(path)
|
||||
|
||||
return mapping
|
||||
|
||||
|
||||
def find_schema_default(kcfg_paths, setting):
|
||||
for path in kcfg_paths:
|
||||
root = _parse_kcfg(path)
|
||||
if root is None:
|
||||
continue
|
||||
|
||||
for group_elem in root.iter(f"{KCFG_NS}group"):
|
||||
if group_elem.get("name") != setting.group:
|
||||
continue
|
||||
for entry in group_elem.findall(f"{KCFG_NS}entry"):
|
||||
if (entry.get("key") or entry.get("name")) != setting.key:
|
||||
continue
|
||||
default_elem = entry.find(f"{KCFG_NS}default")
|
||||
return default_elem.text if default_elem is not None and default_elem.text else ""
|
||||
|
||||
return None
|
||||
|
||||
|
||||
def iter_schema_identifiers(kcfg_map):
|
||||
for rcfile, paths in kcfg_map.items():
|
||||
for path in paths:
|
||||
root = _parse_kcfg(path)
|
||||
if root is None:
|
||||
continue
|
||||
|
||||
for group_elem in root.iter(f"{KCFG_NS}group"):
|
||||
group = group_elem.get("name")
|
||||
if not group:
|
||||
continue
|
||||
for entry in group_elem.findall(f"{KCFG_NS}entry"):
|
||||
key = entry.get("key") or entry.get("name")
|
||||
if key:
|
||||
yield f"{rcfile}.{group}.{key}"
|
||||
|
||||
|
||||
def resolve_mechanism(setting, kcfg_map):
|
||||
if setting.file == "kglobalshortcutsrc":
|
||||
return "shortcuts", None
|
||||
|
||||
default = find_schema_default(kcfg_map.get(setting.file, []), setting)
|
||||
if default is not None:
|
||||
return "schema", default
|
||||
|
||||
return "freeform", None
|
||||
|
||||
|
||||
def read_live_value(setting, default):
|
||||
cmd = ["kreadconfig6", "--file", setting.file, "--group", setting.group, "--key", setting.key]
|
||||
if default is not None:
|
||||
cmd += ["--default", default]
|
||||
|
||||
result = subprocess.run(cmd, capture_output=True, text=True)
|
||||
if result.returncode != 0:
|
||||
raise RuntimeError(
|
||||
f"kreadconfig6 failed for {setting.file}/{setting.group}/{setting.key}: {result.stderr.strip()}"
|
||||
)
|
||||
return result.stdout.rstrip("\n")
|
||||
|
||||
|
||||
def save_one(identifier, kcfg_map):
|
||||
setting = parse_identifier(identifier)
|
||||
mechanism, default = resolve_mechanism(setting, kcfg_map)
|
||||
if mechanism != "schema":
|
||||
raise RuntimeError(f"{identifier}: {mechanism} settings are not yet supported")
|
||||
return read_live_value(setting, default)
|
||||
|
||||
|
||||
def cmd_save(args, manifest_path, schema_dir):
|
||||
if args and args[0] == "help":
|
||||
print(SAVE_USAGE)
|
||||
return 0
|
||||
|
||||
if len(args) > 1:
|
||||
print("dot kde save: too many arguments", file=sys.stderr)
|
||||
return 1
|
||||
|
||||
kcfg_map = build_kcfg_map(schema_dir)
|
||||
manifest = load_manifest(manifest_path)
|
||||
|
||||
try:
|
||||
if args:
|
||||
manifest[args[0]] = save_one(args[0], kcfg_map)
|
||||
else:
|
||||
for identifier in manifest:
|
||||
manifest[identifier] = save_one(identifier, kcfg_map)
|
||||
except (ValueError, RuntimeError) as e:
|
||||
print(f"dot kde save: {e}", file=sys.stderr)
|
||||
return 1
|
||||
|
||||
write_manifest(manifest_path, manifest)
|
||||
return 0
|
||||
|
||||
|
||||
def cmd_complete(schema_dir):
|
||||
kcfg_map = build_kcfg_map(schema_dir)
|
||||
for identifier in sorted(set(iter_schema_identifiers(kcfg_map))):
|
||||
print(identifier)
|
||||
return 0
|
||||
|
||||
|
||||
def main(argv):
|
||||
if not argv:
|
||||
print("dot kde: no command given", file=sys.stderr)
|
||||
return 1
|
||||
|
||||
command, rest = argv[0], argv[1:]
|
||||
schema_dir = Path(os.environ.get("DOT_KDE_KCFG_DIR", DEFAULT_SCHEMA_DIR))
|
||||
manifest_path = Path(os.environ["HOME"]) / ".config" / "dot" / "kde-manifest"
|
||||
|
||||
if command == "save":
|
||||
return cmd_save(rest, manifest_path, schema_dir)
|
||||
|
||||
# Internal, not a user-facing `dot kde` subcommand -- called directly by
|
||||
# completions/dot.fish to source candidates from the live schema, never
|
||||
# dispatched to via kde.fish.
|
||||
if command == "complete":
|
||||
return cmd_complete(schema_dir)
|
||||
|
||||
print(f"dot kde: unknown command {command!r}", file=sys.stderr)
|
||||
return 1
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main(sys.argv[1:]))
|
||||
@@ -266,3 +266,146 @@ set -l pacman_called_help (test -s $PACMAN_LOG; and echo yes; or echo no)
|
||||
@test "dot install help mentions --restore" (string match -q '*--restore*' -- $help_output; echo $status) -eq 0
|
||||
@test "dot install help mentions --no-sync" (string match -q '*--no-sync*' -- $help_output; echo $status) -eq 0
|
||||
@test "dot install help never calls pacman" $pacman_called_help = no
|
||||
|
||||
# --- dot kde ---
|
||||
# The fixture schema directory stands in for the real /usr/share/config.kcfg:
|
||||
# testrc.kcfg declares a plain <kcfgfile name="testrc">, kwin.kcfg declares
|
||||
# <kcfgfile arg="true"> (resolved only via the hand-maintained exceptions
|
||||
# list, kwin.kcfg -> kwinrc), and unmapped.kcfg is an arg="true" schema with
|
||||
# no exceptions-list entry, so it never resolves to anything.
|
||||
set -l kcfg_fixtures (path resolve (status dirname)/fixtures/kcfg)
|
||||
set -gx DOT_KDE_KCFG_DIR $kcfg_fixtures
|
||||
|
||||
# kreadconfig6 itself is never mocked for the tests that exercise real
|
||||
# save behavior (per the project's convention, it runs for real against
|
||||
# fixture rc files under the scratch HOME) -- only the help-path tests below
|
||||
# swap in a logging fake, to prove kreadconfig6 is never invoked for them.
|
||||
set -l path_before_fake_kreadconfig $PATH
|
||||
|
||||
# --- dot kde help / dot kde save help touch neither the manifest nor kreadconfig6 ---
|
||||
set -gx HOME (mktemp -d)
|
||||
dot init --url $remote >/dev/null 2>&1
|
||||
mkdir -p $HOME/.config/dot/commands/kde
|
||||
cp $commands_dir/kde/kde.fish $HOME/.config/dot/commands/kde/kde.fish
|
||||
cp $commands_dir/kde/kde.py $HOME/.config/dot/commands/kde/kde.py
|
||||
|
||||
set -l fake_bin_kde (mktemp -d)
|
||||
set -gx KREADCONFIG_LOG (mktemp)
|
||||
echo '#!/bin/sh
|
||||
echo "$@" >>"$KREADCONFIG_LOG"
|
||||
exit 1' >$fake_bin_kde/kreadconfig6
|
||||
chmod +x $fake_bin_kde/kreadconfig6
|
||||
set -gx PATH $fake_bin_kde $PATH
|
||||
|
||||
set -l kde_help_output (dot kde help)
|
||||
set -l kde_help_status $status
|
||||
set -l kreadconfig_called_for_kde_help (test -s $KREADCONFIG_LOG; and echo yes; or echo no)
|
||||
set -l manifest_exists_after_kde_help (test -e $HOME/.config/dot/kde-manifest; and echo yes; or echo no)
|
||||
|
||||
@test "dot kde help succeeds" $kde_help_status -eq 0
|
||||
@test "dot kde help mentions save" (string match -q '*save*' -- $kde_help_output; echo $status) -eq 0
|
||||
@test "dot kde help never invokes kreadconfig6" $kreadconfig_called_for_kde_help = no
|
||||
@test "dot kde help does not create a manifest" $manifest_exists_after_kde_help = no
|
||||
|
||||
set -l kde_save_help_output (dot kde save help)
|
||||
set -l kde_save_help_status $status
|
||||
set -l kreadconfig_called_for_save_help (test -s $KREADCONFIG_LOG; and echo yes; or echo no)
|
||||
set -l manifest_exists_after_save_help (test -e $HOME/.config/dot/kde-manifest; and echo yes; or echo no)
|
||||
|
||||
@test "dot kde save help succeeds" $kde_save_help_status -eq 0
|
||||
@test "dot kde save help mentions identifier" (string match -q '*identifier*' -- $kde_save_help_output; echo $status) -eq 0
|
||||
@test "dot kde save help never invokes kreadconfig6" $kreadconfig_called_for_save_help = no
|
||||
@test "dot kde save help does not create a manifest" $manifest_exists_after_save_help = no
|
||||
|
||||
set -gx PATH $path_before_fake_kreadconfig
|
||||
|
||||
# --- dot kde save <identifier>: declares a new manifest entry from the real live value ---
|
||||
set -gx HOME (mktemp -d)
|
||||
dot init --url $remote >/dev/null 2>&1
|
||||
mkdir -p $HOME/.config/dot/commands/kde
|
||||
cp $commands_dir/kde/kde.fish $HOME/.config/dot/commands/kde/kde.fish
|
||||
cp $commands_dir/kde/kde.py $HOME/.config/dot/commands/kde/kde.py
|
||||
mkdir -p $HOME/.config
|
||||
printf '[General]\nGreeting=Hi=There\n' >$HOME/.config/testrc
|
||||
set -l manifest $HOME/.config/dot/kde-manifest
|
||||
|
||||
dot kde save testrc.General.Greeting >/dev/null 2>&1
|
||||
set -l save_status $status
|
||||
|
||||
@test "dot kde save <identifier> succeeds" $save_status -eq 0
|
||||
@test "declares the identifier with its live value, preserving an embedded '='" (cat $manifest | string collect) = "testrc.General.Greeting=Hi=There"
|
||||
|
||||
# a kcfg entry whose ini key (key=) differs from its schema name still
|
||||
# resolves correctly, falling back to the schema default when unset live
|
||||
dot kde save testrc.General.RealKey >/dev/null 2>&1
|
||||
@test "resolves an aliased kcfg key (name != key) to its schema default" (string match -q '*testrc.General.RealKey=AliasDefault*' -- (cat $manifest); echo $status) -eq 0
|
||||
|
||||
# the identifier is split on the first two dots only, so the key portion
|
||||
# may itself contain further dots and spaces
|
||||
dot kde save "testrc.General.Some.Key With Spaces" >/dev/null 2>&1
|
||||
@test "an identifier's key portion may contain further dots and spaces" (string match -q '*testrc.General.Some.Key With Spaces=SpacedDefault*' -- (cat $manifest); echo $status) -eq 0
|
||||
|
||||
# an arg="true" schema resolves through the hand-maintained exceptions list
|
||||
# (kwin.kcfg -> kwinrc), not by scanning for a static <kcfgfile name>
|
||||
dot kde save kwinrc.Windows.BorderSize >/dev/null 2>&1
|
||||
@test "resolves an arg=true schema via the hand-maintained exceptions list" (string match -q '*kwinrc.Windows.BorderSize=Normal*' -- (cat $manifest); echo $status) -eq 0
|
||||
|
||||
set -l declared_count_before_freeform (cat $manifest | count)
|
||||
|
||||
# a setting whose rc file never appears in the mapping table falls to the
|
||||
# freeform branch, which the dispatch structure accounts for but does not
|
||||
# implement yet
|
||||
dot kde save somefreeform.Group.Key >/dev/null 2>&1
|
||||
set -l unmapped_status $status
|
||||
set -l declared_count_after_freeform (cat $manifest | count)
|
||||
|
||||
@test "an unmapped rc file is not silently treated as schema-backed" $unmapped_status -ne 0
|
||||
@test "a rejected freeform save adds no manifest entry" $declared_count_after_freeform -eq $declared_count_before_freeform
|
||||
|
||||
# an arg="true" schema *absent* from the exceptions list (unmapped.kcfg)
|
||||
# must not be guessed at (e.g. from its own filename) -- it contributes
|
||||
# nothing to the mapping table, so its settings fall to freeform too
|
||||
dot kde save unmapped.Whatever.Setting >/dev/null 2>&1
|
||||
set -l unlisted_arg_true_status $status
|
||||
set -l declared_count_after_unlisted (cat $manifest | count)
|
||||
|
||||
@test "an arg=true schema missing from the exceptions list resolves to freeform, not schema" $unlisted_arg_true_status -ne 0
|
||||
@test "a rejected unlisted-arg=true save adds no manifest entry" $declared_count_after_unlisted -eq $declared_count_before_freeform
|
||||
|
||||
# --- dot kde save with no arguments refreshes every already-declared entry ---
|
||||
printf '[General]\nGreeting=Changed\n' >$HOME/.config/testrc
|
||||
dot kde save >/dev/null 2>&1
|
||||
set -l refresh_status $status
|
||||
set -l declared_count_after_refresh (cat $manifest | count)
|
||||
|
||||
@test "dot kde save with no arguments succeeds" $refresh_status -eq 0
|
||||
@test "refreshes an already-declared entry's value from the live system" (string match -q '*testrc.General.Greeting=Changed*' -- (cat $manifest); echo $status) -eq 0
|
||||
@test "refresh leaves other already-declared entries untouched" (string match -q '*testrc.General.RealKey=AliasDefault*' -- (cat $manifest); echo $status) -eq 0
|
||||
@test "refresh adds no new undeclared entries" $declared_count_after_refresh -eq $declared_count_before_freeform
|
||||
|
||||
# --- misuse: too many arguments / a malformed identifier ---
|
||||
dot kde save one two >/dev/null 2>&1
|
||||
set -l too_many_args_status $status
|
||||
@test "dot kde save rejects more than one identifier" $too_many_args_status -ne 0
|
||||
|
||||
dot kde save nodots >/dev/null 2>&1
|
||||
set -l bad_identifier_status $status
|
||||
@test "dot kde save rejects an identifier without file.group.key structure" $bad_identifier_status -ne 0
|
||||
|
||||
# --- kde.py complete: tab-completion candidates, sourced from the live
|
||||
# schema mapping table rather than a hardcoded list. This is the
|
||||
# underlying data completions/dot.fish shells out to; the fish
|
||||
# completion wiring itself is verified manually (no existing
|
||||
# infrastructure tests completions at all, per the nested-subcommand
|
||||
# prefactoring task) ---
|
||||
set -l complete_output (python3 $HOME/.config/dot/commands/kde/kde.py complete)
|
||||
|
||||
@test "kde.py complete lists a schema-backed identifier" (string match -q '*testrc.General.Greeting*' -- $complete_output; echo $status) -eq 0
|
||||
@test "kde.py complete resolves an aliased kcfg key to its ini key, not its schema name" (string match -q '*testrc.General.RealKey*' -- $complete_output; echo $status) -eq 0
|
||||
@test "kde.py complete lists an arg=true schema resolved via the exceptions list" (string match -q '*kwinrc.Windows.BorderSize*' -- $complete_output; echo $status) -eq 0
|
||||
@test "kde.py complete never lists an aliased entry under its schema name" (string match -q '*testrc.General.AliasedKey*' -- $complete_output; echo $status) -eq 1
|
||||
@test "kde.py complete never lists an arg=true schema absent from the exceptions list" (string match -q '*Whatever.Setting*' -- $complete_output; echo $status) -eq 1
|
||||
|
||||
# --- dot help / dot help discovers dot kde ---
|
||||
set -l help_with_kde (dot help)
|
||||
@test "dot help lists the kde subcommand" (string match -q '*kde*' -- $help_with_kde; echo $status) -eq 0
|
||||
|
||||
9
.config/dot/tests/fixtures/kcfg/kwin.kcfg
vendored
Normal file
9
.config/dot/tests/fixtures/kcfg/kwin.kcfg
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<kcfg xmlns="http://www.kde.org/standards/kcfg/1.0">
|
||||
<kcfgfile arg="true"/>
|
||||
<group name="Windows">
|
||||
<entry name="BorderSize" type="String">
|
||||
<default>Normal</default>
|
||||
</entry>
|
||||
</group>
|
||||
</kcfg>
|
||||
15
.config/dot/tests/fixtures/kcfg/testrc.kcfg
vendored
Normal file
15
.config/dot/tests/fixtures/kcfg/testrc.kcfg
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<kcfg xmlns="http://www.kde.org/standards/kcfg/1.0">
|
||||
<kcfgfile name="testrc"/>
|
||||
<group name="General">
|
||||
<entry name="Greeting" type="String">
|
||||
<default>Hello</default>
|
||||
</entry>
|
||||
<entry name="AliasedKey" key="RealKey" type="String">
|
||||
<default>AliasDefault</default>
|
||||
</entry>
|
||||
<entry name="Some.Key With Spaces" type="String">
|
||||
<default>SpacedDefault</default>
|
||||
</entry>
|
||||
</group>
|
||||
</kcfg>
|
||||
9
.config/dot/tests/fixtures/kcfg/unmapped.kcfg
vendored
Normal file
9
.config/dot/tests/fixtures/kcfg/unmapped.kcfg
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<kcfg xmlns="http://www.kde.org/standards/kcfg/1.0">
|
||||
<kcfgfile arg="true"/>
|
||||
<group name="Whatever">
|
||||
<entry name="Setting" type="String">
|
||||
<default>Unreachable</default>
|
||||
</entry>
|
||||
</group>
|
||||
</kcfg>
|
||||
Reference in New Issue
Block a user