summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAylur <[email protected]>2024-10-16 12:47:38 +0200
committerGitHub <[email protected]>2024-10-16 12:47:38 +0200
commitc012b5699afd401942e1044c204fb6a666d0a094 (patch)
tree5cd27e5162a84f2ee5310fc698d7b50ee08eddf0
parent2ad95e05d83a455bb30503ca4ca0aa8356ea5ff7 (diff)
parent8368b20eda96674e0f5a502b92d3afb936b71b0b (diff)
Merge branch 'main' into fix/fuzzy-search
-rw-r--r--docs/guide/typescript/widget.md10
l---------docs/result-dev1
-rw-r--r--lib/apps/application.vala55
-rw-r--r--lib/apps/apps.vala63
-rw-r--r--lib/apps/fuzzy.vala4
-rw-r--r--lib/astal/io/application.vala38
-rw-r--r--lib/astal/io/cli.vala16
-rw-r--r--lib/astal/io/file.vala17
-rw-r--r--lib/astal/io/process.vala75
-rw-r--r--lib/astal/io/time.vala44
-rw-r--r--lib/astal/io/variable.vala4
11 files changed, 282 insertions, 45 deletions
diff --git a/docs/guide/typescript/widget.md b/docs/guide/typescript/widget.md
index d16d194..3bdf394 100644
--- a/docs/guide/typescript/widget.md
+++ b/docs/guide/typescript/widget.md
@@ -104,13 +104,14 @@ The `astalify` mixin will apply the following:
- sets up signal handlers that are passed as props prefixed with `on`
```tsx
-import { Widget, Gtk, GObject, Gdk } from "astal/gtk3"
+import GObject from "gi://GObject"
+import { Gtk, Gdk, Widget, astalify, type ConstructProps } from "astal/gtk3"
// subclass, register, define constructor props
-class ColorButton extends Widget.astalify(Gtk.ColorButton) {
+class ColorButton extends astalify(Gtk.ColorButton) {
static { GObject.registerClass(this) }
- constructor(props: Widget.ConstructProps<
+ constructor(props: ConstructProps<
ColorButton,
Gtk.ColorButton.ConstructorProps,
{ onColorSet: [] } // signals of Gtk.ColorButton have to be manually typed
@@ -152,7 +153,8 @@ Type of widgets are available through `Widget`.
Here is an example Widget that takes in and handles a possibly `Binding` prop.
```tsx
-import { Binding, Variable, Widget } from "astal"
+import { Binding, Variable } from "astal"
+import { Widget } from "astal/gtk3"
export interface ToggleButtonProps extends Widget.ButtonProps {
onToggled?: (self: Widget.Button, on: boolean) => void
diff --git a/docs/result-dev b/docs/result-dev
deleted file mode 120000
index 52fdae0..0000000
--- a/docs/result-dev
+++ /dev/null
@@ -1 +0,0 @@
-/nix/store/080gmk15wbbjx258rxzsq19ykjdrvl39-astal-0.1.0-dev \ No newline at end of file
diff --git a/lib/apps/application.vala b/lib/apps/application.vala
index 75ff6b2..7e20b06 100644
--- a/lib/apps/application.vala
+++ b/lib/apps/application.vala
@@ -1,12 +1,45 @@
-namespace AstalApps {
-public class Application : Object {
+public class AstalApps.Application : Object {
+ /**
+ * The underlying DesktopAppInfo.
+ */
public DesktopAppInfo app { get; construct set; }
+
+ /**
+ * The number of times [[email protected]] was called on this Application.
+ */
public int frequency { get; set; default = 0; }
+
+ /**
+ * The name of this Application.
+ */
public string name { get { return app.get_name(); } }
+
+ /**
+ * Name of the .desktop of this Application.
+ */
public string entry { get { return app.get_id(); } }
+
+ /**
+ * Description of this Application.
+ */
public string description { get { return app.get_description(); } }
+
+ /**
+ * The StartupWMClass field from the desktop file.
+ * This represents the WM_CLASS property of the main window of the application.
+ */
public string wm_class { get { return app.get_startup_wm_class(); } }
+
+ /**
+ * `Exec` field from the desktop file.
+ * Note that if you want to launch this Application you should use the [[email protected]] method.
+ */
public string executable { owned get { return app.get_string("Exec"); } }
+
+ /**
+ * `Icon` field from the desktop file.
+ * This is usually a named icon or a path to a file.
+ */
public string icon_name { owned get { return app.get_string("Icon"); } }
internal Application(string id, int? frequency = 0) {
@@ -14,10 +47,17 @@ public class Application : Object {
this.frequency = frequency;
}
+ /**
+ * Get a value from the .desktop file by its key.
+ */
public string get_key(string key) {
return app.get_string(key);
}
+ /**
+ * Launches this application.
+ * The launched application inherits the environment of the launching process
+ */
public bool launch() {
try {
var s = app.launch(null, null);
@@ -29,7 +69,7 @@ public class Application : Object {
}
}
- public Score fuzzy_match(string term) {
+ internal Score fuzzy_match(string term) {
var score = Score();
if (name != null)
score.name = fuzzy_match_string(term, name);
@@ -43,7 +83,7 @@ public class Application : Object {
return score;
}
- public Score exact_match(string term) {
+ internal Score exact_match(string term) {
var score = Score();
if (name != null)
score.name = name.down().contains(term.down()) ? 1 : 0;
@@ -71,14 +111,9 @@ public class Application : Object {
}
}
-int min3(int a, int b, int c) {
- return (a < b) ? ((a < c) ? a : c) : ((b < c) ? b : c);
-}
-
-public struct Score {
+public struct AstalApps.Score {
int name;
int entry;
int executable;
int description;
}
-}
diff --git a/lib/apps/apps.vala b/lib/apps/apps.vala
index acab155..bbe07c6 100644
--- a/lib/apps/apps.vala
+++ b/lib/apps/apps.vala
@@ -1,23 +1,70 @@
-namespace AstalApps {
-public class Apps : Object {
+public class AstalApps.Apps : Object {
private string cache_directory;
private string cache_file;
private List<Application> _list;
private HashTable<string, int> frequents { get; private set; }
+ /**
+ * Indicates wether hidden applications should included in queries.
+ */
public bool show_hidden { get; set; }
+
+ /**
+ * Full list of available applications.
+ */
public List<weak Application> list { owned get { return _list.copy(); } }
+ /**
+ * The minimum score the application has to meet in order to be included in queries.
+ */
public double min_score { get; set; default = 0; }
+ /**
+ * Extra multiplier to apply when matching the `name` of an application.
+ * Defaults to `2`
+ */
public double name_multiplier { get; set; default = 2; }
+
+ /**
+ * Extra multiplier to apply when matching the entry of an application.
+ * Defaults to `1`
+ */
public double entry_multiplier { get; set; default = 1; }
+
+ /**
+ * Extra multiplier to apply when matching the executable of an application.
+ * Defaults to `1`
+ */
public double executable_multiplier { get; set; default = 1; }
+
+ /**
+ * Extra multiplier to apply when matching the description of an application.
+ * Defaults to `0.5`
+ */
public double description_multiplier { get; set; default = 0.5; }
+ /**
+ * Consider the name of an application during queries.
+ * Defaults to `true`
+ */
public bool include_name { get; set; default = true; }
+
+ /**
+ * Consider the entry of an application during queries.
+ * Defaults to `false`
+ */
public bool include_entry { get; set; default = false; }
+
+ /**
+ * Consider the executable of an application during queries.
+ * Defaults to `false`
+ */
public bool include_executable { get; set; default = false; }
+
+ /**
+ * Consider the description of an application during queries.
+ * Defaults to `false`
+ */
public bool include_description { get; set; default = false; }
construct {
@@ -64,7 +111,7 @@ public class Apps : Object {
return r;
}
- public List<weak Application> query(string? search = "", bool exact = false) {
+ internal List<weak Application> query(string? search = "", bool exact = false) {
if (search == null)
search = "";
@@ -113,14 +160,23 @@ public class Apps : Object {
return arr;
}
+ /**
+ * Query the `list` of applications with a fuzzy matching algorithm.
+ */
public List<weak Application> fuzzy_query(string? search = "") {
return query(search, false);
}
+ /**
+ * Query the `list` of applications with a simple string matching algorithm.
+ */
public List<weak Application> exact_query(string? search = "") {
return query(search, true);
}
+ /**
+ * Reload the `list` of Applications.
+ */
public void reload() {
var arr = AppInfo.get_all();
@@ -168,4 +224,3 @@ public class Apps : Object {
}
}
}
-}
diff --git a/lib/apps/fuzzy.vala b/lib/apps/fuzzy.vala
index b77fba7..7745320 100644
--- a/lib/apps/fuzzy.vala
+++ b/lib/apps/fuzzy.vala
@@ -1,7 +1,5 @@
-
namespace AstalApps {
-
-public int fuzzy_match_string(string pattern, string str) {
+private int fuzzy_match_string(string pattern, string str) {
const int unmatched_letter_penalty = -1;
int score = 100;
diff --git a/lib/astal/io/application.vala b/lib/astal/io/application.vala
index b32de34..a420128 100644
--- a/lib/astal/io/application.vala
+++ b/lib/astal/io/application.vala
@@ -4,6 +4,10 @@ public errordomain AppError {
TAKEOVER_FAILED,
}
+/**
+ * This interface is used as a placeholder for the Astal Application class.
+ * It is not meant to be used by consumers.
+ */
public interface Application : Object {
public abstract void quit() throws Error;
public abstract void inspector() throws Error;
@@ -16,6 +20,10 @@ public interface Application : Object {
}
}
+/**
+ * Starts a [[email protected]] and binds `XDG_RUNTIME_DIR/astal/<instance_name>.sock`.
+ * This socket is then used by the astal cli. Not meant for public usage, but for [[email protected]_socket].
+ */
public SocketService acquire_socket(Application app, out string sock) throws Error {
var name = app.instance_name;
foreach (var instance in get_instances()) {
@@ -65,6 +73,10 @@ public SocketService acquire_socket(Application app, out string sock) throws Err
return service;
}
+/**
+ * Get a list of running Astal.Application instances.
+ * It is the equivalent of `astal --list`.
+ */
public static List<string> get_instances() {
var list = new List<string>();
var prefix = "io.Astal.";
@@ -87,6 +99,10 @@ public static List<string> get_instances() {
return list;
}
+/**
+ * Quit an an Astal instances.
+ * It is the equivalent of `astal --quit -i instance`.
+ */
public static void quit_instance(string instance) {
try {
IApplication proxy = Bus.get_proxy_sync(
@@ -101,6 +117,10 @@ public static void quit_instance(string instance) {
}
}
+/**
+ * Open the Gtk debug tool of an an Astal instances.
+ * It is the equivalent of `astal --inspector -i instance`.
+ */
public static void open_inspector(string instance) {
try {
IApplication proxy = Bus.get_proxy_sync(
@@ -115,6 +135,10 @@ public static void open_inspector(string instance) {
}
}
+/**
+ * Toggle a Window of an Astal instances.
+ * It is the equivalent of `astal -i instance --toggle window`.
+ */
public static void toggle_window_by_name(string instance, string window) {
try {
IApplication proxy = Bus.get_proxy_sync(
@@ -129,9 +153,13 @@ public static void toggle_window_by_name(string instance, string window) {
}
}
-public static string send_message(string instance_name, string msg) {
+/**
+ * Send a message to an Astal instances.
+ * It is the equivalent of `astal -i instance content of the message`.
+ */
+public static string send_message(string instance, string msg) {
var rundir = Environment.get_user_runtime_dir();
- var socket_path = @"$rundir/astal/$instance_name.sock";
+ var socket_path = @"$rundir/astal/$instance.sock";
var client = new SocketClient();
try {
@@ -146,11 +174,17 @@ public static string send_message(string instance_name, string msg) {
}
}
+/**
+ * Read the socket of an Astal.Application instance.
+ */
public async string read_sock(SocketConnection conn) throws IOError {
var stream = new DataInputStream(conn.input_stream);
return yield stream.read_upto_async("\x04", -1, Priority.DEFAULT, null, null);
}
+/**
+ * Write the socket of an Astal.Application instance.
+ */
public async void write_sock(SocketConnection conn, string response) throws IOError {
yield conn.output_stream.write_async(response.concat("\x04").data, Priority.DEFAULT);
}
diff --git a/lib/astal/io/cli.vala b/lib/astal/io/cli.vala
index 1db0b2e..8fc0523 100644
--- a/lib/astal/io/cli.vala
+++ b/lib/astal/io/cli.vala
@@ -1,12 +1,12 @@
-private static bool version;
-private static bool help;
-private static bool list;
-private static bool quit;
-private static bool inspector;
-private static string? toggle_window;
-private static string? instance_name;
+static bool version;
+static bool help;
+static bool list;
+static bool quit;
+static bool inspector;
+static string? toggle_window;
+static string? instance_name;
-private const OptionEntry[] options = {
+const OptionEntry[] options = {
{ "version", 'v', OptionFlags.NONE, OptionArg.NONE, ref version, null, null },
{ "help", 'h', OptionFlags.NONE, OptionArg.NONE, ref help, null, null },
{ "list", 'l', OptionFlags.NONE, OptionArg.NONE, ref list, null, null },
diff --git a/lib/astal/io/file.vala b/lib/astal/io/file.vala
index b2d480c..e57f449 100644
--- a/lib/astal/io/file.vala
+++ b/lib/astal/io/file.vala
@@ -1,4 +1,7 @@
namespace AstalIO {
+/**
+ * Read the contents of a file synchronously.
+ */
public string read_file(string path) {
var str = "";
try {
@@ -9,12 +12,18 @@ public string read_file(string path) {
return str;
}
+/**
+ * Read the contents of a file asynchronously.
+ */
public async string read_file_async(string path) throws Error {
uint8[] content;
yield File.new_for_path(path).load_contents_async(null, out content, null);
return (string)content;
}
+/**
+ * Write content to a file synchronously.
+ */
public void write_file(string path, string content) {
try {
FileUtils.set_contents(path, content);
@@ -23,6 +32,9 @@ public void write_file(string path, string content) {
}
}
+/**
+ * Write content to a file asynchronously.
+ */
public async void write_file_async(string path, string content) throws Error {
yield File.new_for_path(path).replace_contents_async(
content.data,
@@ -33,6 +45,11 @@ public async void write_file_async(string path, string content) throws Error {
null);
}
+/**
+ * Monitor a file for changes. If the path is a directory, monitor it recursively.
+ * The callback will be called passed two parameters: the path of the file
+ * that changed and an [[email protected]] indicating the reason.
+ */
public FileMonitor? monitor_file(string path, Closure callback) {
try {
var file = File.new_for_path(path);
diff --git a/lib/astal/io/process.vala b/lib/astal/io/process.vala
index e8637ab..8767012 100644
--- a/lib/astal/io/process.vala
+++ b/lib/astal/io/process.vala
@@ -1,3 +1,6 @@
+/**
+ * `Process` provides shortcuts for [[email protected]] with sane defaults.
+ */
public class AstalIO.Process : Object {
private void read_stream(DataInputStream stream, bool err) {
stream.read_line_utf8_async.begin(Priority.DEFAULT, null, (_, res) => {
@@ -23,34 +26,56 @@ public class AstalIO.Process : Object {
private Subprocess process;
public string[] argv { construct; get; }
+
+ /**
+ * When the underlying subprocess writes to its stdout
+ * this signal is emitted with that line.
+ */
public signal void stdout (string out);
+
+ /**
+ * When the underlying subprocess writes to its stderr
+ * this signal is emitted with that line.
+ */
public signal void stderr (string err);
+ /**
+ * Force quit the subprocess.
+ */
public void kill() {
process.force_exit();
}
+ /**
+ * Send a signal to the subprocess.
+ */
public void signal(int signal_num) {
process.send_signal(signal_num);
}
+ /**
+ * Write a line to the subprocess' stdin synchronously.
+ */
public void write(string in) throws Error {
in_stream.put_string(in);
}
- public void write_async(string in) {
- in_stream.write_all_async.begin(
- in.data,
- Priority.DEFAULT, null, (_, res) => {
- try {
- in_stream.write_all_async.end(res, null);
- } catch (Error err) {
- printerr("%s\n", err.message);
- }
- }
- );
+ /**
+ * Write a line to the subprocess' stdin asynchronously.
+ */
+ public async void write_async(string in) {
+ try {
+ yield in_stream.write_all_async(in.data, in.data.length, null, null);
+ } catch (Error err) {
+ printerr("%s\n", err.message);
+ }
}
+ /**
+ * Start a new subprocess with the given command.
+ *
+ * The first element of the vector is executed with the remaining elements as the argument list.
+ */
public Process.subprocessv(string[] cmd) throws Error {
Object(argv: cmd);
process = new Subprocess.newv(cmd,
@@ -65,12 +90,22 @@ public class AstalIO.Process : Object {
read_stream(err_stream, false);
}
+ /**
+ * Start a new subprocess with the given command
+ * which is parsed using [[email protected]_argv].
+ */
public static Process subprocess(string cmd) throws Error {
string[] argv;
Shell.parse_argv(cmd, out argv);
return new Process.subprocessv(argv);
}
+ /**
+ * Execute a command synchronously.
+ * The first element of the vector is executed with the remaining elements as the argument list.
+ *
+ * @return stdout of the subprocess
+ */
public static string execv(string[] cmd) throws Error {
var process = new Subprocess.newv(
cmd,
@@ -88,12 +123,24 @@ public class AstalIO.Process : Object {
throw new IOError.FAILED(err_str.strip());
}
+ /**
+ * Execute a command synchronously.
+ * The command is parsed using [[email protected]_argv].
+ *
+ * @return stdout of the subprocess
+ */
public static string exec(string cmd) throws Error {
string[] argv;
Shell.parse_argv(cmd, out argv);
return Process.execv(argv);
}
+ /**
+ * Execute a command asynchronously.
+ * The first element of the vector is executed with the remaining elements as the argument list.
+ *
+ * @return stdout of the subprocess
+ */
public static async string exec_asyncv(string[] cmd) throws Error {
var process = new Subprocess.newv(
cmd,
@@ -111,6 +158,12 @@ public class AstalIO.Process : Object {
throw new IOError.FAILED(err_str.strip());
}
+ /**
+ * Execute a command asynchronously.
+ * The command is parsed using [[email protected]_argv].
+ *
+ * @return stdout of the subprocess
+ */
public static async string exec_async(string cmd) throws Error {
string[] argv;
Shell.parse_argv(cmd, out argv);
diff --git a/lib/astal/io/time.vala b/lib/astal/io/time.vala
index 1446441..29e7e1f 100644
--- a/lib/astal/io/time.vala
+++ b/lib/astal/io/time.vala
@@ -1,10 +1,21 @@
+/**
+ * `Time` provides shortcuts for GLib timeout functions.
+ */
public class AstalIO.Time : Object {
- public signal void now ();
- public signal void cancelled ();
private Cancellable cancellable;
private uint timeout_id;
private bool fulfilled = false;
+ /**
+ * Emitted when the timer ticks.
+ */
+ public signal void now ();
+
+ /**
+ * Emitted when the timere is cancelled.
+ */
+ public signal void cancelled ();
+
construct {
cancellable = new Cancellable();
cancellable.cancelled.connect(() => {
@@ -26,6 +37,9 @@ public class AstalIO.Time : Object {
});
}
+ /**
+ * Start an interval timer with a [[email protected]].
+ */
public Time.interval_prio(uint interval, int prio = Priority.DEFAULT, Closure? fn) {
connect_closure(fn);
Idle.add_once(() => now());
@@ -35,6 +49,9 @@ public class AstalIO.Time : Object {
}, prio);
}
+ /**
+ * Start a timeout timer with a [[email protected]].
+ */
public Time.timeout_prio(uint timeout, int prio = Priority.DEFAULT, Closure? fn) {
connect_closure(fn);
timeout_id = Timeout.add(timeout, () => {
@@ -44,6 +61,9 @@ public class AstalIO.Time : Object {
}, prio);
}
+ /**
+ * Start an idle timer with a [[email protected]].
+ */
public Time.idle_prio(int prio = Priority.DEFAULT_IDLE, Closure? fn) {
connect_closure(fn);
timeout_id = Idle.add(() => {
@@ -53,18 +73,38 @@ public class AstalIO.Time : Object {
}, prio);
}
+ /**
+ * Start an interval timer. Ticks immediately then every `interval` milliseconds.
+ *
+ * @param interval Tick every milliseconds.
+ * @param fn Optional callback.
+ */
public static Time interval(uint interval, Closure? fn) {
return new Time.interval_prio(interval, Priority.DEFAULT, fn);
}
+ /**
+ * Start a timeout timer which ticks after `timeout` milliseconds.
+ *
+ * @param timeout Tick after milliseconds.
+ * @param fn Optional callback.
+ */
public static Time timeout(uint timeout, Closure? fn) {
return new Time.timeout_prio(timeout, Priority.DEFAULT, fn);
}
+ /**
+ * Start a timer which will tick when there are no higher priority tasks pending.
+ *
+ * @param fn Optional callback.
+ */
public static Time idle(Closure? fn) {
return new Time.idle_prio(Priority.DEFAULT_IDLE, fn);
}
+ /**
+ * Cancel timer and emit [[email protected]::cancelled]
+ */
public void cancel() {
cancellable.cancel();
}
diff --git a/lib/astal/io/variable.vala b/lib/astal/io/variable.vala
index 2a395b4..312a27a 100644
--- a/lib/astal/io/variable.vala
+++ b/lib/astal/io/variable.vala
@@ -1,3 +1,7 @@
+/*
+ * Base class for [[email protected]] mainly meant to be used
+ * in higher level language bindings such as Lua and Gjs.
+ */
public class AstalIO.VariableBase : Object {
public signal void changed ();
public signal void dropped ();