omarchy-ui 0.0.8-x86_64-linux → 0.0.10-x86_64-linux
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/README.md +70 -48
- data/Service.qml +23 -0
- data/lib/omarchy_ui/cli.rb +111 -15
- data/lib/omarchy_ui/generator.rb +39 -5
- data/lib/omarchy_ui/plugin_package.rb +147 -0
- data/lib/omarchy_ui/plugin_publisher.rb +263 -0
- data/lib/omarchy_ui/project_config.rb +2 -0
- data/lib/omarchy_ui/qml_compiler.rb +368 -0
- data/lib/omarchy_ui/runtime.rb +52 -17
- data/lib/omarchy_ui.rb +4 -1
- data/qml/DesktopStage.qml +88 -0
- data/qml/Positioned.qml +18 -0
- data/vendor/runtime/x86_64-linux/RUNTIME_PROVENANCE.md +1 -1
- metadata +6 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: ba33f1f0b7fead5be0f82726faeeb3815b94386f679732ee4945d840374a1023
|
|
4
|
+
data.tar.gz: bc7bfb798a46491d22085e3f81cbde27da3b9f14149b1ec63bd3e36b182f83c7
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: c76b00784fdf4a0371269d79d570e10ece613faf94449f2e40025a7a5a7a45b53080b259a7a68cedc7e21c89cc03e628cc3e3301c04db806145db19cc2b0d6ed
|
|
7
|
+
data.tar.gz: f4511e5523b4a033be1d80682305d99e0502721186cf8330d3c4d10e332bf0e85233d96f1b59840c54f7679e34abe4b8018b170357170b1bff6e1e38f4f697e6
|
data/README.md
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
</p>
|
|
11
11
|
|
|
12
12
|
<p align="center">
|
|
13
|
-
<img alt="Omarchy UI 0.0.
|
|
13
|
+
<img alt="Omarchy UI 0.0.10" src="https://img.shields.io/badge/Omarchy_UI-0.0.10-b7ff5a?style=flat-square&labelColor=111711">
|
|
14
14
|
<img alt="Ruby 3.1 or newer" src="https://img.shields.io/badge/Ruby-3.1%2B-cc342d?style=flat-square&logo=ruby&logoColor=white">
|
|
15
15
|
<img alt="Zui 0.0.10" src="https://img.shields.io/badge/Zui-0.0.10-7ee14b?style=flat-square&labelColor=111711">
|
|
16
16
|
<img alt="241 components" src="https://img.shields.io/badge/components-241-75d943?style=flat-square&labelColor=111711">
|
|
@@ -46,8 +46,8 @@ and the Omarchy adapter.
|
|
|
46
46
|
</table>
|
|
47
47
|
|
|
48
48
|
> [!IMPORTANT]
|
|
49
|
-
> Omarchy UI currently targets **Omarchy on x86-64 Linux
|
|
50
|
-
>
|
|
49
|
+
> Omarchy UI currently targets **Omarchy on x86-64 Linux**. Reusable Zui application modules can
|
|
50
|
+
> also run through Zui's native host on Linux, macOS, and Windows.
|
|
51
51
|
|
|
52
52
|
## Choose a workflow
|
|
53
53
|
|
|
@@ -59,15 +59,16 @@ and the Omarchy adapter.
|
|
|
59
59
|
|
|
60
60
|
## Requirements
|
|
61
61
|
|
|
62
|
-
- Omarchy on x86-64 Linux
|
|
63
|
-
- Ruby 3.1 or newer
|
|
64
|
-
-
|
|
62
|
+
- Omarchy on x86-64 Linux
|
|
63
|
+
- Ruby 3.1 or newer for installation and development
|
|
64
|
+
- Qt 6 development tools, CMake, Ninja, and a C++ compiler for `bundle`, `validate`, and `push`
|
|
65
|
+
- Optional Qt modules for components that use features such as Quick 3D or Multimedia
|
|
65
66
|
|
|
66
|
-
Omarchy UI
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
67
|
+
Omarchy UI turns Ruby and assets into an Omarchy-compatible application or plugin. It owns the
|
|
68
|
+
metadata, entry points, adapter, validation, tree-shaken and AOT-compiled Zui QML, and embedded mruby
|
|
69
|
+
runtime. Omarchy UI invokes the build tools; projects do not contain CMake files or distribution
|
|
70
|
+
scripts. The finished package does not require Ruby or framework gems. Components report a clear
|
|
71
|
+
error when a required Qt module or resource is unavailable.
|
|
71
72
|
|
|
72
73
|
## Quick start
|
|
73
74
|
|
|
@@ -79,7 +80,7 @@ gem install omarchy-ui
|
|
|
79
80
|
|
|
80
81
|
The gem installs the compatible Zui version as a dependency.
|
|
81
82
|
|
|
82
|
-
### 2. Generate a
|
|
83
|
+
### 2. Generate a project
|
|
83
84
|
|
|
84
85
|
```bash
|
|
85
86
|
omarchy_ui new Counter
|
|
@@ -93,13 +94,12 @@ omarchy_ui new "System Status" --plugin
|
|
|
93
94
|
cd system-status
|
|
94
95
|
```
|
|
95
96
|
|
|
96
|
-
Both commands create a ready-to-run Ruby project.
|
|
97
|
-
|
|
98
|
-
|
|
97
|
+
Both commands create a ready-to-run Ruby project. Developers write the interface and behavior;
|
|
98
|
+
Omarchy UI generates the Omarchy package without application-owned QML, shell entry points, or
|
|
99
|
+
handwritten manifests.
|
|
99
100
|
|
|
100
|
-
Each project includes a Ruby-native `config.rb`
|
|
101
|
-
|
|
102
|
-
single configuration when assembling the complete package.
|
|
101
|
+
Each project includes a Ruby-native `config.rb` with its type, identity, version, entry point, and
|
|
102
|
+
plugin metadata. `bundle`, `validate`, and `push` use this single configuration.
|
|
103
103
|
|
|
104
104
|
The generator creates a small, host-independent project:
|
|
105
105
|
|
|
@@ -120,8 +120,8 @@ counter/
|
|
|
120
120
|
omarchy_ui run main.rb
|
|
121
121
|
```
|
|
122
122
|
|
|
123
|
-
`run` bundles the project's Ruby entry point, asks Zui to tree-shake the QML runtime, prepares the
|
|
124
|
-
|
|
123
|
+
`run` bundles the project's Ruby entry point, asks Zui to tree-shake the QML runtime, prepares the
|
|
124
|
+
Omarchy host, and launches it through Quickshell.
|
|
125
125
|
|
|
126
126
|
## Application model
|
|
127
127
|
|
|
@@ -246,16 +246,15 @@ QML is not required.
|
|
|
246
246
|
|
|
247
247
|
## Omarchy plugins
|
|
248
248
|
|
|
249
|
-
Generate a
|
|
249
|
+
Generate a plugin project with one command:
|
|
250
250
|
|
|
251
251
|
```bash
|
|
252
252
|
omarchy_ui new "System Status" --plugin
|
|
253
253
|
cd system-status
|
|
254
254
|
```
|
|
255
255
|
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
tree-shaken Zui package, validation, and install lifecycle.
|
|
256
|
+
Developers work in Ruby and add their own assets. Omarchy UI supplies the plugin metadata, shell
|
|
257
|
+
surfaces, native host, tree-shaken Zui package, validation, and installation lifecycle.
|
|
259
258
|
|
|
260
259
|
The Ruby entry point uses ordinary Zui components:
|
|
261
260
|
|
|
@@ -282,8 +281,8 @@ OmarchyUI.plugin do
|
|
|
282
281
|
end
|
|
283
282
|
```
|
|
284
283
|
|
|
285
|
-
`bar_widget` and `panel :status` are the
|
|
286
|
-
|
|
284
|
+
`bar_widget` and `panel :status` are the developer-facing surface declarations. Omarchy UI maps them
|
|
285
|
+
to the required shell entry points when it builds or stages the plugin.
|
|
287
286
|
|
|
288
287
|
### Validate and install
|
|
289
288
|
|
|
@@ -292,8 +291,21 @@ omarchy_ui validate
|
|
|
292
291
|
omarchy_ui push
|
|
293
292
|
```
|
|
294
293
|
|
|
295
|
-
`validate` generates and checks the
|
|
296
|
-
|
|
294
|
+
`validate` generates and checks the plugin without modifying the Ruby project. `push` builds,
|
|
295
|
+
validates, installs, enables, and reloads it for development.
|
|
296
|
+
|
|
297
|
+
To publish, target a separate public distribution repository. Omarchy UI rebuilds the thin package,
|
|
298
|
+
enforces the marketplace contract, pushes it, and prints the complete submission for review:
|
|
299
|
+
|
|
300
|
+
```bash
|
|
301
|
+
omarchy_ui publish --repo YOUR_GITHUB_NAME/PLUGIN_REPOSITORY \
|
|
302
|
+
--category System --tags system,quickshell --create
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
After reviewing the printed title, metadata, and five marketplace attestations, rerun the same
|
|
306
|
+
command with `--submit`. It creates a submission or refreshes an existing open one. This two-step
|
|
307
|
+
flow prevents accidental replacement of the source repository and ensures the ownership statement
|
|
308
|
+
is reviewed before it is posted.
|
|
297
309
|
|
|
298
310
|
During development, suppress either lifecycle action when needed:
|
|
299
311
|
|
|
@@ -302,10 +314,6 @@ omarchy_ui push --no-enable
|
|
|
302
314
|
omarchy_ui push --no-restart
|
|
303
315
|
```
|
|
304
316
|
|
|
305
|
-
> [!WARNING]
|
|
306
|
-
> Omarchy plugins execute as unsandboxed user code inside the shell environment. Review the Ruby,
|
|
307
|
-
> assets, generated package, and provenance before installing a third-party plugin.
|
|
308
|
-
|
|
309
317
|
## Command-line reference
|
|
310
318
|
|
|
311
319
|
```text
|
|
@@ -314,11 +322,12 @@ omarchy_ui <command> [arguments]
|
|
|
314
322
|
|
|
315
323
|
| Command | Arguments | Result |
|
|
316
324
|
| --- | --- | --- |
|
|
317
|
-
| `omarchy_ui new NAME` | One project name | Creates
|
|
318
|
-
| `omarchy_ui new NAME --plugin` | One project name
|
|
325
|
+
| `omarchy_ui new NAME` | One project name | Creates an Omarchy application project |
|
|
326
|
+
| `omarchy_ui new NAME --plugin --github USER` | One project name, `--plugin`, and optional GitHub user | Creates a marketplace-ready Omarchy plugin project |
|
|
319
327
|
| `omarchy_ui run FILE` | One Ruby entry point | Runs an application through the Omarchy/Quickshell host |
|
|
320
|
-
| `omarchy_ui bundle [DIRECTORY]` | Zero or one project directory | Generates the
|
|
321
|
-
| `omarchy_ui
|
|
328
|
+
| `omarchy_ui bundle [DIRECTORY]` | Zero or one project directory | Generates the distributable package and prints its location |
|
|
329
|
+
| `omarchy_ui publish [DIRECTORY]` | Required `--repo`, `--category`, `--tags`; optional `--create`, `--submit` | Builds and pushes a thin distribution repository, then previews or submits its marketplace issue |
|
|
330
|
+
| `omarchy_ui validate [DIRECTORY]` | Zero or one plugin directory | Stages the plugin and delegates validation to `omarchy plugin validate` |
|
|
322
331
|
| `omarchy_ui push [DIRECTORY]` | Optional `--no-enable` and `--no-restart` | Atomically installs and activates a validated plugin |
|
|
323
332
|
| `omarchy_ui version` | None | Prints the installed Omarchy UI version |
|
|
324
333
|
|
|
@@ -327,19 +336,29 @@ not forward arbitrary Ruby arguments.
|
|
|
327
336
|
|
|
328
337
|
## Packaging
|
|
329
338
|
|
|
330
|
-
Create the
|
|
339
|
+
Create the distributable package from the project root:
|
|
331
340
|
|
|
332
341
|
```bash
|
|
333
342
|
omarchy_ui bundle
|
|
334
343
|
```
|
|
335
344
|
|
|
336
|
-
Omarchy UI
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
Zui 0.0.10 so
|
|
341
|
-
|
|
342
|
-
|
|
345
|
+
Omarchy UI assembles one bundled Ruby program and required assets, native runtime, manifest, and only
|
|
346
|
+
the Zui components used by the project. It AOT-compiles the generated QML into a content-addressed Qt
|
|
347
|
+
module, then discards the generated component, control, theme, and font source tree. Applications
|
|
348
|
+
receive a direct launcher; plugins must pass Omarchy validation before the command succeeds. Omarchy
|
|
349
|
+
UI pins Zui 0.0.10 so the compiled UI matches the Zui core embedded in the deterministic mruby
|
|
350
|
+
runtime.
|
|
351
|
+
|
|
352
|
+
Current Omarchy entry points resolve by filename, so a package retains only the required generated
|
|
353
|
+
loader shims. Applications keep `App.qml`; standard plugins keep `Service.qml`, `Panel.qml`, and
|
|
354
|
+
`BarWidget.qml`. Each shim contains only an import and a compiled type instance. The application
|
|
355
|
+
interface is authored in Ruby and stored in native `.so` artifacts. Distributable packages do not
|
|
356
|
+
include generated QML source, build reports, audit/provenance folders, checksums, tests, or CI files.
|
|
357
|
+
They also omit `config.rb` and Ruby files already folded into `main.rb`.
|
|
358
|
+
Compiled packages should be built against the Qt version shipped by their target Omarchy release.
|
|
359
|
+
|
|
360
|
+
The source `config.rb` is the build configuration. Omarchy UI generates plugin manifests from it;
|
|
361
|
+
developers never maintain a separate manifest.
|
|
343
362
|
|
|
344
363
|
## Component catalog
|
|
345
364
|
|
|
@@ -406,10 +425,12 @@ Zui DSL · state · events · bindings · scheduler
|
|
|
406
425
|
│
|
|
407
426
|
│ versioned JSON render, patch, event, and effect protocol
|
|
408
427
|
▼
|
|
409
|
-
Omarchy
|
|
428
|
+
Omarchy process bridge ───────────────── embedded mruby runtime
|
|
410
429
|
│
|
|
411
430
|
▼
|
|
412
|
-
Zui
|
|
431
|
+
Tree-shaken Zui host + component catalog
|
|
432
|
+
│
|
|
433
|
+
│ bundle: Qt AOT module + required loader shims
|
|
413
434
|
│
|
|
414
435
|
▼
|
|
415
436
|
App window · Omarchy panel · Omarchy bar widget
|
|
@@ -427,8 +448,9 @@ The dependency direction is deliberate:
|
|
|
427
448
|
- **Applications own** Ruby source, assets, state, behavior, and reusable UI modules.
|
|
428
449
|
|
|
429
450
|
At bundle, validation, and push time, Omarchy UI asks Zui to analyze the bundled Ruby syntax and
|
|
430
|
-
generate only the required component adapters plus their renderer dependencies.
|
|
431
|
-
host
|
|
451
|
+
generate only the required component adapters plus their renderer dependencies. Omarchy UI overlays
|
|
452
|
+
its host, compiles the complete generated QML graph into a content-addressed Qt module, and emits the
|
|
453
|
+
minimal loader files required by Omarchy. Read the full [QML ownership and adapter
|
|
432
454
|
boundary](docs/qml-support.md).
|
|
433
455
|
|
|
434
456
|
## Runtime integrity
|
data/Service.qml
CHANGED
|
@@ -499,4 +499,27 @@ Item {
|
|
|
499
499
|
repeat: false
|
|
500
500
|
onTriggered: root.startRuby()
|
|
501
501
|
}
|
|
502
|
+
|
|
503
|
+
// A desktop surface is rendered by the same long-lived service that owns
|
|
504
|
+
// the Ruby runtime. Its DesktopStage adapter creates the layer-shell window;
|
|
505
|
+
// plugins keep all scene structure, state, and interaction in Ruby.
|
|
506
|
+
ControlNode {
|
|
507
|
+
id: desktopRenderer
|
|
508
|
+
visible: root.ready && root.rootId("desktop") !== ""
|
|
509
|
+
bridge: root
|
|
510
|
+
surfaceName: "desktop"
|
|
511
|
+
controlId: root.rootId(surfaceName)
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
IpcHandler {
|
|
515
|
+
target: root.manifest && root.manifest.id ? String(root.manifest.id) : "omarchy-ui"
|
|
516
|
+
|
|
517
|
+
function playPause(): string {
|
|
518
|
+
var desktopId = root.rootId("desktop")
|
|
519
|
+
if (desktopId === "") return "not-ready"
|
|
520
|
+
return root.sendEvent("desktop", desktopId, "shortcut", { name: "play_pause" })
|
|
521
|
+
? "ok"
|
|
522
|
+
: "not-ready"
|
|
523
|
+
}
|
|
524
|
+
}
|
|
502
525
|
}
|
data/lib/omarchy_ui/cli.rb
CHANGED
|
@@ -23,11 +23,12 @@ module OmarchyUI
|
|
|
23
23
|
when "run" then run_file(arguments)
|
|
24
24
|
when "new" then new_project(arguments)
|
|
25
25
|
when "bundle" then bundle_project(arguments)
|
|
26
|
+
when "publish" then publish(arguments)
|
|
26
27
|
when "push" then push(arguments)
|
|
27
28
|
when "validate" then validate(arguments)
|
|
28
29
|
when "version", "--version", "-v" then @out.puts(OmarchyUI::VERSION); 0
|
|
29
30
|
else
|
|
30
|
-
@err.puts("Usage: omarchy_ui <new NAME [--plugin]|run FILE|bundle [DIRECTORY]|push [DIRECTORY]|validate [DIRECTORY]|version>")
|
|
31
|
+
@err.puts("Usage: omarchy_ui <new NAME [--plugin] [--github USER]|run FILE|bundle [DIRECTORY]|publish [DIRECTORY] --repo OWNER/REPO --category CATEGORY --tags TAGS [--create] [--submit]|push [DIRECTORY]|validate [DIRECTORY]|version>")
|
|
31
32
|
command.nil? ? 0 : 64
|
|
32
33
|
end
|
|
33
34
|
rescue Interrupt
|
|
@@ -68,11 +69,14 @@ module OmarchyUI
|
|
|
68
69
|
|
|
69
70
|
def new_project(arguments)
|
|
70
71
|
plugin = !arguments.delete("--plugin").nil?
|
|
72
|
+
github_user = extract_option!(arguments, "--github")
|
|
71
73
|
name = arguments.shift || raise(ArgumentError, "new requires a project name")
|
|
72
|
-
raise ArgumentError, "new accepts a name and
|
|
74
|
+
raise ArgumentError, "new accepts a name, --plugin, and --github USER" unless arguments.empty?
|
|
75
|
+
raise ArgumentError, "--github is only valid with --plugin" if github_user && !plugin
|
|
73
76
|
destination = File.expand_path(slug(name))
|
|
74
77
|
kind = plugin ? :plugin : :application
|
|
75
|
-
|
|
78
|
+
github_user ||= default_github_user if plugin
|
|
79
|
+
Generator.new(path: destination, name: name, kind:, author: default_author, github_user:).create
|
|
76
80
|
label = plugin ? "Omarchy-compliant plugin" : "self-contained Omarchy application"
|
|
77
81
|
@out.puts("Created #{label} in #{destination}")
|
|
78
82
|
0
|
|
@@ -91,6 +95,30 @@ module OmarchyUI
|
|
|
91
95
|
"Omarchy UI Developer"
|
|
92
96
|
end
|
|
93
97
|
|
|
98
|
+
def default_github_user
|
|
99
|
+
configured = ENV["OMARCHY_UI_GITHUB_USER"].to_s.strip
|
|
100
|
+
return configured unless configured.empty?
|
|
101
|
+
|
|
102
|
+
output, _error, status = Open3.capture3("gh", "api", "user", "--jq", ".login")
|
|
103
|
+
login = output.to_s.strip
|
|
104
|
+
return login if status.success? && !login.empty?
|
|
105
|
+
|
|
106
|
+
raise ArgumentError,
|
|
107
|
+
"plugin generation needs --github USER or OMARCHY_UI_GITHUB_USER (gh auth login can provide it automatically)"
|
|
108
|
+
rescue Errno::ENOENT
|
|
109
|
+
raise ArgumentError, "plugin generation needs --github USER or OMARCHY_UI_GITHUB_USER"
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
def extract_option!(arguments, name)
|
|
113
|
+
index = arguments.index(name)
|
|
114
|
+
return nil unless index
|
|
115
|
+
|
|
116
|
+
value = arguments[index + 1]
|
|
117
|
+
raise ArgumentError, "#{name} requires a value" if value.nil? || value.start_with?("--")
|
|
118
|
+
arguments.slice!(index, 2)
|
|
119
|
+
value
|
|
120
|
+
end
|
|
121
|
+
|
|
94
122
|
def slug(value)
|
|
95
123
|
result = value.to_s.downcase.gsub(/[^a-z0-9]+/, "-").gsub(/\A-|\-\z/, "")
|
|
96
124
|
raise ArgumentError, "name must contain letters or numbers" if result.empty?
|
|
@@ -114,16 +142,21 @@ module OmarchyUI
|
|
|
114
142
|
config = ProjectConfig.load(source)
|
|
115
143
|
entrypoint = config&.entrypoint || "main.rb"
|
|
116
144
|
raise ArgumentError, "#{entrypoint} not found: #{source}" unless File.file?(File.join(source, entrypoint))
|
|
145
|
+
precompiled = config.nil? && compiled_package?(source)
|
|
117
146
|
destination = File.join(source, "dist", config&.slug || File.basename(source))
|
|
118
147
|
raise ArgumentError, "bundle destination already exists: #{destination}" if File.exist?(destination)
|
|
119
148
|
FileUtils.mkdir_p(destination)
|
|
120
|
-
entries = application_entries(source, config:)
|
|
149
|
+
entries = precompiled ? package_entries(source) : application_entries(source, config:)
|
|
121
150
|
FileUtils.cp_r(entries.map { |entry| File.join(source, entry) }, destination)
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
151
|
+
unless precompiled
|
|
152
|
+
config.write_manifest(destination) if config&.plugin?
|
|
153
|
+
bundle_ruby_entrypoint(source, destination, entrypoint:)
|
|
154
|
+
Runtime.install_package(destination, compiled: true)
|
|
155
|
+
end
|
|
156
|
+
prune_bundled_ruby_sources(destination, entrypoint:)
|
|
125
157
|
plugin = config ? config.plugin? : File.file?(File.join(destination, "manifest.json"))
|
|
126
158
|
if plugin
|
|
159
|
+
PluginPackage.validate!(destination)
|
|
127
160
|
raise ArgumentError, "bundled plugin validation failed" unless system("omarchy", "plugin", "validate", destination)
|
|
128
161
|
@out.puts("Bundled plugin in #{destination}")
|
|
129
162
|
return 0
|
|
@@ -140,6 +173,8 @@ module OmarchyUI
|
|
|
140
173
|
export OMARCHY_UI_RUNTIME="$app_dir/omarchy-ui-runtime"
|
|
141
174
|
export OMARCHY_UI_PROJECT_DIR="$app_dir"
|
|
142
175
|
export OMARCHY_UI_RUBY_PROGRAM="$app_dir/#{entrypoint}"
|
|
176
|
+
export QML2_IMPORT_PATH="$app_dir${QML2_IMPORT_PATH:+:$QML2_IMPORT_PATH}"
|
|
177
|
+
export QML_IMPORT_PATH="$app_dir${QML_IMPORT_PATH:+:$QML_IMPORT_PATH}"
|
|
143
178
|
export QT_LOGGING_RULES="${QT_LOGGING_RULES:+$QT_LOGGING_RULES;}qt.qpa.services.warning=false"
|
|
144
179
|
exec quickshell --path "$app_dir/App.qml"
|
|
145
180
|
SH
|
|
@@ -156,9 +191,54 @@ module OmarchyUI
|
|
|
156
191
|
end
|
|
157
192
|
|
|
158
193
|
def application_entries(source, config: ProjectConfig.load(source))
|
|
159
|
-
generated = Runtime::GENERATED_ENTRIES +
|
|
194
|
+
generated = Runtime::GENERATED_ENTRIES + %w[run Commons Ui]
|
|
160
195
|
generated.concat([ProjectConfig::FILE_NAME, "manifest.json"]) if config
|
|
161
|
-
Dir.children(source).reject
|
|
196
|
+
Dir.children(source).reject do |entry|
|
|
197
|
+
(PluginPackage::DEVELOPMENT_ENTRIES + PluginPackage::SOURCE_CONTROL_ENTRIES).include?(entry) ||
|
|
198
|
+
generated.include?(entry)
|
|
199
|
+
end
|
|
200
|
+
end
|
|
201
|
+
|
|
202
|
+
def package_entries(source)
|
|
203
|
+
excluded = PluginPackage::DEVELOPMENT_ENTRIES + PluginPackage::SOURCE_CONTROL_ENTRIES +
|
|
204
|
+
Runtime::LEGACY_METADATA_FILES
|
|
205
|
+
Dir.children(source).reject { |entry| excluded.include?(entry) }
|
|
206
|
+
end
|
|
207
|
+
|
|
208
|
+
def compiled_package?(source)
|
|
209
|
+
compiled_root = File.join(source, QmlCompiler::COMPILED_ROOT, "Bundles")
|
|
210
|
+
shims = QmlCompiler::ENTRY_TYPES.keys.any? { |entry| File.file?(File.join(source, entry)) }
|
|
211
|
+
return false unless File.directory?(compiled_root) && shims
|
|
212
|
+
|
|
213
|
+
QmlCompiler.verify!(source)
|
|
214
|
+
true
|
|
215
|
+
end
|
|
216
|
+
|
|
217
|
+
def publish(arguments)
|
|
218
|
+
repository = extract_option!(arguments, "--repo")
|
|
219
|
+
category = extract_option!(arguments, "--category")
|
|
220
|
+
tags = extract_option!(arguments, "--tags").to_s.split(",")
|
|
221
|
+
create = !arguments.delete("--create").nil?
|
|
222
|
+
submit = !arguments.delete("--submit").nil?
|
|
223
|
+
source = File.expand_path(arguments.shift || Dir.pwd)
|
|
224
|
+
raise ArgumentError, "publish accepts one directory and publish options" unless arguments.empty?
|
|
225
|
+
config = ProjectConfig.load(source)
|
|
226
|
+
raise ArgumentError, "publish requires an Omarchy UI plugin project" unless config&.plugin?
|
|
227
|
+
|
|
228
|
+
with_staged_project(source) do |staging|
|
|
229
|
+
raise ArgumentError, "staged plugin validation failed" unless system("omarchy", "plugin", "validate", staging)
|
|
230
|
+
PluginPublisher.publish!(
|
|
231
|
+
package: staging,
|
|
232
|
+
source:,
|
|
233
|
+
repository:,
|
|
234
|
+
category:,
|
|
235
|
+
tags:,
|
|
236
|
+
create:,
|
|
237
|
+
submit:,
|
|
238
|
+
out: @out
|
|
239
|
+
)
|
|
240
|
+
end
|
|
241
|
+
0
|
|
162
242
|
end
|
|
163
243
|
|
|
164
244
|
def push(arguments)
|
|
@@ -213,15 +293,20 @@ module OmarchyUI
|
|
|
213
293
|
def stage_project(source, parent: nil, prefix: ".omarchy-ui-staging-")
|
|
214
294
|
raise ArgumentError, "project directory not found: #{source}" unless File.directory?(source)
|
|
215
295
|
config = ProjectConfig.load(source)
|
|
296
|
+
precompiled = config.nil? && compiled_package?(source)
|
|
216
297
|
staging = parent ? Dir.mktmpdir(prefix, parent) : Dir.mktmpdir(prefix)
|
|
217
|
-
entries = application_entries(source, config:)
|
|
298
|
+
entries = precompiled ? package_entries(source) : application_entries(source, config:)
|
|
218
299
|
FileUtils.cp_r(entries.map { |entry| File.join(source, entry) }, staging) unless entries.empty?
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
300
|
+
unless precompiled
|
|
301
|
+
config.write_manifest(staging) if config&.plugin?
|
|
302
|
+
entrypoint = config&.entrypoint || "main.rb"
|
|
303
|
+
if File.file?(File.join(staging, entrypoint))
|
|
304
|
+
bundle_ruby_entrypoint(source, staging, entrypoint:)
|
|
305
|
+
Runtime.install_package(staging, compiled: true)
|
|
306
|
+
end
|
|
224
307
|
end
|
|
308
|
+
prune_bundled_ruby_sources(staging, entrypoint: "main.rb") if File.file?(File.join(staging, "manifest.json"))
|
|
309
|
+
PluginPackage.validate!(staging) if File.file?(File.join(staging, "manifest.json"))
|
|
225
310
|
staging
|
|
226
311
|
rescue StandardError
|
|
227
312
|
FileUtils.remove_entry(staging) if staging && File.exist?(staging)
|
|
@@ -235,6 +320,17 @@ module OmarchyUI
|
|
|
235
320
|
File.write(destination_entrypoint, SourceBundle.new(source_entrypoint, root: source).call)
|
|
236
321
|
end
|
|
237
322
|
|
|
323
|
+
def prune_bundled_ruby_sources(destination, entrypoint: "main.rb")
|
|
324
|
+
kept = File.expand_path(entrypoint, destination)
|
|
325
|
+
Dir.glob(File.join(destination, "**", "*.rb"), File::FNM_DOTMATCH).each do |path|
|
|
326
|
+
FileUtils.rm_f(path) unless File.expand_path(path) == kept
|
|
327
|
+
end
|
|
328
|
+
directories = Dir.glob(File.join(destination, "**", "*"), File::FNM_DOTMATCH)
|
|
329
|
+
.select { |path| File.directory?(path) && !File.symlink?(path) }
|
|
330
|
+
.sort_by { |path| -path.count(File::SEPARATOR) }
|
|
331
|
+
directories.each { |path| Dir.rmdir(path) if Dir.empty?(path) }
|
|
332
|
+
end
|
|
333
|
+
|
|
238
334
|
def activate_plugin(plugin_id)
|
|
239
335
|
return if system("omarchy", "plugin", "enable", plugin_id)
|
|
240
336
|
system("omarchy-shell", "shell", "rescanPlugins")
|
data/lib/omarchy_ui/generator.rb
CHANGED
|
@@ -5,12 +5,17 @@ require "fileutils"
|
|
|
5
5
|
module OmarchyUI
|
|
6
6
|
class Generator
|
|
7
7
|
PROJECT_KINDS = %i[application plugin].freeze
|
|
8
|
+
GITHUB_USER = /\A(?!-)[A-Za-z0-9-]{1,39}(?<!-)\z/
|
|
8
9
|
|
|
9
|
-
def initialize(path:, name: nil, kind: :application, plugin_id: nil, author: nil)
|
|
10
|
+
def initialize(path:, name: nil, kind: :application, plugin_id: nil, author: nil, github_user: nil)
|
|
10
11
|
@path = File.expand_path(path)
|
|
11
12
|
@name = name || File.basename(@path).split(/[-_]/).map(&:capitalize).join(" ")
|
|
12
13
|
@kind = kind.to_sym
|
|
13
|
-
@
|
|
14
|
+
@github_user = github_user.to_s.strip
|
|
15
|
+
if plugin? && !GITHUB_USER.match?(@github_user)
|
|
16
|
+
raise ArgumentError, "plugin generation needs a valid GitHub username"
|
|
17
|
+
end
|
|
18
|
+
@plugin_id = plugin_id || "io.github.#{@github_user.downcase}.#{project_slug}"
|
|
14
19
|
@author = author.to_s.strip.empty? ? "Omarchy UI Developer" : author.to_s.strip
|
|
15
20
|
raise ArgumentError, "unsupported project kind: #{@kind}" unless PROJECT_KINDS.include?(@kind)
|
|
16
21
|
end
|
|
@@ -124,6 +129,9 @@ module OmarchyUI
|
|
|
124
129
|
|
|
125
130
|
A pure Ruby desktop application built with Zui and the Omarchy UI host.
|
|
126
131
|
|
|
132
|
+
The interface and behavior are authored entirely in Ruby. Omarchy UI generates QML only
|
|
133
|
+
as a temporary build input, compiles it, and ships no handwritten QML source.
|
|
134
|
+
|
|
127
135
|
## Run
|
|
128
136
|
|
|
129
137
|
```bash
|
|
@@ -139,7 +147,10 @@ module OmarchyUI
|
|
|
139
147
|
omarchy_ui bundle
|
|
140
148
|
```
|
|
141
149
|
|
|
142
|
-
Omarchy UI generates the complete self-contained
|
|
150
|
+
Omarchy UI tree-shakes and compiles the UI, then generates the complete self-contained
|
|
151
|
+
application package required by Omarchy. The package contains the bundled Ruby program,
|
|
152
|
+
native runtime, compiled Qt module, and one generated `App.qml` loader shim—no build reports
|
|
153
|
+
or generated QML source tree.
|
|
143
154
|
MARKDOWN
|
|
144
155
|
end
|
|
145
156
|
|
|
@@ -149,6 +160,26 @@ module OmarchyUI
|
|
|
149
160
|
|
|
150
161
|
A pure Ruby Omarchy plugin built with Omarchy UI and Zui.
|
|
151
162
|
|
|
163
|
+
The interface and behavior are authored entirely in Ruby. Omarchy UI generates QML only
|
|
164
|
+
as a temporary build input, compiles it, and ships no handwritten QML source.
|
|
165
|
+
|
|
166
|
+
## Install
|
|
167
|
+
|
|
168
|
+
```bash
|
|
169
|
+
omarchy plugin add https://github.com/#{@github_user}/#{project_slug}.git --enable
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
## Remove
|
|
173
|
+
|
|
174
|
+
```bash
|
|
175
|
+
omarchy plugin remove #{@plugin_id}
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
## Dependencies
|
|
179
|
+
|
|
180
|
+
- Omarchy Quattro on x86-64 Linux
|
|
181
|
+
- No additional runtime dependency in the generated starter
|
|
182
|
+
|
|
152
183
|
## Validate
|
|
153
184
|
|
|
154
185
|
```bash
|
|
@@ -168,8 +199,11 @@ module OmarchyUI
|
|
|
168
199
|
```
|
|
169
200
|
|
|
170
201
|
Write the plugin interface and behavior in Ruby under `main.rb` and `components/`.
|
|
171
|
-
Public plugin identity and release metadata live in `config.rb`. Omarchy UI
|
|
172
|
-
|
|
202
|
+
Public plugin identity and release metadata live in `config.rb`. Omarchy UI tree-shakes and
|
|
203
|
+
compiles the UI, then generates and validates the complete Omarchy-compatible plugin package.
|
|
204
|
+
The package contains the bundled Ruby program, native runtime, compiled Qt module, manifest,
|
|
205
|
+
and only the generated loader shims named by that manifest—no build reports, audit folder,
|
|
206
|
+
tests, or generated QML source tree.
|
|
173
207
|
MARKDOWN
|
|
174
208
|
end
|
|
175
209
|
|