diff options
-rw-r--r-- | docs/guide/typescript/widget.md | 10 | ||||
l--------- | docs/result-dev | 1 | ||||
-rw-r--r-- | lib/apps/application.vala | 55 | ||||
-rw-r--r-- | lib/apps/apps.vala | 63 | ||||
-rw-r--r-- | lib/apps/fuzzy.vala | 4 | ||||
-rw-r--r-- | lib/astal/io/application.vala | 38 | ||||
-rw-r--r-- | lib/astal/io/cli.vala | 16 | ||||
-rw-r--r-- | lib/astal/io/file.vala | 17 | ||||
-rw-r--r-- | lib/astal/io/process.vala | 75 | ||||
-rw-r--r-- | lib/astal/io/time.vala | 44 | ||||
-rw-r--r-- | lib/astal/io/variable.vala | 4 |
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 (); |