From f2bbfe83b4b23e87d8a049a2d698c6576a5bcd8c Mon Sep 17 00:00:00 2001 From: dec05eba Date: Mon, 30 Oct 2023 10:23:49 +0100 Subject: Initial commit --- LICENSE | 19 +++++++++++++++++ README.md | 32 ++++++++++++++++++++++++++++ python/qm-file-manager.py | 31 +++++++++++++++++++++++++++ shell/qm-file-manager.sh | 32 ++++++++++++++++++++++++++++ zig/qm-file-manager.zig | 54 +++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 168 insertions(+) create mode 100644 LICENSE create mode 100644 README.md create mode 100755 python/qm-file-manager.py create mode 100755 shell/qm-file-manager.sh create mode 100644 zig/qm-file-manager.zig diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..00bd50b --- /dev/null +++ b/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2023 dec05eba + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..5120e91 --- /dev/null +++ b/README.md @@ -0,0 +1,32 @@ +qm plugin protocol with example. A "file manager" plugin example is written in shell script, python and zig + +# Protocol +## Input +Plugins get inputs as environment variables.\ +The environment variable `ACTION` is set to `get` to get data.\ +The environment variable `URL` is set to _url_ relevant to the page, so for example for a file manager `URL` is set to the directory to display files of. +## Output +Plugins output data by writing lines to stdout.\ +Data is first written to stdout and then a _command_ is written to stdout.\ +First `add_tab` command is expected, followed by multiple `add_body_item`. The body items are put in the tab that is output before the body items. +### add_tab +The add_tab command expects `title` data, for example: +```bash +echo "title Files" +echo "add_tab" +``` +### add_body_item +The add_body_item command expects `title` and `url` data and optionally `thumbnail_url` and `thumbnail_size`, for example: +```bash +echo "title file.png" +echo "url img1.png" +echo "thumbnail_url img1.png" +echo "thumbnail_size 1920x1080" +echo "add_body_item" + +echo "title img2.png" +echo "url img2.png" +echo "thumbnail_url img2.png" +echo "thumbnail_size 1280x720" +echo "add_body_item" +``` diff --git a/python/qm-file-manager.py b/python/qm-file-manager.py new file mode 100755 index 0000000..c022d3e --- /dev/null +++ b/python/qm-file-manager.py @@ -0,0 +1,31 @@ +#!/usr/bin/env python3 + +import os + +def get(url): + print("title %s" % url) + print("add_tab") + + if url != "/": + print("title Go to parent directory") + print("url ..") + print("thumbnail_url folder.png") + print("thumbnail_size 32x32") + print("add_body_item") + + for entry in os.scandir(url): + print("title %s" % entry.path) + print("url %s" % entry.path) + if entry.is_dir(): + print("thumbnail_url folder.png") + else: + print("thumbnail_url file.png") + print("thumbnail_size 32x32") + print("add_body_item") + +action = os.environ["ACTION"] +if action == "get": + get(os.environ["URL"]) +else: + print("error unexpected action %s" % action) + exit(1) \ No newline at end of file diff --git a/shell/qm-file-manager.sh b/shell/qm-file-manager.sh new file mode 100755 index 0000000..c5e6474 --- /dev/null +++ b/shell/qm-file-manager.sh @@ -0,0 +1,32 @@ +#!/bin/sh + +get() { + echo "title $1" + echo "add_tab" + + if [ "$1" != "/" ]; then + echo "title Go to parent directory" + echo "url .." + echo "thumbnail_url folder.png" + echo "thumbnail_size 32x32" + echo "add_body_item" + fi + + for f in "$1/"*; do + echo "title $f" + echo "url $f" + if [ -d "$f" ]; then + echo "thumbnail_url folder.png" + else + echo "thumbnail_url file.png" + fi + echo "thumbnail_size 32x32" + echo "add_body_item" + done +} + +case "$ACTION" in + "get") get "$URL";; + *) echo "error unexpected action $ACTION"; exit 1;; +esac + diff --git a/zig/qm-file-manager.zig b/zig/qm-file-manager.zig new file mode 100644 index 0000000..b8b06e5 --- /dev/null +++ b/zig/qm-file-manager.zig @@ -0,0 +1,54 @@ +const std = @import("std"); + +const stdout_file = std.io.getStdOut().writer(); +var bw = std.io.bufferedWriter(stdout_file); +const stdout = bw.writer(); + +pub fn main() !u8 { + const action = std.os.getenv("ACTION") orelse return error.MissingAction; + if (std.mem.eql(u8, action, "get")) { + try get(std.os.getenv("URL") orelse return error.MissingUrl); + return 0; + } else { + try stdout.print("error unexpected action {s}\n", .{action}); + try bw.flush(); + return 1; + } +} + +fn get(url: []const u8) !void { + try stdout.print("title {s}\n", .{url}); + try stdout.print("add_tab\n", .{}); + + if (!std.mem.eql(u8, url, "/")) { + try stdout.print("title Go to parent directory\n", .{}); + try stdout.print("url ..\n", .{}); + try stdout.print("thumbnail_url folder.png\n", .{}); + try stdout.print("thumbnail_size 32x32\n", .{}); + try stdout.print("add_body_item\n", .{}); + } + + var dirIt = try std.fs.cwd().openIterableDir(url, .{ .no_follow = true }); + defer dirIt.close(); + + var pathBuf: [std.fs.MAX_PATH_BYTES]u8 = undefined; + + var it = dirIt.iterate(); + while (try it.next()) |*entry| { + var fba = std.heap.FixedBufferAllocator.init(&pathBuf); + var allocator = fba.allocator(); + const fullFilepath = try std.fs.path.join(allocator, &[_][]const u8{ url, entry.name }); + + try stdout.print("title {s}\n", .{fullFilepath}); + try stdout.print("url {s}\n", .{fullFilepath}); + if (entry.kind == .directory) { + try stdout.print("thumbnail_url folder.png\n", .{}); + } else { + try stdout.print("thumbnail_url file.png\n", .{}); + } + try stdout.print("thumbnail_size 32x32\n", .{}); + try stdout.print("add_body_item\n", .{}); + } + + try bw.flush(); +} -- cgit v1.2.3