hiiro 0.1.383 → 0.1.384
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +9 -13
- data/bin/h-js +21 -0
- data/bin/h-plist +214 -0
- data/doc/AGENTS_md.html +898 -0
- data/doc/AppTest/MockApp.html +192 -0
- data/doc/AppTest/MockEnvironment.html +192 -0
- data/doc/AppTest/MockGit.html +157 -0
- data/doc/AppTest/MockItem.html +178 -0
- data/doc/AppTest/MockMatcher.html +200 -0
- data/doc/AppTest/MockResult.html +235 -0
- data/doc/AppTest.html +401 -0
- data/doc/Asarfile/Appfile.html +4219 -0
- data/doc/Asarfile.html +1445 -0
- data/doc/BackgroundTest.html +388 -0
- data/doc/BinsTest.html +245 -0
- data/doc/BranchManager.html +373 -804
- data/doc/BranchTest/MockGit.html +272 -0
- data/doc/BranchTest.html +621 -0
- data/doc/CHANGELOG_md.html +771 -0
- data/doc/CLAUDE_md.html +310 -1092
- data/doc/ClaudeTest.html +323 -0
- data/doc/CommitTest.html +271 -0
- data/doc/ConfigTest.html +407 -0
- data/doc/ContextBundleManager.html +811 -0
- data/doc/CurrentTaskTest.html +325 -0
- data/doc/Directory.html +63 -770
- data/doc/EnvFile.html +397 -0
- data/doc/EnvironmentTest.html +610 -0
- data/doc/FilesystemEffectsTest.html +478 -0
- data/doc/FuzzyfindTest.html +382 -0
- data/doc/Gemfile.html +309 -669
- data/doc/Gemfile_lock.html +336 -691
- data/doc/GitBranchTest.html +428 -0
- data/doc/GitBranchesTest.html +428 -0
- data/doc/GitEffectsTest.html +381 -0
- data/doc/GitPrTest.html +581 -0
- data/doc/GitRemoteTest.html +519 -0
- data/doc/GitWorktreeTest.html +576 -0
- data/doc/GitWorktreesTest.html +712 -0
- data/doc/Globber.html +593 -0
- data/doc/HerdrEffectsTest.html +464 -0
- data/doc/HerdrPluginTest.html +344 -0
- data/doc/HerdrWorkspaceTest.html +230 -0
- data/doc/Hiiro/AnyStruct.html +78 -835
- data/doc/Hiiro/AppFiles.html +88 -882
- data/doc/Hiiro/AppRecord.html +233 -0
- data/doc/Hiiro/Args.html +82 -855
- data/doc/Hiiro/Assignment.html +232 -0
- data/doc/Hiiro/Background.html +287 -0
- data/doc/Hiiro/Bins.html +70 -818
- data/doc/Hiiro/Branch.html +416 -0
- data/doc/Hiiro/Capture.html +314 -0
- data/doc/Hiiro/CheckRun.html +261 -0
- data/doc/Hiiro/Config.html +178 -830
- data/doc/Hiiro/CurrentTask.html +254 -0
- data/doc/Hiiro/DB/JSON.html +200 -0
- data/doc/Hiiro/DB.html +440 -0
- data/doc/Hiiro/Effects/Executor/Filesystem/NullFilesystem.html +642 -0
- data/doc/Hiiro/Effects/Executor/Filesystem.html +750 -0
- data/doc/Hiiro/Effects/Executor/NullExecutor.html +436 -0
- data/doc/Hiiro/Effects/Executor.html +509 -0
- data/doc/Hiiro/Effects.html +121 -0
- data/doc/Hiiro/Error.html +127 -0
- data/doc/Hiiro/FallbackTarget/App.html +308 -0
- data/doc/Hiiro/FallbackTarget/Environment.html +777 -0
- data/doc/Hiiro/FallbackTarget.html +1748 -0
- data/doc/Hiiro/Fuzzyfind.html +70 -818
- data/doc/Hiiro/Git/Branch.html +106 -975
- data/doc/Hiiro/Git/Branches.html +128 -1084
- data/doc/Hiiro/Git/Pr.html +2575 -1115
- data/doc/Hiiro/Git/Remote.html +106 -971
- data/doc/Hiiro/Git/Worktree.html +90 -899
- data/doc/Hiiro/Git/Worktrees.html +129 -1085
- data/doc/Hiiro/Git.html +306 -1413
- data/doc/Hiiro/Glob.html +58 -757
- data/doc/Hiiro/Herdr/Collection/Workspace/Workspaces/Tab/Tabs/Pane/Panes.html +5289 -0
- data/doc/Hiiro/Herdr/Collection/Workspace/Workspaces/Tab/Tabs/Pane.html +5470 -0
- data/doc/Hiiro/Herdr/Collection/Workspace/Workspaces/Tab/Tabs.html +2292 -0
- data/doc/Hiiro/Herdr/Collection/Workspace/Workspaces/Tab.html +2619 -0
- data/doc/Hiiro/Herdr/Collection/Workspace/Workspaces.html +1339 -0
- data/doc/Hiiro/Herdr/Collection/Workspace.html +2337 -0
- data/doc/Hiiro/Herdr/Collection.html +2190 -0
- data/doc/Hiiro/Herdr.html +125 -0
- data/doc/Hiiro/InputFile.html +550 -0
- data/doc/Hiiro/Invocation.html +356 -0
- data/doc/Hiiro/InvocationResolution.html +218 -0
- data/doc/Hiiro/Link.html +507 -0
- data/doc/Hiiro/Matcher/Item.html +60 -777
- data/doc/Hiiro/Matcher/PathResult.html +106 -979
- data/doc/Hiiro/Matcher/Result.html +110 -1001
- data/doc/Hiiro/Matcher.html +147 -1138
- data/doc/Hiiro/Notification.html +159 -953
- data/doc/Hiiro/Options/Args/Definition.html +557 -0
- data/doc/Hiiro/Options/Args.html +1301 -1020
- data/doc/Hiiro/Options.html +155 -963
- data/doc/Hiiro/PaneHome.html +312 -0
- data/doc/Hiiro/Paths/Symlink.html +102 -946
- data/doc/Hiiro/Paths.html +75 -838
- data/doc/Hiiro/PinRecord.html +309 -0
- data/doc/Hiiro/PinnedPRManager.html +1388 -0
- data/doc/Hiiro/PinnedPr.html +2261 -0
- data/doc/Hiiro/Project.html +233 -0
- data/doc/Hiiro/Projects.html +437 -0
- data/doc/Hiiro/PsProcess.html +770 -0
- data/doc/Hiiro/Queue/Prompt.html +177 -927
- data/doc/Hiiro/Queue.html +963 -1622
- data/doc/Hiiro/Rbenv.html +197 -988
- data/doc/Hiiro/RegistryEntry/Hiiro.html +176 -0
- data/doc/Hiiro/RegistryEntry.html +842 -0
- data/doc/Hiiro/Reminder.html +238 -0
- data/doc/Hiiro/Result.html +462 -0
- data/doc/Hiiro/RunnerTool.html +106 -956
- data/doc/Hiiro/Runners/Bin.html +98 -939
- data/doc/Hiiro/Runners/Subcommand.html +100 -956
- data/doc/Hiiro/Runners.html +150 -1043
- data/doc/Hiiro/ServiceManager.html +251 -1283
- data/doc/Hiiro/Shell.html +226 -772
- data/doc/Hiiro/ShellCommand.html +277 -0
- data/doc/Hiiro/SparseGroups.html +64 -784
- data/doc/Hiiro/Tag.html +543 -0
- data/doc/Hiiro/Tags.html +117 -906
- data/doc/Hiiro/Task.html +203 -982
- data/doc/Hiiro/TaskCli/Commands/Error.html +137 -0
- data/doc/Hiiro/TaskCli/Commands.html +3128 -0
- data/doc/Hiiro/TaskCli.html +220 -0
- data/doc/Hiiro/TaskManager/Config.html +110 -876
- data/doc/Hiiro/TaskManager.html +530 -1372
- data/doc/Hiiro/TaskRecord.html +511 -0
- data/doc/Hiiro/TaskResource.html +176 -0
- data/doc/Hiiro/TaskSessions/Error.html +131 -0
- data/doc/Hiiro/TaskSessions.html +247 -0
- data/doc/Hiiro/Tasks.html +289 -776
- data/doc/Hiiro/TestHarness.html +1105 -0
- data/doc/Hiiro/TodoItem.html +184 -1165
- data/doc/Hiiro/TodoManager.html +163 -1185
- data/doc/Hiiro/Tree.html +123 -898
- data/doc/Hiiro/Tui/ListScreen.html +672 -0
- data/doc/Hiiro/Tui/Terminal.html +488 -0
- data/doc/Hiiro/Tui.html +121 -0
- data/doc/Hiiro.html +631 -1851
- data/doc/HiiroAddCmdTest.html +366 -0
- data/doc/HiiroAddDefaultTest.html +384 -0
- data/doc/HiiroRunnersBinTest.html +363 -0
- data/doc/HiiroRunnersSubcommandTest.html +430 -0
- data/doc/HiiroSetup.html +190 -0
- data/doc/HiiroTest.html +533 -0
- data/doc/HomeDirs.html +528 -0
- data/doc/JsTest.html +187 -0
- data/doc/LICENSE.html +309 -669
- data/doc/LinkManager/Link.html +86 -885
- data/doc/LinkManager.html +224 -1007
- data/doc/LinkTest/MockLinkManager.html +331 -0
- data/doc/LinkTest.html +198 -0
- data/doc/MatcherItemTest.html +167 -0
- data/doc/MatcherResultTest.html +375 -0
- data/doc/MatcherTest.html +908 -0
- data/doc/MockHiiro.html +346 -0
- data/doc/NotificationTest/MockHiiroForNotify.html +180 -0
- data/doc/NotificationTest.html +592 -0
- data/doc/Notify.html +77 -828
- data/doc/NotifyPluginTest.html +421 -0
- data/doc/Object.html +7684 -1547
- data/doc/ObsidianNotes.html +599 -0
- data/doc/OptionsDefinitionTest.html +348 -0
- data/doc/OptionsTest.html +1047 -0
- data/doc/PaneTest/MockHerdr.html +1113 -0
- data/doc/PaneTest.html +415 -0
- data/doc/Pins/Pin.html +355 -1062
- data/doc/Pins.html +73 -815
- data/doc/PinsPinTest/MockHiiro.html +178 -0
- data/doc/PinsPinTest.html +514 -0
- data/doc/PluginTest.html +388 -0
- data/doc/PortfolioApi.html +311 -0
- data/doc/Project.html +84 -941
- data/doc/ProjectPluginTest.html +507 -0
- data/doc/ProjectTest.html +249 -0
- data/doc/QueueHerdrTest.html +181 -0
- data/doc/README_md.html +557 -741
- data/doc/Rakefile.html +309 -669
- data/doc/ReminderManager/Reminder.html +626 -0
- data/doc/ReminderManager.html +469 -0
- data/doc/RequirePathsTest.html +168 -0
- data/doc/RubyGems/Version/Git/Claude.html +251 -0
- data/doc/RubyGems/Version/Git/RubyGem.html +214 -0
- data/doc/RubyGems/Version/Git.html +1175 -0
- data/doc/RubyGems/Version.html +379 -0
- data/doc/RubyGems.html +251 -0
- data/doc/SaveTest.html +352 -0
- data/doc/ServiceManagerHerdrTest.html +187 -0
- data/doc/SessionTest/MockHerdr.html +699 -0
- data/doc/SessionTest.html +343 -0
- data/doc/ShaTest.html +343 -0
- data/doc/ShellTest.html +430 -0
- data/doc/String.html +58 -757
- data/doc/SystemCallCapture.html +267 -0
- data/doc/TODO_md.html +311 -672
- data/doc/TaskCommandTest.html +2416 -0
- data/doc/TaskManager.html +1554 -1599
- data/doc/TaskManagerConfigTest.html +451 -0
- data/doc/TaskManagerFilterTasksTest.html +421 -0
- data/doc/TaskManagerFromWorktreeTest.html +308 -0
- data/doc/TaskTest.html +545 -0
- data/doc/TaskToggleTui.html +224 -0
- data/doc/TestHarnessEffectsTest.html +562 -0
- data/doc/TestHelpers.html +231 -0
- data/doc/TodoItemTest.html +983 -0
- data/doc/TodoManagerTest.html +1172 -0
- data/doc/TodoTest/MockTodoManager.html +398 -0
- data/doc/TodoTest.html +243 -0
- data/doc/TreeTest.html +477 -0
- data/doc/WindowTest/MockHerdr.html +746 -0
- data/doc/WindowTest.html +343 -0
- data/doc/WtreeTest.html +566 -0
- data/doc/bin/h-_config.html +362 -0
- data/doc/bin/h-dsstore-read.html +358 -0
- data/doc/css/fonts.css +167 -0
- data/doc/css/rdoc.css +328 -1600
- data/doc/demo_sh.html +314 -674
- data/doc/docs/README_md.html +477 -736
- data/doc/docs/coupling-and-extraction-plan_txt.html +1589 -0
- data/doc/docs/docker-testing-guide_md.html +668 -865
- data/doc/docs/h-app_md.html +615 -0
- data/doc/docs/h-bg_md.html +420 -0
- data/doc/docs/h-bin_md.html +475 -0
- data/doc/docs/h-branch_md.html +1035 -0
- data/doc/docs/h-claude_md.html +1121 -0
- data/doc/docs/h-commit_md.html +417 -0
- data/doc/docs/h-config_md.html +522 -0
- data/doc/docs/h-cpr_md.html +399 -0
- data/doc/docs/h-db_md.html +555 -0
- data/doc/docs/h-file_md.html +422 -0
- data/doc/docs/h-herdr_md.html +470 -0
- data/doc/docs/h-img_md.html +430 -0
- data/doc/docs/h-link_md.html +619 -0
- data/doc/docs/h-misc_md.html +435 -0
- data/doc/docs/h-notify_md.html +510 -0
- data/doc/docs/h-pane_md.html +405 -784
- data/doc/docs/h-plugin_md.html +382 -705
- data/doc/docs/h-pm_md.html +549 -0
- data/doc/docs/h-pr-monitor_md.html +458 -0
- data/doc/docs/h-pr_md.html +795 -0
- data/doc/docs/h-project_md.html +522 -0
- data/doc/docs/h-queue_md.html +744 -0
- data/doc/docs/h-registry_md.html +542 -0
- data/doc/docs/h-run_md.html +493 -0
- data/doc/docs/h-save_md.html +453 -0
- data/doc/docs/h-service_md.html +654 -0
- data/doc/docs/h-session_md.html +370 -762
- data/doc/docs/h-sha_md.html +461 -0
- data/doc/docs/h-sparse_md.html +493 -0
- data/doc/docs/h-subtask_md.html +359 -0
- data/doc/docs/h-tags_md.html +417 -0
- data/doc/docs/h-task_md.html +447 -0
- data/doc/docs/h-title_md.html +400 -0
- data/doc/docs/h-todo_md.html +617 -0
- data/doc/docs/h-window_md.html +356 -785
- data/doc/docs/h-wtree_md.html +539 -0
- data/doc/docs/h_md.html +605 -0
- data/doc/docs/t_md.html +659 -0
- data/doc/docs/why-t_md.html +698 -0
- data/doc/fonts/Lato-Light.ttf +0 -0
- data/doc/fonts/Lato-LightItalic.ttf +0 -0
- data/doc/fonts/Lato-Regular.ttf +0 -0
- data/doc/fonts/Lato-RegularItalic.ttf +0 -0
- data/doc/fonts/SourceCodePro-Bold.ttf +0 -0
- data/doc/fonts/SourceCodePro-Regular.ttf +0 -0
- data/doc/h-tmux-plugins_tmux.html +309 -669
- data/doc/herdr-plugin/herdr-plugin_toml.html +375 -0
- data/doc/hiiro_gemspec.html +621 -0
- data/doc/images/add.png +0 -0
- data/doc/images/arrow_up.png +0 -0
- data/doc/images/brick.png +0 -0
- data/doc/images/brick_link.png +0 -0
- data/doc/images/bug.png +0 -0
- data/doc/images/bullet_black.png +0 -0
- data/doc/images/bullet_toggle_minus.png +0 -0
- data/doc/images/bullet_toggle_plus.png +0 -0
- data/doc/images/date.png +0 -0
- data/doc/images/delete.png +0 -0
- data/doc/images/find.png +0 -0
- data/doc/images/loadingAnimation.gif +0 -0
- data/doc/images/macFFBgHack.png +0 -0
- data/doc/images/package.png +0 -0
- data/doc/images/page_green.png +0 -0
- data/doc/images/page_white_text.png +0 -0
- data/doc/images/page_white_width.png +0 -0
- data/doc/images/plugin.png +0 -0
- data/doc/images/ruby.png +0 -0
- data/doc/images/tag_blue.png +0 -0
- data/doc/images/tag_green.png +0 -0
- data/doc/images/transparent.png +0 -0
- data/doc/images/wrench.png +0 -0
- data/doc/images/wrench_orange.png +0 -0
- data/doc/images/zoom.png +0 -0
- data/doc/index.html +313 -667
- data/doc/js/darkfish.js +120 -0
- data/doc/js/search.js +110 -0
- data/doc/merge.html +353 -0
- data/doc/notes.html +328 -688
- data/doc/obsidian_slides_md.html +353 -687
- data/doc/record-demo_sh.html +313 -673
- data/doc/script/compare.html +310 -670
- data/doc/script/install.html +309 -669
- data/doc/script/sync.html +312 -672
- data/doc/script/test.html +309 -669
- data/doc/script/update.html +323 -667
- data/doc/side-effect-separation-plan_md.html +439 -0
- data/doc/slides_md.html +374 -727
- data/doc/table_of_contents.html +10197 -0
- data/lib/hiiro/version.rb +1 -1
- data/script/publish +1 -1
- metadata +230 -3
- data/.DS_Store +0 -0
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 308d4ea2a261c3dd45eedd5b40bb0bcf8ada1b6cd2310bd908abac4e4d73c408
|
|
4
|
+
data.tar.gz: e138d7b8aeed4b9fa598dbe8d0d7dfb45abec78658c338a048d42d8d540a3a27
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 9d0e4d5ab790f5c262d7d4c03517c7caf40214ad9e9e2b76e7df84724bdf19f105eff32c935bcdea3f73cc64ec3bdf5e922258ffed5c44cdd9969b2649e313b7
|
|
7
|
+
data.tar.gz: 74a0868f58e19659707345d4241f08ae0c112f2e925b2c5fe43e6faf008b7eceafdcc914aba27ce5f638ccd7c7c4b55a383ac7f3126cd78cc1e7b26a2daf263c
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.1.384] - 2026-09-23
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
- `h plist` command for working with property lists
|
|
7
|
+
|
|
8
|
+
### Fixed
|
|
9
|
+
- publish script now requires hiiro unconditionally at startup instead of only when falling back to local version
|
|
10
|
+
|
|
3
11
|
## [0.1.381] - 2026-09-20
|
|
4
12
|
|
|
5
13
|
### Added
|
|
@@ -14,8 +22,6 @@
|
|
|
14
22
|
- `h save` subcommands: `ls`/`list`, `dir`, `show`/`cat`, `copy`, `open`, `edit`, `rm`/`remove` for managing saved files
|
|
15
23
|
- `t path`, `t cd`, `t start`, and `t switch` accept optional `APP` argument to select a configured relative directory beneath the task root
|
|
16
24
|
- APP resolves by exact name or unique case-sensitive prefix; fails when ambiguous or missing
|
|
17
|
-
|
|
18
|
-
### Added
|
|
19
25
|
- `t switch` / `t workspace` and `t cd` accept an optional APP positional (or `--app`) resolving through the apps registry by exact name or unique prefix; the workspace or pane cd targets the app directory under the task worktree, e.g. `t switch aldi cpm` opens `~/work/aldi/main/retailer-tools/content-page-migrator`
|
|
20
26
|
|
|
21
27
|
## [0.1.376] - 2026-09-14
|
|
@@ -143,14 +149,4 @@
|
|
|
143
149
|
|
|
144
150
|
### Removed
|
|
145
151
|
- Remove tmux paste-buffer, jumplist, task-color, focus-hook, and arbitrary-layout features that Herdr 0.8.2 does not support.
|
|
146
|
-
- Remove the old `Hiiro::Tmux` adapter and tmux-specific command tests.
|
|
147
|
-
|
|
148
|
-
### Fixed
|
|
149
|
-
- Strip the desktop notifier executable path and run notifications and sounds as detached processes instead of creating persistent Herdr tabs.
|
|
150
|
-
- Preserve `add_cmd` declaration locations and argument metadata in generated help; allow command groups to pass arguments and help through to child commands.
|
|
151
|
-
- Make undeclared `add_cmd opts:` entries boolean flags without consuming positional arguments; preserve explicit options and reserve conflicting short aliases.
|
|
152
|
-
- Show selected command options for `add_cmd -h`/`--help` without executing the command block.
|
|
153
|
-
- Focus the exact Herdr pane through the socket API and read the CLI's plain-text pane output without JSON parsing.
|
|
154
|
-
- Restore the missing `Hiiro::Bins` helper so `require "hiiro"` boots and commands like `h jumplist record` dispatch correctly.
|
|
155
|
-
- Make Hiiro's Ruby requirement explicit as Ruby 3.2+ and have rbenv-wide gem installs skip incompatible Ruby versions.
|
|
156
|
-
- Update the publish script to preserve the Ruby support constant, run only on supported Ruby, and install releases only into compatible rbenv versions.
|
|
152
|
+
- Remove the old `Hiiro::Tmux` adapter and tmux-specific command tests.
|
data/bin/h-js
CHANGED
|
@@ -5,6 +5,27 @@ require 'hiiro'
|
|
|
5
5
|
# sed -n '/scripts.*[{]/,/[}]/p' package.json
|
|
6
6
|
|
|
7
7
|
Hiiro.run do
|
|
8
|
+
add_cmd :add, args: ['NAME', 'COMMAND...'] do
|
|
9
|
+
abort 'Usage: h-js add NAME COMMAND... (use -- before command flags)' unless opts.args.length >= 2
|
|
10
|
+
name, *command_args = opts.args
|
|
11
|
+
abort 'Script name cannot be blank' if name.strip.empty?
|
|
12
|
+
command = command_args.length == 1 ? command_args.first : Shellwords.join(command_args)
|
|
13
|
+
abort 'Script command cannot be blank' if command.strip.empty?
|
|
14
|
+
abort 'No package.json in the current directory' unless File.file?('package.json')
|
|
15
|
+
|
|
16
|
+
package = JSON.parse(File.read('package.json'))
|
|
17
|
+
abort 'package.json must contain an object' unless package.is_a?(Hash)
|
|
18
|
+
package['scripts'] = {} unless package.key?('scripts')
|
|
19
|
+
abort 'package.json scripts must be an object' unless package['scripts'].is_a?(Hash)
|
|
20
|
+
abort "Script #{name.inspect} already exists" if package['scripts'].key?(name)
|
|
21
|
+
|
|
22
|
+
package['scripts'][name] = command
|
|
23
|
+
File.write('package.json', JSON.pretty_generate(package) + "\n")
|
|
24
|
+
puts "Added script #{name.inspect} to package.json"
|
|
25
|
+
rescue JSON::ParserError => error
|
|
26
|
+
abort "Invalid package.json: #{error.message}"
|
|
27
|
+
end
|
|
28
|
+
|
|
8
29
|
add_cmd :pkg do
|
|
9
30
|
file, *_other = Dir.glob('package.json')
|
|
10
31
|
|
data/bin/h-plist
ADDED
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
|
|
3
|
+
require 'hiiro'
|
|
4
|
+
require 'open3'
|
|
5
|
+
require 'json'
|
|
6
|
+
|
|
7
|
+
PLIST_TYPES = %w[bool integer float date string data xml json dictionary array].freeze
|
|
8
|
+
PLIST_FORMATS = %w[xml1 binary1 json swift objc].freeze
|
|
9
|
+
|
|
10
|
+
def require_plist(path)
|
|
11
|
+
unless path && !path.empty?
|
|
12
|
+
STDERR.puts 'A plist path is required.'
|
|
13
|
+
exit 1
|
|
14
|
+
end
|
|
15
|
+
expanded = File.expand_path(path)
|
|
16
|
+
unless File.file?(expanded)
|
|
17
|
+
STDERR.puts "Plist not found: #{expanded}"
|
|
18
|
+
exit 1
|
|
19
|
+
end
|
|
20
|
+
expanded
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def run_plutil(*arguments, allow_failure: false)
|
|
24
|
+
stdout, stderr, status = Open3.capture3('plutil', *arguments)
|
|
25
|
+
unless status.success? || allow_failure
|
|
26
|
+
STDERR.print(stderr.empty? ? stdout : stderr)
|
|
27
|
+
exit status.exitstatus
|
|
28
|
+
end
|
|
29
|
+
[stdout, stderr, status]
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def print_plutil(*arguments)
|
|
33
|
+
stdout, stderr, = run_plutil(*arguments)
|
|
34
|
+
STDOUT.print(stdout)
|
|
35
|
+
STDERR.print(stderr)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def validate_type(type)
|
|
39
|
+
return type if PLIST_TYPES.include?(type)
|
|
40
|
+
STDERR.puts "Unknown type #{type.inspect}. Use: #{PLIST_TYPES.join(', ')}"
|
|
41
|
+
exit 1
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def mutation_arguments(verb, key, type, values)
|
|
45
|
+
args = [verb, key, "-#{validate_type(type)}"]
|
|
46
|
+
unless %w[dictionary array].include?(type)
|
|
47
|
+
if values.empty?
|
|
48
|
+
STDERR.puts "A value is required for type #{type}."
|
|
49
|
+
exit 1
|
|
50
|
+
end
|
|
51
|
+
args << values.join(' ')
|
|
52
|
+
end
|
|
53
|
+
args
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
Hiiro.run(*ARGV) do
|
|
57
|
+
add_subcmd(:show, :print) do |path=nil|
|
|
58
|
+
print_plutil('-p', '--', require_plist(path))
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
add_subcmd(:get) do |path=nil, key=nil, format='raw'|
|
|
62
|
+
unless key
|
|
63
|
+
STDERR.puts 'Usage: h plist get <file> <keypath> [raw|json|xml1|binary1]'
|
|
64
|
+
exit 1
|
|
65
|
+
end
|
|
66
|
+
unless %w[raw json xml1 binary1].include?(format)
|
|
67
|
+
STDERR.puts 'Format must be raw, json, xml1, or binary1.'
|
|
68
|
+
exit 1
|
|
69
|
+
end
|
|
70
|
+
print_plutil('-extract', key, format, '-o', '-', '--', require_plist(path))
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
add_subcmd(:keys) do |path=nil, key=nil|
|
|
74
|
+
plist = require_plist(path)
|
|
75
|
+
stdout, = if key
|
|
76
|
+
run_plutil('-extract', key, 'json', '-expect', 'dictionary', '-o', '-', '--', plist)
|
|
77
|
+
else
|
|
78
|
+
run_plutil('-convert', 'json', '-o', '-', '--', plist)
|
|
79
|
+
end
|
|
80
|
+
value = JSON.parse(stdout)
|
|
81
|
+
unless value.is_a?(Hash)
|
|
82
|
+
STDERR.puts(key ? "Not a dictionary: #{key}" : 'The plist root is not a dictionary.')
|
|
83
|
+
exit 1
|
|
84
|
+
end
|
|
85
|
+
puts value.keys.sort
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
add_subcmd(:type) do |path=nil, key=nil|
|
|
89
|
+
unless key
|
|
90
|
+
STDERR.puts 'Usage: h plist type <file> <keypath>'
|
|
91
|
+
exit 1
|
|
92
|
+
end
|
|
93
|
+
print_plutil('-type', key, '--', require_plist(path))
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
add_subcmd(:lint) do |*paths|
|
|
97
|
+
if paths.empty?
|
|
98
|
+
STDERR.puts 'Usage: h plist lint <file...>'
|
|
99
|
+
exit 1
|
|
100
|
+
end
|
|
101
|
+
expanded = paths.map { |path| require_plist(path) }
|
|
102
|
+
print_plutil('-lint', '--', *expanded)
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
add_subcmd(:set) do |path=nil, key=nil, *arguments|
|
|
106
|
+
unless key
|
|
107
|
+
STDERR.puts 'Usage: h plist set <file> <keypath> [type] <value>'
|
|
108
|
+
exit 1
|
|
109
|
+
end
|
|
110
|
+
type = PLIST_TYPES.include?(arguments.first) ? arguments.shift : 'string'
|
|
111
|
+
values = arguments
|
|
112
|
+
plist = require_plist(path)
|
|
113
|
+
_, _, status = run_plutil('-type', key, '--', plist, allow_failure: true)
|
|
114
|
+
verb = status.success? ? '-replace' : '-insert'
|
|
115
|
+
print_plutil(*mutation_arguments(verb, key, type, values), '--', plist)
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
add_subcmd(:add, :insert) do |path=nil, key=nil, *arguments|
|
|
119
|
+
unless key
|
|
120
|
+
STDERR.puts 'Usage: h plist add <file> <keypath> [type] <value>'
|
|
121
|
+
exit 1
|
|
122
|
+
end
|
|
123
|
+
type = PLIST_TYPES.include?(arguments.first) ? arguments.shift : 'string'
|
|
124
|
+
values = arguments
|
|
125
|
+
print_plutil(*mutation_arguments('-insert', key, type, values), '--', require_plist(path))
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
add_subcmd(:rm, :remove, :delete) do |path=nil, key=nil|
|
|
129
|
+
unless key
|
|
130
|
+
STDERR.puts 'Usage: h plist rm <file> <keypath>'
|
|
131
|
+
exit 1
|
|
132
|
+
end
|
|
133
|
+
print_plutil('-remove', key, '--', require_plist(path))
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
add_subcmd(:convert) do |path=nil, format=nil, output=nil|
|
|
137
|
+
plist = require_plist(path)
|
|
138
|
+
unless PLIST_FORMATS.include?(format)
|
|
139
|
+
STDERR.puts "Usage: h plist convert <file> <#{PLIST_FORMATS.join('|')}> [output]"
|
|
140
|
+
exit 1
|
|
141
|
+
end
|
|
142
|
+
args = ['-convert', format]
|
|
143
|
+
args.concat(['-o', File.expand_path(output)]) if output
|
|
144
|
+
print_plutil(*args, '--', plist)
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
add_subcmd(:json) do |path=nil|
|
|
148
|
+
print_plutil('-convert', 'json', '-r', '-o', '-', '--', require_plist(path))
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
add_subcmd(:xml) do |path=nil|
|
|
152
|
+
print_plutil('-convert', 'xml1', '-o', '-', '--', require_plist(path))
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
add_subcmd(:create) do |path=nil, format='xml1'|
|
|
156
|
+
unless path
|
|
157
|
+
STDERR.puts 'Usage: h plist create <file> [xml1|binary1|json]'
|
|
158
|
+
exit 1
|
|
159
|
+
end
|
|
160
|
+
unless %w[xml1 binary1 json].include?(format)
|
|
161
|
+
STDERR.puts 'Create format must be xml1, binary1, or json.'
|
|
162
|
+
exit 1
|
|
163
|
+
end
|
|
164
|
+
expanded = File.expand_path(path)
|
|
165
|
+
if File.exist?(expanded)
|
|
166
|
+
STDERR.puts "Refusing to overwrite existing file: #{expanded}"
|
|
167
|
+
exit 1
|
|
168
|
+
end
|
|
169
|
+
print_plutil('-create', format, expanded)
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
add_subcmd(:edit) do |path=nil|
|
|
173
|
+
exec('safe_nvim', require_plist(path))
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
add_subcmd(:help) do
|
|
177
|
+
puts <<~HELP
|
|
178
|
+
h-plist — inspect and modify Apple property lists with plutil
|
|
179
|
+
|
|
180
|
+
READ:
|
|
181
|
+
h plist <file> Pretty-print a plist
|
|
182
|
+
h plist show <file> Pretty-print a plist
|
|
183
|
+
h plist get <file> <keypath> [format] Extract a value
|
|
184
|
+
h plist keys <file> [dict-keypath] List dictionary keys
|
|
185
|
+
h plist type <file> <keypath> Print a value's type
|
|
186
|
+
h plist lint <file...> Validate plist syntax
|
|
187
|
+
h plist json <file> Emit readable JSON
|
|
188
|
+
h plist xml <file> Emit XML
|
|
189
|
+
|
|
190
|
+
WRITE:
|
|
191
|
+
h plist set <file> <keypath> [type] <value> Insert or replace
|
|
192
|
+
h plist add <file> <keypath> [type] <value> Insert only
|
|
193
|
+
h plist rm <file> <keypath> Remove a value
|
|
194
|
+
h plist convert <file> <format> [output] Convert in place or copy
|
|
195
|
+
h plist create <file> [format] Create without overwrite
|
|
196
|
+
h plist edit <file> Open with safe_nvim
|
|
197
|
+
|
|
198
|
+
TYPES:
|
|
199
|
+
bool, integer, float, date, string (default), data, xml, json,
|
|
200
|
+
dictionary, array
|
|
201
|
+
|
|
202
|
+
Key paths use plutil syntax. Numeric components address array indexes.
|
|
203
|
+
Quote values containing spaces. Mutating commands edit the file in place.
|
|
204
|
+
HELP
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
add_default do |path=nil|
|
|
208
|
+
if path
|
|
209
|
+
print_plutil('-p', '--', require_plist(path))
|
|
210
|
+
else
|
|
211
|
+
run_subcmd(:help)
|
|
212
|
+
end
|
|
213
|
+
end
|
|
214
|
+
end
|