mirror of
https://github.com/fairyglade/ly.git
synced 2025-12-21 11:44:55 +00:00
Compare commits
201 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a9b6bfc62a | ||
|
|
32d0de3d2d | ||
|
|
a4dd5b3c44 | ||
|
|
b7d81a9b51 | ||
|
|
3359127a06 | ||
|
|
faa2636c99 | ||
|
|
9d23209ca3 | ||
|
|
170e523823 | ||
|
|
f983c6b19b | ||
|
|
d12850889c | ||
|
|
42393f46d1 | ||
|
|
fa0d8c509d | ||
|
|
b42953fd7e | ||
|
|
11d9cf8b71 | ||
|
|
67a4dd8f9d | ||
|
|
cedb7a3b02 | ||
|
|
02729cce21 | ||
|
|
d9204131aa | ||
|
|
e90cf40e5b | ||
|
|
b0395ef103 | ||
|
|
692e7265e3 | ||
|
|
732888fd94 | ||
|
|
71a06e13a6 | ||
|
|
f74c4e92a9 | ||
|
|
555e72a388 | ||
|
|
a1b38188d0 | ||
|
|
751d31cae2 | ||
|
|
c6a3223a03 | ||
|
|
d2803194f3 | ||
|
|
4345a99c02 | ||
|
|
fecc688418 | ||
|
|
b7e37ce1b7 | ||
|
|
be5a68dd1d | ||
|
|
622303d150 | ||
|
|
7747b27f9d | ||
|
|
585ca5f0da | ||
|
|
c624c35ac7 | ||
|
|
beb6d04c58 | ||
|
|
32793bcfeb | ||
|
|
9ded9fd765 | ||
|
|
13ba52319c | ||
|
|
1672d4a9ec | ||
|
|
e0ed1b4eb1 | ||
|
|
fa0748ead2 | ||
|
|
86ea38f460 | ||
|
|
9efb734fd5 | ||
|
|
5f52063835 | ||
|
|
548fa210c1 | ||
|
|
75975ea301 | ||
|
|
8fa6b2cec9 | ||
|
|
4dcef65b1c | ||
|
|
1eca889e45 | ||
|
|
ac1d828a5f | ||
|
|
92845268af | ||
|
|
6504cd0209 | ||
|
|
a058a81ec9 | ||
|
|
c6db79b873 | ||
|
|
932c751ac2 | ||
|
|
4599654398 | ||
|
|
e19a23b54c | ||
|
|
f2ca72eace | ||
|
|
4e859e56cb | ||
|
|
78d64ad2a7 | ||
|
|
d80ec8fd1f | ||
|
|
d12fa27168 | ||
|
|
593a775148 | ||
|
|
6079c01a4b | ||
|
|
9c79137c9f | ||
|
|
9168266cca | ||
|
|
6cb102257c | ||
|
|
55abc4d7f1 | ||
|
|
f013af0dde | ||
|
|
973d8fe120 | ||
|
|
3e6d7a1b3b | ||
|
|
0c69e0412c | ||
|
|
d0ccaa4d69 | ||
|
|
a766dc2b9c | ||
|
|
f54657432a | ||
|
|
87503367e9 | ||
|
|
85e071a60a | ||
|
|
24599368df | ||
|
|
d5bc6aab24 | ||
|
|
c9a416b8a2 | ||
|
|
15c2b19371 | ||
|
|
142073c362 | ||
|
|
514931b486 | ||
|
|
50e9e912e0 | ||
|
|
895edaf904 | ||
|
|
bebccf4d5a | ||
|
|
346a614ba0 | ||
|
|
d171634f9b | ||
|
|
f5f7422d82 | ||
|
|
117eccd65a | ||
|
|
b6726a76c6 | ||
|
|
0dea19c8db | ||
|
|
7a82b51ac5 | ||
|
|
fe36879dfb | ||
|
|
47ebe641d9 | ||
|
|
7a1fce660c | ||
|
|
06e283961d | ||
|
|
e125d8f1aa | ||
|
|
e885a5e776 | ||
|
|
aea95b7724 | ||
|
|
215ca5edc7 | ||
|
|
022d146f76 | ||
|
|
87ceba4de8 | ||
|
|
b80c276dad | ||
|
|
b84158e1c0 | ||
|
|
c87d5b4e7a | ||
|
|
028cb9496a | ||
|
|
00c94f8ffd | ||
|
|
2bd0d0d4f3 | ||
|
|
767bdaf166 | ||
|
|
c033f5bd03 | ||
|
|
096b1a7d44 | ||
|
|
f0869f0e13 | ||
|
|
1ca53f661e | ||
|
|
8562cf4e29 | ||
|
|
b5b3317dd8 | ||
|
|
2901b408dc | ||
|
|
4e40e32f59 | ||
|
|
5e85618730 | ||
|
|
2c428f5537 | ||
|
|
071b7a2182 | ||
|
|
1075c923ef | ||
|
|
391f86f602 | ||
|
|
6fbbb4eff0 | ||
|
|
c7f70ac78f | ||
|
|
ef86ea19ac | ||
|
|
37061269a4 | ||
|
|
7b9f03176d | ||
|
|
b73c78d2fb | ||
|
|
0bbe9c78dd | ||
|
|
b18f29a81a | ||
|
|
cab3a7d214 | ||
|
|
8995c590eb | ||
|
|
57d5d7497b | ||
|
|
ce3b310e58 | ||
|
|
5d3cd62434 | ||
|
|
d40ec873a7 | ||
|
|
61f3fadfbf | ||
|
|
1314c57796 | ||
|
|
872b15c0d4 | ||
|
|
9b4d381f1e | ||
|
|
bacbacd5fb | ||
|
|
ee0c00574a | ||
|
|
6df91cac12 | ||
|
|
598fa6a505 | ||
|
|
548a411ae2 | ||
|
|
48f28e40c4 | ||
|
|
46f9ddd5fc | ||
|
|
a393525212 | ||
|
|
961018e753 | ||
|
|
8b12ade372 | ||
|
|
a64d7efc69 | ||
|
|
b592a11fb0 | ||
|
|
3fedb59fdb | ||
|
|
b1bf89a4cf | ||
|
|
2dec2e0b7f | ||
|
|
5f2f21620a | ||
|
|
48185bdfe0 | ||
|
|
f646dddd02 | ||
|
|
c1f1c8f5c1 | ||
|
|
ee488ba36e | ||
|
|
56c210372d | ||
|
|
04a0ad3b33 | ||
|
|
2dd83b41e8 | ||
|
|
19d4b195f3 | ||
|
|
93554d9ba3 | ||
|
|
075bf67cef | ||
|
|
33791a2844 | ||
|
|
8333f7ea77 | ||
|
|
2bc12549a1 | ||
|
|
1df890b238 | ||
|
|
92c6a38835 | ||
|
|
a7e8b55c6e | ||
|
|
b7e1c81ad1 | ||
|
|
dc310ca80e | ||
|
|
da2ea08078 | ||
|
|
8c69472065 | ||
|
|
0ee28927cf | ||
|
|
b7934e42d1 | ||
|
|
e775827c8b | ||
|
|
9cd58123c4 | ||
|
|
0cead672da | ||
|
|
ce90f91bbf | ||
|
|
23c7175528 | ||
|
|
5ea780f806 | ||
|
|
2eaa473144 | ||
|
|
a939b82179 | ||
|
|
2b0301c1d0 | ||
|
|
b84e6c9eed | ||
|
|
49b8697546 | ||
|
|
1d7a001a0b | ||
|
|
3dc1482603 | ||
|
|
e4abf79ad5 | ||
|
|
5f8fbe381c | ||
|
|
c6d7d177b7 | ||
|
|
dc8d143fac | ||
|
|
cbe7b37564 | ||
|
|
4eb4e15e43 |
68
.github/ISSUE_TEMPLATE/bug.yml
vendored
Normal file
68
.github/ISSUE_TEMPLATE/bug.yml
vendored
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
name: Bug report
|
||||||
|
description: File a bug report.
|
||||||
|
title: "[Bug] "
|
||||||
|
labels: ["bug"]
|
||||||
|
body:
|
||||||
|
- type: checkboxes
|
||||||
|
id: prerequisites
|
||||||
|
attributes:
|
||||||
|
label: Pre-requisites
|
||||||
|
description: By submitting this issue, you agree to have done the following.
|
||||||
|
options:
|
||||||
|
- label: I have looked for any other duplicate issues
|
||||||
|
required: true
|
||||||
|
- type: input
|
||||||
|
id: version
|
||||||
|
attributes:
|
||||||
|
label: Ly version
|
||||||
|
description: The output of `ly --version`. Please note that only Ly v1.1.0 and above are supported.
|
||||||
|
placeholder: 1.1.0-dev.12+2b0301c
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: textarea
|
||||||
|
id: observed
|
||||||
|
attributes:
|
||||||
|
label: Observed behavior
|
||||||
|
description: What happened?
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: textarea
|
||||||
|
id: expected
|
||||||
|
attributes:
|
||||||
|
label: Expected behavior
|
||||||
|
description: What did you expect to happen instead?
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: input
|
||||||
|
id: desktop
|
||||||
|
attributes:
|
||||||
|
label: OS + Desktop environment/Window manager
|
||||||
|
description: Which OS and DE (or WM) did you use when observing the problem?
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: textarea
|
||||||
|
id: reproduction
|
||||||
|
attributes:
|
||||||
|
label: Steps to reproduce
|
||||||
|
description: What **exactly** can someone else do in order to observe the problem you observed?
|
||||||
|
placeholder: |
|
||||||
|
1. Authenticate with ...
|
||||||
|
2. Go to ...
|
||||||
|
3. Create file ...
|
||||||
|
4. Log out and log back in
|
||||||
|
5. Observe error
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: textarea
|
||||||
|
id: logs
|
||||||
|
attributes:
|
||||||
|
label: Relevant logs
|
||||||
|
description: |
|
||||||
|
Please copy and paste any relevant logs, error messages or any other output. This will be automatically formatted into code, so no need for backticks. Screenshots are accepted if they make life easier for you.
|
||||||
|
If you're using the latest code on master (for v1.1.0), including your session log (found at /var/log/ly-session.log unless modified) is a good idea. (But make sure it's relevant!)
|
||||||
|
render: shell
|
||||||
|
- type: textarea
|
||||||
|
id: moreinfo
|
||||||
|
attributes:
|
||||||
|
label: Additional information
|
||||||
|
description: If you have any additional information that might be helpful in reproducing the problem, please provide it here.
|
||||||
22
.github/ISSUE_TEMPLATE/feature.yml
vendored
Normal file
22
.github/ISSUE_TEMPLATE/feature.yml
vendored
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
name: Feature request
|
||||||
|
description: Request a new feature or enhancement.
|
||||||
|
title: "[Feature] "
|
||||||
|
labels: ["feature"]
|
||||||
|
body:
|
||||||
|
- type: checkboxes
|
||||||
|
id: prerequisites
|
||||||
|
attributes:
|
||||||
|
label: Pre-requisites
|
||||||
|
description: By submitting this issue, you agree to have done the following.
|
||||||
|
options:
|
||||||
|
- label: I have looked for any other duplicate issues
|
||||||
|
required: true
|
||||||
|
- label: I have confirmed the requested feature doesn't exist in the latest version in development
|
||||||
|
required: true
|
||||||
|
- type: textarea
|
||||||
|
id: wanted
|
||||||
|
attributes:
|
||||||
|
label: Wanted behavior
|
||||||
|
description: What do you want to be added? Describe the behavior clearly.
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
BIN
.github/screenshot.png
vendored
Normal file
BIN
.github/screenshot.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 43 KiB |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -2,3 +2,4 @@
|
|||||||
zig-cache/
|
zig-cache/
|
||||||
zig-out/
|
zig-out/
|
||||||
valgrind.log
|
valgrind.log
|
||||||
|
.zig-cache
|
||||||
|
|||||||
432
build.zig
432
build.zig
@@ -1,29 +1,61 @@
|
|||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
|
const builtin = @import("builtin");
|
||||||
|
|
||||||
|
const PatchMap = std.StringHashMap([]const u8);
|
||||||
|
const InitSystem = enum {
|
||||||
|
systemd,
|
||||||
|
openrc,
|
||||||
|
runit,
|
||||||
|
s6,
|
||||||
|
dinit,
|
||||||
|
};
|
||||||
|
|
||||||
|
const min_zig_string = "0.14.0";
|
||||||
|
const current_zig = builtin.zig_version;
|
||||||
|
|
||||||
|
// Implementing zig version detection through compile time
|
||||||
|
comptime {
|
||||||
|
const min_zig = std.SemanticVersion.parse(min_zig_string) catch unreachable;
|
||||||
|
if (current_zig.order(min_zig) == .lt) {
|
||||||
|
@compileError(std.fmt.comptimePrint("Your Zig version v{} does not meet the minimum build requirement of v{}", .{ current_zig, min_zig }));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const ly_version = std.SemanticVersion{ .major = 1, .minor = 1, .patch = 2 };
|
||||||
|
|
||||||
const ly_version = std.SemanticVersion{ .major = 1, .minor = 0, .patch = 0 };
|
|
||||||
var dest_directory: []const u8 = undefined;
|
var dest_directory: []const u8 = undefined;
|
||||||
var data_directory: []const u8 = undefined;
|
var config_directory: []const u8 = undefined;
|
||||||
var exe_name: []const u8 = undefined;
|
var prefix_directory: []const u8 = undefined;
|
||||||
|
var executable_name: []const u8 = undefined;
|
||||||
|
var init_system: InitSystem = undefined;
|
||||||
|
var default_tty_str: []const u8 = undefined;
|
||||||
|
|
||||||
pub fn build(b: *std.Build) !void {
|
pub fn build(b: *std.Build) !void {
|
||||||
dest_directory = b.option([]const u8, "dest_directory", "Specify a dest directory for installation") orelse "";
|
dest_directory = b.option([]const u8, "dest_directory", "Specify a destination directory for installation") orelse "";
|
||||||
data_directory = b.option([]const u8, "data_directory", "Specify a default data directory (default is /etc/ly)") orelse "/etc/ly";
|
config_directory = b.option([]const u8, "config_directory", "Specify a default config directory (default is /etc). This path gets embedded into the binary") orelse "/etc";
|
||||||
data_directory = try std.fs.path.join(b.allocator, &[_][]const u8{ dest_directory, data_directory });
|
prefix_directory = b.option([]const u8, "prefix_directory", "Specify a default prefix directory (default is /usr)") orelse "/usr";
|
||||||
exe_name = b.option([]const u8, "name", "Specify installed executable file name (default is ly)") orelse "ly";
|
executable_name = b.option([]const u8, "name", "Specify installed executable file name (default is ly)") orelse "ly";
|
||||||
|
init_system = b.option(InitSystem, "init_system", "Specify the target init system (default is systemd)") orelse .systemd;
|
||||||
|
|
||||||
const build_options = b.addOptions();
|
const build_options = b.addOptions();
|
||||||
build_options.addOption([]const u8, "data_directory", data_directory);
|
|
||||||
|
|
||||||
const version_str = try getVersionStr(b, "ly", ly_version);
|
const version_str = try getVersionStr(b, "ly", ly_version);
|
||||||
|
const enable_x11_support = b.option(bool, "enable_x11_support", "Enable X11 support (default is on)") orelse true;
|
||||||
|
const default_tty = b.option(u8, "default_tty", "Set the TTY (default is 2)") orelse 2;
|
||||||
|
|
||||||
|
default_tty_str = try std.fmt.allocPrint(b.allocator, "{d}", .{default_tty});
|
||||||
|
|
||||||
|
build_options.addOption([]const u8, "config_directory", config_directory);
|
||||||
|
build_options.addOption([]const u8, "prefix_directory", prefix_directory);
|
||||||
build_options.addOption([]const u8, "version", version_str);
|
build_options.addOption([]const u8, "version", version_str);
|
||||||
|
build_options.addOption(u8, "tty", default_tty);
|
||||||
|
build_options.addOption(bool, "enable_x11_support", enable_x11_support);
|
||||||
|
|
||||||
const target = b.standardTargetOptions(.{});
|
const target = b.standardTargetOptions(.{});
|
||||||
const optimize = b.standardOptimizeOption(.{});
|
const optimize = b.standardOptimizeOption(.{});
|
||||||
|
|
||||||
const exe = b.addExecutable(.{
|
const exe = b.addExecutable(.{
|
||||||
.name = "ly",
|
.name = "ly",
|
||||||
.root_source_file = .{ .path = "src/main.zig" },
|
.root_source_file = b.path("src/main.zig"),
|
||||||
.target = target,
|
.target = target,
|
||||||
.optimize = optimize,
|
.optimize = optimize,
|
||||||
});
|
});
|
||||||
@@ -36,25 +68,21 @@ pub fn build(b: *std.Build) !void {
|
|||||||
const clap = b.dependency("clap", .{ .target = target, .optimize = optimize });
|
const clap = b.dependency("clap", .{ .target = target, .optimize = optimize });
|
||||||
exe.root_module.addImport("clap", clap.module("clap"));
|
exe.root_module.addImport("clap", clap.module("clap"));
|
||||||
|
|
||||||
exe.addIncludePath(.{ .path = "include" });
|
exe.addIncludePath(b.path("include"));
|
||||||
exe.linkSystemLibrary("pam");
|
exe.linkSystemLibrary("pam");
|
||||||
exe.linkSystemLibrary("xcb");
|
if (enable_x11_support) exe.linkSystemLibrary("xcb");
|
||||||
exe.linkLibC();
|
exe.linkLibC();
|
||||||
|
|
||||||
// HACK: Only fails with ReleaseSafe, so we'll override it.
|
|
||||||
const translate_c = b.addTranslateC(.{
|
const translate_c = b.addTranslateC(.{
|
||||||
.root_source_file = .{ .path = "include/termbox2.h" },
|
.root_source_file = b.path("include/termbox2.h"),
|
||||||
.target = target,
|
.target = target,
|
||||||
.optimize = if (optimize == .ReleaseSafe) .ReleaseFast else optimize,
|
.optimize = optimize,
|
||||||
});
|
});
|
||||||
translate_c.defineCMacroRaw("TB_IMPL");
|
translate_c.defineCMacroRaw("TB_IMPL");
|
||||||
|
translate_c.defineCMacro("TB_OPT_ATTR_W", "32"); // Enable 24-bit color support + styling (32-bit)
|
||||||
const termbox2 = translate_c.addModule("termbox2");
|
const termbox2 = translate_c.addModule("termbox2");
|
||||||
exe.root_module.addImport("termbox2", termbox2);
|
exe.root_module.addImport("termbox2", termbox2);
|
||||||
|
|
||||||
if (optimize == .ReleaseSafe) {
|
|
||||||
std.debug.print("warn: termbox2 module is being built in ReleaseFast due to a bug.\n", .{});
|
|
||||||
}
|
|
||||||
|
|
||||||
b.installArtifact(exe);
|
b.installArtifact(exe);
|
||||||
|
|
||||||
const run_cmd = b.addRunArtifact(exe);
|
const run_cmd = b.addRunArtifact(exe);
|
||||||
@@ -66,179 +94,216 @@ pub fn build(b: *std.Build) !void {
|
|||||||
const run_step = b.step("run", "Run the app");
|
const run_step = b.step("run", "Run the app");
|
||||||
run_step.dependOn(&run_cmd.step);
|
run_step.dependOn(&run_cmd.step);
|
||||||
|
|
||||||
const installexe_step = b.step("installexe", "Install Ly");
|
const installexe_step = b.step("installexe", "Install Ly and the selected init system service");
|
||||||
installexe_step.makeFn = ExeInstaller(true).make;
|
installexe_step.makeFn = Installer(true).make;
|
||||||
installexe_step.dependOn(b.getInstallStep());
|
installexe_step.dependOn(b.getInstallStep());
|
||||||
|
|
||||||
const installnoconf_step = b.step("installnoconf", "Install Ly without its configuration file");
|
const installnoconf_step = b.step("installnoconf", "Install Ly and the selected init system service, but not the configuration file");
|
||||||
installnoconf_step.makeFn = ExeInstaller(false).make;
|
installnoconf_step.makeFn = Installer(false).make;
|
||||||
installnoconf_step.dependOn(b.getInstallStep());
|
installnoconf_step.dependOn(b.getInstallStep());
|
||||||
|
|
||||||
const installsystemd_step = b.step("installsystemd", "Install the Ly systemd service");
|
const uninstallexe_step = b.step("uninstallexe", "Uninstall Ly and remove the selected init system service");
|
||||||
installsystemd_step.makeFn = ServiceInstaller(.Systemd).make;
|
uninstallexe_step.makeFn = Uninstaller(true).make;
|
||||||
installsystemd_step.dependOn(installexe_step);
|
|
||||||
|
|
||||||
const installopenrc_step = b.step("installopenrc", "Install the Ly openrc service");
|
const uninstallnoconf_step = b.step("uninstallnoconf", "Uninstall Ly and remove the selected init system service, but keep the configuration directory");
|
||||||
installopenrc_step.makeFn = ServiceInstaller(.Openrc).make;
|
uninstallnoconf_step.makeFn = Uninstaller(false).make;
|
||||||
installopenrc_step.dependOn(installexe_step);
|
|
||||||
|
|
||||||
const installrunit_step = b.step("installrunit", "Install the Ly runit service");
|
|
||||||
installrunit_step.makeFn = ServiceInstaller(.Runit).make;
|
|
||||||
installrunit_step.dependOn(installexe_step);
|
|
||||||
|
|
||||||
const uninstallall_step = b.step("uninstallall", "Uninstall Ly and all services");
|
|
||||||
uninstallall_step.makeFn = uninstallall;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn ExeInstaller(install_conf: bool) type {
|
pub fn Installer(install_config: bool) type {
|
||||||
return struct {
|
return struct {
|
||||||
pub fn make(step: *std.Build.Step, progress: *std.Progress.Node) !void {
|
pub fn make(step: *std.Build.Step, _: std.Build.Step.MakeOptions) !void {
|
||||||
_ = progress;
|
|
||||||
try install_ly(step.owner.allocator, install_conf);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
const InitSystem = enum {
|
|
||||||
Systemd,
|
|
||||||
Openrc,
|
|
||||||
Runit,
|
|
||||||
};
|
|
||||||
pub fn ServiceInstaller(comptime init_system: InitSystem) type {
|
|
||||||
return struct {
|
|
||||||
pub fn make(step: *std.Build.Step, progress: *std.Progress.Node) !void {
|
|
||||||
_ = progress;
|
|
||||||
const allocator = step.owner.allocator;
|
const allocator = step.owner.allocator;
|
||||||
switch (init_system) {
|
|
||||||
.Openrc => {
|
|
||||||
const service_path = try std.fs.path.join(allocator, &[_][]const u8{ dest_directory, "/etc/init.d" });
|
|
||||||
std.fs.cwd().makePath(service_path) catch {};
|
|
||||||
var service_dir = std.fs.openDirAbsolute(service_path, .{}) catch unreachable;
|
|
||||||
defer service_dir.close();
|
|
||||||
|
|
||||||
try std.fs.cwd().copyFile("res/ly-openrc", service_dir, exe_name, .{ .override_mode = 755 });
|
var patch_map = PatchMap.init(allocator);
|
||||||
},
|
defer patch_map.deinit();
|
||||||
.Runit => {
|
|
||||||
const service_path = try std.fs.path.join(allocator, &[_][]const u8{ dest_directory, "/etc/sv/ly" });
|
|
||||||
std.fs.cwd().makePath(service_path) catch {};
|
|
||||||
var service_dir = std.fs.openDirAbsolute(service_path, .{}) catch unreachable;
|
|
||||||
defer service_dir.close();
|
|
||||||
|
|
||||||
try std.fs.cwd().copyFile("res/ly-runit-service/conf", service_dir, "conf", .{});
|
try patch_map.put("$DEFAULT_TTY", default_tty_str);
|
||||||
try std.fs.cwd().copyFile("res/ly-runit-service/finish", service_dir, "finish", .{});
|
try patch_map.put("$CONFIG_DIRECTORY", config_directory);
|
||||||
try std.fs.cwd().copyFile("res/ly-runit-service/run", service_dir, "run", .{});
|
try patch_map.put("$PREFIX_DIRECTORY", prefix_directory);
|
||||||
},
|
try patch_map.put("$EXECUTABLE_NAME", executable_name);
|
||||||
.Systemd => {
|
|
||||||
const service_path = try std.fs.path.join(allocator, &[_][]const u8{ dest_directory, "/usr/lib/systemd/system" });
|
|
||||||
std.fs.cwd().makePath(service_path) catch {};
|
|
||||||
var service_dir = std.fs.openDirAbsolute(service_path, .{}) catch unreachable;
|
|
||||||
defer service_dir.close();
|
|
||||||
|
|
||||||
try std.fs.cwd().copyFile("res/ly.service", service_dir, "ly.service", .{ .override_mode = 644 });
|
try install_ly(allocator, patch_map, install_config);
|
||||||
},
|
try install_service(allocator, patch_map);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn install_ly(allocator: std.mem.Allocator, install_config: bool) !void {
|
fn install_ly(allocator: std.mem.Allocator, patch_map: PatchMap, install_config: bool) !void {
|
||||||
std.fs.cwd().makePath(data_directory) catch {
|
const ly_config_directory = try std.fs.path.join(allocator, &[_][]const u8{ dest_directory, config_directory, "/ly" });
|
||||||
std.debug.print("warn: {s} already exists as a directory.\n", .{data_directory});
|
|
||||||
|
std.fs.cwd().makePath(ly_config_directory) catch {
|
||||||
|
std.debug.print("warn: {s} already exists as a directory.\n", .{ly_config_directory});
|
||||||
};
|
};
|
||||||
|
|
||||||
const lang_path = try std.fs.path.join(allocator, &[_][]const u8{ data_directory, "/lang" });
|
const ly_lang_path = try std.fs.path.join(allocator, &[_][]const u8{ dest_directory, config_directory, "/ly/lang" });
|
||||||
std.fs.cwd().makePath(lang_path) catch {
|
std.fs.cwd().makePath(ly_lang_path) catch {
|
||||||
std.debug.print("warn: {s} already exists as a directory.\n", .{data_directory});
|
std.debug.print("warn: {s} already exists as a directory.\n", .{ly_lang_path});
|
||||||
};
|
};
|
||||||
|
|
||||||
var current_dir = std.fs.cwd();
|
|
||||||
|
|
||||||
{
|
{
|
||||||
const exe_path = try std.fs.path.join(allocator, &[_][]const u8{ dest_directory, "/usr/bin" });
|
const exe_path = try std.fs.path.join(allocator, &[_][]const u8{ dest_directory, prefix_directory, "/bin" });
|
||||||
if (!std.mem.eql(u8, dest_directory, "")) {
|
std.fs.cwd().makePath(exe_path) catch {
|
||||||
std.fs.cwd().makePath(exe_path) catch {
|
if (!std.mem.eql(u8, dest_directory, "")) {
|
||||||
std.debug.print("warn: {s} already exists as a directory.\n", .{exe_path});
|
std.debug.print("warn: {s} already exists as a directory.\n", .{exe_path});
|
||||||
};
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
var executable_dir = std.fs.openDirAbsolute(exe_path, .{}) catch unreachable;
|
var executable_dir = std.fs.cwd().openDir(exe_path, .{}) catch unreachable;
|
||||||
defer executable_dir.close();
|
defer executable_dir.close();
|
||||||
|
|
||||||
try current_dir.copyFile("zig-out/bin/ly", executable_dir, exe_name, .{});
|
try installFile("zig-out/bin/ly", executable_dir, exe_path, executable_name, .{});
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
var config_dir = std.fs.openDirAbsolute(data_directory, .{}) catch unreachable;
|
var config_dir = std.fs.cwd().openDir(ly_config_directory, .{}) catch unreachable;
|
||||||
defer config_dir.close();
|
defer config_dir.close();
|
||||||
|
|
||||||
if (install_config) {
|
if (install_config) {
|
||||||
try current_dir.copyFile("res/config.ini", config_dir, "config.ini", .{});
|
const patched_config = try patchFile(allocator, "res/config.ini", patch_map);
|
||||||
|
try installText(patched_config, config_dir, ly_config_directory, "config.ini", .{});
|
||||||
}
|
}
|
||||||
try current_dir.copyFile("res/xsetup.sh", config_dir, "xsetup.sh", .{});
|
|
||||||
try current_dir.copyFile("res/wsetup.sh", config_dir, "wsetup.sh", .{});
|
const patched_setup = try patchFile(allocator, "res/setup.sh", patch_map);
|
||||||
|
try installText(patched_setup, config_dir, ly_config_directory, "setup.sh", .{ .mode = 0o755 });
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
var lang_dir = std.fs.openDirAbsolute(lang_path, .{}) catch unreachable;
|
var lang_dir = std.fs.cwd().openDir(ly_lang_path, .{}) catch unreachable;
|
||||||
defer lang_dir.close();
|
defer lang_dir.close();
|
||||||
|
|
||||||
try current_dir.copyFile("res/lang/cat.ini", lang_dir, "cat.ini", .{});
|
try installFile("res/lang/cat.ini", lang_dir, ly_lang_path, "cat.ini", .{});
|
||||||
try current_dir.copyFile("res/lang/cs.ini", lang_dir, "cs.ini", .{});
|
try installFile("res/lang/cs.ini", lang_dir, ly_lang_path, "cs.ini", .{});
|
||||||
try current_dir.copyFile("res/lang/de.ini", lang_dir, "de.ini", .{});
|
try installFile("res/lang/de.ini", lang_dir, ly_lang_path, "de.ini", .{});
|
||||||
try current_dir.copyFile("res/lang/en.ini", lang_dir, "en.ini", .{});
|
try installFile("res/lang/en.ini", lang_dir, ly_lang_path, "en.ini", .{});
|
||||||
try current_dir.copyFile("res/lang/es.ini", lang_dir, "es.ini", .{});
|
try installFile("res/lang/es.ini", lang_dir, ly_lang_path, "es.ini", .{});
|
||||||
try current_dir.copyFile("res/lang/fr.ini", lang_dir, "fr.ini", .{});
|
try installFile("res/lang/fr.ini", lang_dir, ly_lang_path, "fr.ini", .{});
|
||||||
try current_dir.copyFile("res/lang/it.ini", lang_dir, "it.ini", .{});
|
try installFile("res/lang/it.ini", lang_dir, ly_lang_path, "it.ini", .{});
|
||||||
try current_dir.copyFile("res/lang/pl.ini", lang_dir, "pl.ini", .{});
|
try installFile("res/lang/pl.ini", lang_dir, ly_lang_path, "pl.ini", .{});
|
||||||
try current_dir.copyFile("res/lang/pt.ini", lang_dir, "pt.ini", .{});
|
try installFile("res/lang/pt.ini", lang_dir, ly_lang_path, "pt.ini", .{});
|
||||||
try current_dir.copyFile("res/lang/pt_BR.ini", lang_dir, "pt_BR.ini", .{});
|
try installFile("res/lang/pt_BR.ini", lang_dir, ly_lang_path, "pt_BR.ini", .{});
|
||||||
try current_dir.copyFile("res/lang/ro.ini", lang_dir, "ro.ini", .{});
|
try installFile("res/lang/ro.ini", lang_dir, ly_lang_path, "ro.ini", .{});
|
||||||
try current_dir.copyFile("res/lang/ru.ini", lang_dir, "ru.ini", .{});
|
try installFile("res/lang/ru.ini", lang_dir, ly_lang_path, "ru.ini", .{});
|
||||||
try current_dir.copyFile("res/lang/sr.ini", lang_dir, "sr.ini", .{});
|
try installFile("res/lang/sr.ini", lang_dir, ly_lang_path, "sr.ini", .{});
|
||||||
try current_dir.copyFile("res/lang/sv.ini", lang_dir, "sv.ini", .{});
|
try installFile("res/lang/sv.ini", lang_dir, ly_lang_path, "sv.ini", .{});
|
||||||
try current_dir.copyFile("res/lang/tr.ini", lang_dir, "tr.ini", .{});
|
try installFile("res/lang/tr.ini", lang_dir, ly_lang_path, "tr.ini", .{});
|
||||||
try current_dir.copyFile("res/lang/uk.ini", lang_dir, "uk.ini", .{});
|
try installFile("res/lang/uk.ini", lang_dir, ly_lang_path, "uk.ini", .{});
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
const pam_path = try std.fs.path.join(allocator, &[_][]const u8{ dest_directory, "/etc/pam.d" });
|
const pam_path = try std.fs.path.join(allocator, &[_][]const u8{ dest_directory, config_directory, "/pam.d" });
|
||||||
if (!std.mem.eql(u8, dest_directory, "")) {
|
std.fs.cwd().makePath(pam_path) catch {
|
||||||
std.fs.cwd().makePath(pam_path) catch {
|
if (!std.mem.eql(u8, dest_directory, "")) {
|
||||||
std.debug.print("warn: {s} already exists as a directory.\n", .{pam_path});
|
std.debug.print("warn: {s} already exists as a directory.\n", .{pam_path});
|
||||||
};
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
var pam_dir = std.fs.openDirAbsolute(pam_path, .{}) catch unreachable;
|
var pam_dir = std.fs.cwd().openDir(pam_path, .{}) catch unreachable;
|
||||||
defer pam_dir.close();
|
defer pam_dir.close();
|
||||||
|
|
||||||
try current_dir.copyFile("res/pam.d/ly", pam_dir, "ly", .{ .override_mode = 644 });
|
try installFile("res/pam.d/ly", pam_dir, pam_path, "ly", .{ .override_mode = 0o644 });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn uninstallall(step: *std.Build.Step, progress: *std.Progress.Node) !void {
|
fn install_service(allocator: std.mem.Allocator, patch_map: PatchMap) !void {
|
||||||
_ = progress;
|
switch (init_system) {
|
||||||
try std.fs.deleteTreeAbsolute(data_directory);
|
.systemd => {
|
||||||
const allocator = step.owner.allocator;
|
const service_path = try std.fs.path.join(allocator, &[_][]const u8{ dest_directory, prefix_directory, "/lib/systemd/system" });
|
||||||
|
std.fs.cwd().makePath(service_path) catch {};
|
||||||
|
var service_dir = std.fs.cwd().openDir(service_path, .{}) catch unreachable;
|
||||||
|
defer service_dir.close();
|
||||||
|
|
||||||
const exe_path = try std.fs.path.join(allocator, &[_][]const u8{ dest_directory, "/usr/bin/", exe_name });
|
const patched_service = try patchFile(allocator, "res/ly.service", patch_map);
|
||||||
try std.fs.deleteFileAbsolute(exe_path);
|
try installText(patched_service, service_dir, service_path, "ly.service", .{ .mode = 0o644 });
|
||||||
|
},
|
||||||
|
.openrc => {
|
||||||
|
const service_path = try std.fs.path.join(allocator, &[_][]const u8{ dest_directory, config_directory, "/init.d" });
|
||||||
|
std.fs.cwd().makePath(service_path) catch {};
|
||||||
|
var service_dir = std.fs.cwd().openDir(service_path, .{}) catch unreachable;
|
||||||
|
defer service_dir.close();
|
||||||
|
|
||||||
const pam_path = try std.fs.path.join(allocator, &[_][]const u8{ dest_directory, "/etc/pam.d/ly" });
|
const patched_service = try patchFile(allocator, "res/ly-openrc", patch_map);
|
||||||
try std.fs.deleteFileAbsolute(pam_path);
|
try installText(patched_service, service_dir, service_path, executable_name, .{ .mode = 0o755 });
|
||||||
|
},
|
||||||
|
.runit => {
|
||||||
|
const service_path = try std.fs.path.join(allocator, &[_][]const u8{ dest_directory, config_directory, "/sv/ly" });
|
||||||
|
std.fs.cwd().makePath(service_path) catch {};
|
||||||
|
var service_dir = std.fs.cwd().openDir(service_path, .{}) catch unreachable;
|
||||||
|
defer service_dir.close();
|
||||||
|
|
||||||
const systemd_service_path = try std.fs.path.join(allocator, &[_][]const u8{ dest_directory, "/usr/lib/systemd/system/ly.service" });
|
const supervise_path = try std.fs.path.join(allocator, &[_][]const u8{ service_path, "supervise" });
|
||||||
std.fs.deleteFileAbsolute(systemd_service_path) catch {
|
|
||||||
std.debug.print("warn: systemd service not found.\n", .{});
|
|
||||||
};
|
|
||||||
|
|
||||||
const openrc_service_path = try std.fs.path.join(allocator, &[_][]const u8{ dest_directory, "/etc/init.d/ly" });
|
const patched_conf = try patchFile(allocator, "res/ly-runit-service/conf", patch_map);
|
||||||
std.fs.deleteFileAbsolute(openrc_service_path) catch {
|
try installText(patched_conf, service_dir, service_path, "conf", .{});
|
||||||
std.debug.print("warn: openrc service not found.\n", .{});
|
|
||||||
};
|
|
||||||
|
|
||||||
const runit_service_path = try std.fs.path.join(allocator, &[_][]const u8{ dest_directory, "/etc/sv/ly" });
|
try installFile("res/ly-runit-service/finish", service_dir, service_path, "finish", .{ .override_mode = 0o755 });
|
||||||
std.fs.deleteTreeAbsolute(runit_service_path) catch {
|
|
||||||
std.debug.print("warn: runit service not found.\n", .{});
|
const patched_run = try patchFile(allocator, "res/ly-runit-service/run", patch_map);
|
||||||
|
try installText(patched_run, service_dir, service_path, "run", .{ .mode = 0o755 });
|
||||||
|
|
||||||
|
try std.fs.cwd().symLink("/run/runit/supervise.ly", supervise_path, .{});
|
||||||
|
std.debug.print("info: installed symlink /run/runit/supervise.ly\n", .{});
|
||||||
|
},
|
||||||
|
.s6 => {
|
||||||
|
const admin_service_path = try std.fs.path.join(allocator, &[_][]const u8{ dest_directory, config_directory, "/s6/adminsv/default/contents.d" });
|
||||||
|
std.fs.cwd().makePath(admin_service_path) catch {};
|
||||||
|
var admin_service_dir = std.fs.cwd().openDir(admin_service_path, .{}) catch unreachable;
|
||||||
|
defer admin_service_dir.close();
|
||||||
|
|
||||||
|
const file = try admin_service_dir.createFile("ly-srv", .{});
|
||||||
|
file.close();
|
||||||
|
|
||||||
|
const service_path = try std.fs.path.join(allocator, &[_][]const u8{ dest_directory, config_directory, "/s6/sv/ly-srv" });
|
||||||
|
std.fs.cwd().makePath(service_path) catch {};
|
||||||
|
var service_dir = std.fs.cwd().openDir(service_path, .{}) catch unreachable;
|
||||||
|
defer service_dir.close();
|
||||||
|
|
||||||
|
const patched_run = try patchFile(allocator, "res/ly-s6/run", patch_map);
|
||||||
|
try installText(patched_run, service_dir, service_path, "run", .{ .mode = 0o755 });
|
||||||
|
|
||||||
|
try installFile("res/ly-s6/type", service_dir, service_path, "type", .{});
|
||||||
|
},
|
||||||
|
.dinit => {
|
||||||
|
const service_path = try std.fs.path.join(allocator, &[_][]const u8{ dest_directory, config_directory, "/dinit.d" });
|
||||||
|
std.fs.cwd().makePath(service_path) catch {};
|
||||||
|
var service_dir = std.fs.cwd().openDir(service_path, .{}) catch unreachable;
|
||||||
|
defer service_dir.close();
|
||||||
|
|
||||||
|
const patched_service = try patchFile(allocator, "res/ly-dinit", patch_map);
|
||||||
|
try installText(patched_service, service_dir, service_path, "ly", .{});
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn Uninstaller(uninstall_config: bool) type {
|
||||||
|
return struct {
|
||||||
|
pub fn make(step: *std.Build.Step, _: std.Build.Step.MakeOptions) !void {
|
||||||
|
const allocator = step.owner.allocator;
|
||||||
|
|
||||||
|
if (uninstall_config) {
|
||||||
|
try deleteTree(allocator, config_directory, "/ly", "ly config directory not found");
|
||||||
|
}
|
||||||
|
|
||||||
|
const exe_path = try std.fs.path.join(allocator, &[_][]const u8{ prefix_directory, "/bin/", executable_name });
|
||||||
|
var success = true;
|
||||||
|
std.fs.cwd().deleteFile(exe_path) catch {
|
||||||
|
std.debug.print("warn: ly executable not found\n", .{});
|
||||||
|
success = false;
|
||||||
|
};
|
||||||
|
if (success) std.debug.print("info: deleted {s}\n", .{exe_path});
|
||||||
|
|
||||||
|
try deleteFile(allocator, config_directory, "/pam.d/ly", "ly pam file not found");
|
||||||
|
|
||||||
|
switch (init_system) {
|
||||||
|
.systemd => try deleteFile(allocator, prefix_directory, "/lib/systemd/system/ly.service", "systemd service not found"),
|
||||||
|
.openrc => try deleteFile(allocator, config_directory, "/init.d/ly", "openrc service not found"),
|
||||||
|
.runit => try deleteTree(allocator, config_directory, "/sv/ly", "runit service not found"),
|
||||||
|
.s6 => {
|
||||||
|
try deleteTree(allocator, config_directory, "/s6/sv/ly-srv", "s6 service not found");
|
||||||
|
try deleteFile(allocator, config_directory, "/s6/adminsv/default/contents.d/ly-srv", "s6 admin service not found");
|
||||||
|
},
|
||||||
|
.dinit => try deleteFile(allocator, config_directory, "/dinit.d/ly", "dinit service not found"),
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -296,3 +361,90 @@ fn getVersionStr(b: *std.Build, name: []const u8, version: std.SemanticVersion)
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn installFile(
|
||||||
|
source_file: []const u8,
|
||||||
|
destination_directory: std.fs.Dir,
|
||||||
|
destination_directory_path: []const u8,
|
||||||
|
destination_file: []const u8,
|
||||||
|
options: std.fs.Dir.CopyFileOptions,
|
||||||
|
) !void {
|
||||||
|
try std.fs.cwd().copyFile(source_file, destination_directory, destination_file, options);
|
||||||
|
std.debug.print("info: installed {s}/{s}\n", .{ destination_directory_path, destination_file });
|
||||||
|
}
|
||||||
|
|
||||||
|
fn patchFile(allocator: std.mem.Allocator, source_file: []const u8, patch_map: PatchMap) ![]const u8 {
|
||||||
|
var file = try std.fs.cwd().openFile(source_file, .{});
|
||||||
|
defer file.close();
|
||||||
|
|
||||||
|
const reader = file.reader();
|
||||||
|
var text = try reader.readAllAlloc(allocator, std.math.maxInt(u16));
|
||||||
|
|
||||||
|
var iterator = patch_map.iterator();
|
||||||
|
while (iterator.next()) |kv| {
|
||||||
|
const new_text = try std.mem.replaceOwned(u8, allocator, text, kv.key_ptr.*, kv.value_ptr.*);
|
||||||
|
allocator.free(text);
|
||||||
|
text = new_text;
|
||||||
|
}
|
||||||
|
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn installText(
|
||||||
|
text: []const u8,
|
||||||
|
destination_directory: std.fs.Dir,
|
||||||
|
destination_directory_path: []const u8,
|
||||||
|
destination_file: []const u8,
|
||||||
|
options: std.fs.File.CreateFlags,
|
||||||
|
) !void {
|
||||||
|
var file = try destination_directory.createFile(destination_file, options);
|
||||||
|
defer file.close();
|
||||||
|
|
||||||
|
const writer = file.writer();
|
||||||
|
try writer.writeAll(text);
|
||||||
|
|
||||||
|
std.debug.print("info: installed {s}/{s}\n", .{ destination_directory_path, destination_file });
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deleteFile(
|
||||||
|
allocator: std.mem.Allocator,
|
||||||
|
prefix: []const u8,
|
||||||
|
file: []const u8,
|
||||||
|
warning: []const u8,
|
||||||
|
) !void {
|
||||||
|
const path = try std.fs.path.join(allocator, &[_][]const u8{ dest_directory, prefix, file });
|
||||||
|
|
||||||
|
std.fs.cwd().deleteFile(path) catch |err| {
|
||||||
|
if (err == error.FileNotFound) {
|
||||||
|
std.debug.print("warn: {s}\n", .{warning});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
return err;
|
||||||
|
};
|
||||||
|
|
||||||
|
std.debug.print("info: deleted {s}\n", .{path});
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deleteTree(
|
||||||
|
allocator: std.mem.Allocator,
|
||||||
|
prefix: []const u8,
|
||||||
|
directory: []const u8,
|
||||||
|
warning: []const u8,
|
||||||
|
) !void {
|
||||||
|
const path = try std.fs.path.join(allocator, &[_][]const u8{ dest_directory, prefix, directory });
|
||||||
|
|
||||||
|
var dir = std.fs.cwd().openDir(path, .{}) catch |err| {
|
||||||
|
if (err == error.FileNotFound) {
|
||||||
|
std.debug.print("warn: {s}\n", .{warning});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
return err;
|
||||||
|
};
|
||||||
|
dir.close();
|
||||||
|
|
||||||
|
try std.fs.cwd().deleteTree(path);
|
||||||
|
|
||||||
|
std.debug.print("info: deleted {s}\n", .{path});
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,15 +1,16 @@
|
|||||||
.{
|
.{
|
||||||
.name = "ly",
|
.name = .ly,
|
||||||
.version = "1.0.0",
|
.version = "1.1.2",
|
||||||
.minimum_zig_version = "0.12.0",
|
.fingerprint = 0xa148ffcc5dc2cb59,
|
||||||
|
.minimum_zig_version = "0.14.0",
|
||||||
.dependencies = .{
|
.dependencies = .{
|
||||||
.clap = .{
|
.clap = .{
|
||||||
.url = "https://github.com/Hejsil/zig-clap/archive/8c98e6404b22aafc0184e999d8f068b81cc22fa1.tar.gz",
|
.url = "https://github.com/Hejsil/zig-clap/archive/refs/tags/0.10.0.tar.gz",
|
||||||
.hash = "122014e73fd712190e109950837b97f6143f02d7e2b6986e1db70b6f4aadb5ba6a0d",
|
.hash = "clap-0.10.0-oBajB434AQBDh-Ei3YtoKIRxZacVPF1iSwp3IX_ZB8f0",
|
||||||
},
|
},
|
||||||
.zigini = .{
|
.zigini = .{
|
||||||
.url = "https://github.com/Kawaii-Ash/zigini/archive/ce1f322482099db058f5d9fdd05fbfa255d79723.tar.gz",
|
.url = "https://github.com/Kawaii-Ash/zigini/archive/2ed3d417f17fab5b0ee8cad8a63c6d62d7ac1042.tar.gz",
|
||||||
.hash = "1220e7a99793a0430e0a7c0b938cb3c98321035bc297e21cd0e2413cf740b4923b9f",
|
.hash = "zigini-0.3.1-BSkB7XJGAAB2E-sKyzhTaQCBlYBL8yqzE4E_jmSY99sC",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
.paths = .{""},
|
.paths = .{""},
|
||||||
|
|||||||
52
changelog.md
52
changelog.md
@@ -1,52 +0,0 @@
|
|||||||
# Zig Rewrite (Version 1.0.0)
|
|
||||||
|
|
||||||
## Config Options
|
|
||||||
|
|
||||||
res/config.ini contains all of the available config options and their default values.
|
|
||||||
|
|
||||||
### Additions
|
|
||||||
|
|
||||||
+ `border_fg` has been introduced to change the color of the borders.
|
|
||||||
+ `term_restore_cursor_cmd` should restore the cursor to it's usual state.
|
|
||||||
+ `vi_mode` to enable vi keybindings.
|
|
||||||
+ `sleep_key` and `sleep_cmd`.
|
|
||||||
+ `numlock` to set numlock on startup.
|
|
||||||
+ `initial_info_text` allows changing the initial text on the info line.
|
|
||||||
+ `box_title` to display a title at the top of the main box
|
|
||||||
|
|
||||||
Note: `sleep_cmd` is unset by default, meaning it's hidden and has no effect.
|
|
||||||
|
|
||||||
### Changes
|
|
||||||
|
|
||||||
+ xinitrc can be set to null to hide it.
|
|
||||||
+ `blank_password` has been renamed to `clear_password`.
|
|
||||||
+ `save_file` has been deprecated and will be removed in a future version.
|
|
||||||
|
|
||||||
### Removals
|
|
||||||
|
|
||||||
+ `wayland_specifier` has been removed.
|
|
||||||
|
|
||||||
## Save File
|
|
||||||
|
|
||||||
The save file is now in .ini format and stored in the same directory as the config.
|
|
||||||
Older save files will be migrated to the new format.
|
|
||||||
|
|
||||||
Example:
|
|
||||||
|
|
||||||
```ini
|
|
||||||
user = ash
|
|
||||||
session_index = 0
|
|
||||||
```
|
|
||||||
|
|
||||||
## Misc
|
|
||||||
|
|
||||||
+ Display server name added next to selected session.
|
|
||||||
+ getty@tty2 has been added as a conflict in res/ly.service, so if it is running, ly should still be able to start.
|
|
||||||
+ `XDG_CURRENT_DESKTOP` is now set by ly.
|
|
||||||
+ LANG is no longer set by ly.
|
|
||||||
+ X Server PID is fetched from /tmp/X{d}.lock to be able to kill the process since it detaches.
|
|
||||||
+ Non .desktop files are now ignored in sessions directory.
|
|
||||||
+ PAM auth is now done in a child process. (Fixes some issues with logging out and back in).
|
|
||||||
+ When ly receives SIGTERM, the terminal is now cleared and existing child processes are cleaned up.
|
|
||||||
+ Shift+Tab now focuses previous input.
|
|
||||||
+ Display text in the info line when authenticating.
|
|
||||||
1555
include/termbox2.h
1555
include/termbox2.h
File diff suppressed because it is too large
Load Diff
183
readme.md
183
readme.md
@@ -1,21 +1,22 @@
|
|||||||
|
|
||||||
# Ly - a TUI display manager
|
# Ly - a TUI display manager
|
||||||

|
|
||||||
|
## Development is now continuing on [Codeberg](https://codeberg.org/AnErrupTion/ly), with the [GitHub](https://github.com/fairyglade/ly) repository becoming a mirror. Issues & pull requests on GitHub will be ignored from now on.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
Ly is a lightweight TUI (ncurses-like) display manager for Linux and BSD.
|
Ly is a lightweight TUI (ncurses-like) display manager for Linux and BSD.
|
||||||
|
|
||||||
## Dependencies
|
## Dependencies
|
||||||
- Compile-time:
|
- Compile-time:
|
||||||
- zig 0.12.0
|
- zig 0.14.0
|
||||||
- a C standard library
|
- libc
|
||||||
- pam
|
- pam
|
||||||
- xcb
|
- xcb (optional, required by default; needed for X11 support)
|
||||||
- Runtime (with default config):
|
- Runtime (with default config):
|
||||||
- xorg
|
- xorg
|
||||||
- xorg-xauth
|
- xorg-xauth
|
||||||
- mcookie
|
|
||||||
- tput
|
|
||||||
- shutdown
|
- shutdown
|
||||||
|
- brightnessctl
|
||||||
|
|
||||||
### Debian
|
### Debian
|
||||||
```
|
```
|
||||||
@@ -27,34 +28,15 @@ Ly is a lightweight TUI (ncurses-like) display manager for Linux and BSD.
|
|||||||
It is recommended to add a rule for Ly as it currently does not ship one.
|
It is recommended to add a rule for Ly as it currently does not ship one.
|
||||||
|
|
||||||
```
|
```
|
||||||
# dnf install kernel-devel pam-devel libxcb-devel
|
# dnf install kernel-devel pam-devel libxcb-devel zig
|
||||||
```
|
```
|
||||||
|
|
||||||
## Support
|
## Support
|
||||||
The following desktop environments were tested with success:
|
The following desktop environments were tested with success:
|
||||||
- awesome
|
|
||||||
- bspwm
|
[Wayland Environments](#supported-wayland-environments)
|
||||||
- budgie
|
|
||||||
- cinnamon
|
[X11 Environments](#supported-x11-environments)
|
||||||
- deepin
|
|
||||||
- dwl
|
|
||||||
- dwm
|
|
||||||
- enlightenment
|
|
||||||
- gnome
|
|
||||||
- i3
|
|
||||||
- kde
|
|
||||||
- labwc
|
|
||||||
- lxde
|
|
||||||
- lxqt
|
|
||||||
- mate
|
|
||||||
- maxx
|
|
||||||
- pantheon
|
|
||||||
- qtile
|
|
||||||
- spectrwm
|
|
||||||
- sway
|
|
||||||
- windowmaker
|
|
||||||
- xfce
|
|
||||||
- xmonad
|
|
||||||
|
|
||||||
Ly should work with any X desktop environment, and provides
|
Ly should work with any X desktop environment, and provides
|
||||||
basic wayland support (sway works very well, for example).
|
basic wayland support (sway works very well, for example).
|
||||||
@@ -68,7 +50,7 @@ changing the source code won't be necessary :)
|
|||||||
## Cloning and Compiling
|
## Cloning and Compiling
|
||||||
Clone the repository
|
Clone the repository
|
||||||
```
|
```
|
||||||
$ git clone https://github.com/fairyglade/ly
|
$ git clone https://codeberg.org/AnErrupTion/ly
|
||||||
```
|
```
|
||||||
|
|
||||||
Change the directory to ly
|
Change the directory to ly
|
||||||
@@ -82,14 +64,26 @@ $ zig build
|
|||||||
```
|
```
|
||||||
|
|
||||||
Test in the configured tty (tty2 by default)
|
Test in the configured tty (tty2 by default)
|
||||||
or a terminal emulator (but desktop environments won't start)
|
or a terminal emulator (but authentication won't work)
|
||||||
```
|
```
|
||||||
# zig build run
|
$ zig build run
|
||||||
```
|
```
|
||||||
|
|
||||||
Install Ly and the provided systemd service file
|
**Important**: Running Ly in a terminal emulator as root is *not* recommended. If you
|
||||||
|
want to properly test Ly, please enable its service (as described below) and reboot
|
||||||
|
your machine.
|
||||||
|
|
||||||
|
Install Ly for systemd-based systems (the default)
|
||||||
```
|
```
|
||||||
# zig build installsystemd
|
# zig build installexe
|
||||||
|
```
|
||||||
|
|
||||||
|
Instead of DISPLAY_MANAGER you need to add your DM:
|
||||||
|
- gdm.service
|
||||||
|
- sddm.service
|
||||||
|
- lightdm.service
|
||||||
|
```
|
||||||
|
# systemctl disable DISPLAY_MANAGER
|
||||||
```
|
```
|
||||||
|
|
||||||
Enable the service
|
Enable the service
|
||||||
@@ -104,13 +98,13 @@ disable getty on Ly's tty to prevent "login" from spawning on top of it
|
|||||||
```
|
```
|
||||||
|
|
||||||
### OpenRC
|
### OpenRC
|
||||||
**NOTE**: On Gentoo, Ly will disable the `display-manager-init` service in order to run.
|
**NOTE 1**: On Gentoo, Ly will disable the `display-manager-init` service in order to run.
|
||||||
|
|
||||||
Clone, compile and test.
|
Clone, compile and test.
|
||||||
|
|
||||||
Install Ly and the provided OpenRC service
|
Install Ly and the provided OpenRC service
|
||||||
```
|
```
|
||||||
# zig build installopenrc
|
# zig build installexe -Dinit_system=openrc
|
||||||
```
|
```
|
||||||
|
|
||||||
Enable the service
|
Enable the service
|
||||||
@@ -126,9 +120,11 @@ then you have to disable getty, so it doesn't respawn on top of ly
|
|||||||
# rc-update del agetty.tty2
|
# rc-update del agetty.tty2
|
||||||
```
|
```
|
||||||
|
|
||||||
|
**NOTE 2**: To avoid a console spawning on top on Ly, comment out the appropriate line from /etc/inittab (default is 2).
|
||||||
|
|
||||||
### runit
|
### runit
|
||||||
```
|
```
|
||||||
# zig build installrunit
|
# zig build installexe -Dinit_system=runit
|
||||||
# ln -s /etc/sv/ly /var/service/
|
# ln -s /etc/sv/ly /var/service/
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -148,24 +144,68 @@ you should disable the agetty-tty2 service like this:
|
|||||||
# rm /var/service/agetty-tty2
|
# rm /var/service/agetty-tty2
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### s6
|
||||||
|
```
|
||||||
|
# zig build installexe -Dinit_system=s6
|
||||||
|
```
|
||||||
|
|
||||||
|
Then, edit `/etc/s6/config/ttyX.conf` and set `SPAWN="no"`, where X is the TTY ID (e.g. `2`).
|
||||||
|
|
||||||
|
Finally, enable the service:
|
||||||
|
|
||||||
|
```
|
||||||
|
# s6-service add default ly-srv
|
||||||
|
# s6-db-reload
|
||||||
|
# s6-rc -u change ly-srv
|
||||||
|
```
|
||||||
|
|
||||||
|
### dinit
|
||||||
|
```
|
||||||
|
# zig build installexe -Dinit_system=dinit
|
||||||
|
# dinitctl enable ly
|
||||||
|
```
|
||||||
|
|
||||||
|
In addition to the steps above, you will also have to keep a TTY free within `/etc/dinit.d/config/console.conf`.
|
||||||
|
|
||||||
|
To do that, change `ACTIVE_CONSOLES` so that the tty that ly should use in `/etc/ly/config.ini` is free.
|
||||||
|
|
||||||
### Updating
|
### Updating
|
||||||
You can also install Ly without copying the system service and the configuration file. That's
|
You can also install Ly without overrding the current configuration file. That's called
|
||||||
called *updating*. To update, simply run:
|
*updating*. To update, simply run:
|
||||||
|
|
||||||
```
|
```
|
||||||
# zig build installnoconf
|
# zig build installnoconf
|
||||||
```
|
```
|
||||||
|
|
||||||
If you want to also copy the default config file (but still not the system service), run:
|
You can, of course, still select the init system of your choice when using this command.
|
||||||
|
|
||||||
```
|
|
||||||
# zig build installexe
|
|
||||||
```
|
|
||||||
|
|
||||||
## Arch Linux Installation
|
## Arch Linux Installation
|
||||||
You can install ly from the [`[extra]` repos](https://archlinux.org/packages/extra/x86_64/ly/):
|
You can install ly from the [`[extra]` repos](https://archlinux.org/packages/extra/x86_64/ly/):
|
||||||
```
|
```
|
||||||
$ sudo pacman -S ly
|
# pacman -S ly
|
||||||
|
```
|
||||||
|
|
||||||
|
## Gentoo Installation
|
||||||
|
You can install ly from the GURU repository:
|
||||||
|
|
||||||
|
Note: If the package is masked, you may need to unmask it using ~amd64 keyword:
|
||||||
|
```bash
|
||||||
|
# echo 'x11-misc/ly ~amd64' >> /etc/portage/package.accept_keywords
|
||||||
|
```
|
||||||
|
|
||||||
|
1. Enable the GURU repository:
|
||||||
|
```bash
|
||||||
|
# eselect repository enable guru
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Sync the GURU repository:
|
||||||
|
```bash
|
||||||
|
# emaint sync -r guru
|
||||||
|
```
|
||||||
|
|
||||||
|
3. Install ly from source:
|
||||||
|
```bash
|
||||||
|
# emerge --ask x11-misc/ly
|
||||||
```
|
```
|
||||||
|
|
||||||
## Configuration
|
## Configuration
|
||||||
@@ -189,19 +229,46 @@ On Arch Linux, the example .xinitrc (/etc/X11/xinit/xinitrc) starts like this:
|
|||||||
```
|
```
|
||||||
|
|
||||||
## Tips
|
## Tips
|
||||||
The numlock and capslock state is printed in the top-right corner.
|
- The numlock and capslock state is printed in the top-right corner.
|
||||||
Use the F1 and F2 keys to respectively shutdown and reboot.
|
- Use the F1 and F2 keys to respectively shutdown and reboot.
|
||||||
Take a look at your .xsession if X doesn't start, as it can interfere
|
- Take a look at your .xsession if X doesn't start, as it can interfere
|
||||||
(this file is launched with X to configure the display properly).
|
(this file is launched with X to configure the display properly).
|
||||||
|
|
||||||
|
## Supported Wayland Environments
|
||||||
|
- budgie
|
||||||
|
- cosmic
|
||||||
|
- deepin
|
||||||
|
- enlightenment
|
||||||
|
- gnome
|
||||||
|
- hyprland
|
||||||
|
- kde
|
||||||
|
- labwc
|
||||||
|
- niri
|
||||||
|
- pantheon
|
||||||
|
- sway
|
||||||
|
- weston
|
||||||
|
|
||||||
|
## Supported X11 Environments
|
||||||
|
- awesome
|
||||||
|
- bspwm
|
||||||
|
- budgie
|
||||||
|
- cinnamon
|
||||||
|
- dwm
|
||||||
|
- enlightenment
|
||||||
|
- gnome
|
||||||
|
- kde
|
||||||
|
- leftwm
|
||||||
|
- lxde
|
||||||
|
- mate
|
||||||
|
- maxx
|
||||||
|
- pantheon
|
||||||
|
- qwm
|
||||||
|
- spectrwm
|
||||||
|
- windowmaker
|
||||||
|
- xfce
|
||||||
|
- xmonad
|
||||||
|
|
||||||
## PSX DOOM fire animation
|
|
||||||
To enable the famous PSX DOOM fire described by [Fabien Sanglard](http://fabiensanglard.net/doom_fire_psx/index.html),
|
|
||||||
just uncomment `animate = true` in `/etc/ly/config.ini`. You may also
|
|
||||||
disable the main box borders with `hide_borders = true`.
|
|
||||||
|
|
||||||
## Additional Information
|
## Additional Information
|
||||||
The name "Ly" is a tribute to the fairy from the game Rayman.
|
The name "Ly" is a tribute to the fairy from the game Rayman.
|
||||||
Ly was tested by oxodao, who is some seriously awesome dude.
|
Ly was tested by oxodao, who is some seriously awesome dude.
|
||||||
|
|
||||||
## Gentoo (OpenRC) installation tip
|
|
||||||
To avoid a console spawning on top on Ly, comment out the appropriate line from /etc/inittab (default is 2).
|
|
||||||
|
|||||||
298
res/config.ini
298
res/config.ini
@@ -1,126 +1,167 @@
|
|||||||
|
# Ly supports 24-bit true color with styling, which means each color is a 32-bit value.
|
||||||
|
# The format is 0xSSRRGGBB, where SS is the styling, RR is red, GG is green, and BB is blue.
|
||||||
|
# Here are the possible styling options:
|
||||||
|
#define TB_BOLD 0x01000000
|
||||||
|
#define TB_UNDERLINE 0x02000000
|
||||||
|
#define TB_REVERSE 0x04000000
|
||||||
|
#define TB_ITALIC 0x08000000
|
||||||
|
#define TB_BLINK 0x10000000
|
||||||
|
#define TB_HI_BLACK 0x20000000
|
||||||
|
#define TB_BRIGHT 0x40000000
|
||||||
|
#define TB_DIM 0x80000000
|
||||||
|
# Programmatically, you'd apply them using the bitwise OR operator (|), but because Ly's
|
||||||
|
# configuration doesn't support using it, you have to manually compute the color value.
|
||||||
|
# Note that, if you want to use the default color value of the terminal, you can use the
|
||||||
|
# special value 0x00000000. This means that, if you want to use black, you *must* use
|
||||||
|
# the styling option TB_HI_BLACK (the RGB values are ignored when using this option).
|
||||||
|
|
||||||
|
# Allow empty password or not when authenticating
|
||||||
|
allow_empty_password = true
|
||||||
|
|
||||||
# The active animation
|
# The active animation
|
||||||
# none -> Nothing (default)
|
# none -> Nothing
|
||||||
# doom -> PSX DOOM fire
|
# doom -> PSX DOOM fire
|
||||||
# matrix -> CMatrix
|
# matrix -> CMatrix
|
||||||
|
# colormix -> Color mixing shader
|
||||||
animation = none
|
animation = none
|
||||||
|
|
||||||
# Format string for clock in top right corner (see strftime specification). Example: %c
|
# Stop the animation after some time
|
||||||
clock = null
|
# 0 -> Run forever
|
||||||
|
# 1..2e12 -> Stop the animation after this many seconds
|
||||||
# Enable/disable big clock
|
animation_timeout_sec = 0
|
||||||
bigclock = false
|
|
||||||
|
|
||||||
# The character used to mask the password
|
# The character used to mask the password
|
||||||
|
# You can either type it directly as a UTF-8 character (like *), or use a UTF-32
|
||||||
|
# codepoint (for example 0x2022 for a bullet point)
|
||||||
|
# If null, the password will be hidden
|
||||||
|
# Note: you can use a # by escaping it like so: \#
|
||||||
asterisk = *
|
asterisk = *
|
||||||
|
|
||||||
# Erase password input on failure
|
# The number of failed authentications before a special animation is played... ;)
|
||||||
clear_password = false
|
auth_fails = 10
|
||||||
|
|
||||||
# Enable vi keybindings
|
|
||||||
vi_mode = false
|
|
||||||
|
|
||||||
# The `fg` and `bg` color settings take a digit 0-8 corresponding to:
|
|
||||||
#define TB_DEFAULT 0x00
|
|
||||||
#define TB_BLACK 0x01
|
|
||||||
#define TB_RED 0x02
|
|
||||||
#define TB_GREEN 0x03
|
|
||||||
#define TB_YELLOW 0x04
|
|
||||||
#define TB_BLUE 0x05
|
|
||||||
#define TB_MAGENTA 0x06
|
|
||||||
#define TB_CYAN 0x07
|
|
||||||
#define TB_WHITE 0x08
|
|
||||||
#
|
|
||||||
# Setting both to zero makes `bg` black and `fg` white. To set the actual color palette you are encouraged to use another tool
|
|
||||||
# such as [mkinitcpio-colors](https://github.com/evanpurkhiser/mkinitcpio-colors). Note that the color palette defined with
|
|
||||||
# `mkinitcpio-colors` takes 16 colors (0-15), only values 0-8 are valid for `ly` config and these values do not correspond
|
|
||||||
# exactly. For instance, in defining palettes with `mkinitcpio-colors` the order is black, dark red, dark green, brown, dark
|
|
||||||
# blue, dark purple, dark cyan, light gray, dark gray, bright red, bright green, yellow, bright blue, bright purple, bright
|
|
||||||
# cyan, and white, indexed in that order 0 through 15. For example, the color defined for white (indexed at 15 in the mkinitcpio
|
|
||||||
# config) will be used by `ly` for `fg = 8`.
|
|
||||||
|
|
||||||
# Background color id
|
# Background color id
|
||||||
bg = 0
|
bg = 0x00000000
|
||||||
|
|
||||||
# Foreground color id
|
# Change the state and language of the big clock
|
||||||
fg = 8
|
# none -> Disabled (default)
|
||||||
|
# en -> English
|
||||||
# Border color
|
# fa -> Farsi
|
||||||
border_fg = 8
|
bigclock = none
|
||||||
|
|
||||||
# Title to show at the top of the main box
|
|
||||||
box_title = null
|
|
||||||
|
|
||||||
# Initial text to show on the info line (Defaults to hostname)
|
|
||||||
initial_info_text = null
|
|
||||||
|
|
||||||
# Blank main box background
|
# Blank main box background
|
||||||
# Setting to false will make it transparent
|
# Setting to false will make it transparent
|
||||||
blank_box = true
|
blank_box = true
|
||||||
|
|
||||||
# Remove main box borders
|
# Border foreground color id
|
||||||
hide_borders = false
|
border_fg = 0x00FFFFFF
|
||||||
|
|
||||||
# Main box margins
|
# Title to show at the top of the main box
|
||||||
margin_box_h = 2
|
# If set to null, none will be shown
|
||||||
margin_box_v = 1
|
box_title = null
|
||||||
|
|
||||||
# Input boxes length
|
# Brightness increase command
|
||||||
input_len = 34
|
brightness_down_cmd = $PREFIX_DIRECTORY/bin/brightnessctl -q s 10%-
|
||||||
|
|
||||||
# Max input sizes
|
# Brightness decrease key, or null to disable
|
||||||
max_desktop_len = 100
|
brightness_down_key = F5
|
||||||
max_login_len = 255
|
|
||||||
max_password_len = 255
|
|
||||||
|
|
||||||
# Input box active by default on startup
|
# Brightness increase command
|
||||||
# Available inputs: session, login, password
|
brightness_up_cmd = $PREFIX_DIRECTORY/bin/brightnessctl -q s +10%
|
||||||
default_input = login
|
|
||||||
|
|
||||||
# Load the saved desktop and username
|
# Brightness increase key, or null to disable
|
||||||
load = true
|
brightness_up_key = F6
|
||||||
|
|
||||||
# Save the current desktop and login as defaults
|
# Erase password input on failure
|
||||||
save = true
|
clear_password = false
|
||||||
|
|
||||||
# Deprecated - Will be removed in a future version
|
# Format string for clock in top right corner (see strftime specification). Example: %c
|
||||||
# New save files are now loaded from the same directory as the config
|
# If null, the clock won't be shown
|
||||||
# Currently used to migrate old save files to the new version
|
clock = null
|
||||||
# File in which to save and load the default desktop and login
|
|
||||||
save_file = /etc/ly/save
|
|
||||||
|
|
||||||
# Remove power management command hints
|
# CMatrix animation foreground color id
|
||||||
hide_key_hints = false
|
cmatrix_fg = 0x0000FF00
|
||||||
|
|
||||||
# Specifies the key used for shutdown (F1-F12)
|
# CMatrix animation minimum codepoint. It uses a 16-bit integer
|
||||||
shutdown_key = F1
|
# For Japanese characters for example, you can use 0x3000 here
|
||||||
|
cmatrix_min_codepoint = 0x21
|
||||||
|
|
||||||
# Specifies the key used for restart (F1-F12)
|
# CMatrix animation maximum codepoint. It uses a 16-bit integer
|
||||||
restart_key = F2
|
# For Japanese characters for example, you can use 0x30FF here
|
||||||
|
cmatrix_max_codepoint = 0x7B
|
||||||
|
|
||||||
# Specifies the key used for sleep (F1-F12)
|
# Color mixing animation first color id
|
||||||
sleep_key = F3
|
colormix_col1 = 0x00FF0000
|
||||||
|
|
||||||
# Command executed when pressing shutdown_key
|
# Color mixing animation second color id
|
||||||
shutdown_cmd = /sbin/shutdown -a now
|
colormix_col2 = 0x000000FF
|
||||||
|
|
||||||
# Command executed when pressing restart_key
|
# Color mixing animation third color id
|
||||||
restart_cmd = /sbin/shutdown -r now
|
colormix_col3 = 0x20000000
|
||||||
|
|
||||||
# Command executed when pressing sleep key (can be null)
|
|
||||||
sleep_cmd = null
|
|
||||||
|
|
||||||
# Active language
|
|
||||||
# Available languages are found in /etc/ly/lang/
|
|
||||||
lang = en
|
|
||||||
|
|
||||||
# TTY in use
|
|
||||||
tty = 2
|
|
||||||
|
|
||||||
# Console path
|
# Console path
|
||||||
console_dev = /dev/console
|
console_dev = /dev/console
|
||||||
|
|
||||||
# Default path. If null, ly doesn't set a path.
|
# Input box active by default on startup
|
||||||
path = /sbin:/bin:/usr/local/sbin:/usr/local/bin:/usr/bin:/usr/sbin
|
# Available inputs: info_line, session, login, password
|
||||||
|
default_input = login
|
||||||
|
|
||||||
|
# DOOM animation top color (low intensity flames)
|
||||||
|
doom_top_color = 0x00FF0000
|
||||||
|
|
||||||
|
# DOOM animation middle color (medium intensity flames)
|
||||||
|
doom_middle_color = 0x00FFFF00
|
||||||
|
|
||||||
|
# DOOM animation bottom color (high intensity flames)
|
||||||
|
doom_bottom_color = 0x00FFFFFF
|
||||||
|
|
||||||
|
# Error background color id
|
||||||
|
error_bg = 0x00000000
|
||||||
|
|
||||||
|
# Error foreground color id
|
||||||
|
# Default is red and bold
|
||||||
|
error_fg = 0x01FF0000
|
||||||
|
|
||||||
|
# Foreground color id
|
||||||
|
fg = 0x00FFFFFF
|
||||||
|
|
||||||
|
# Remove main box borders
|
||||||
|
hide_borders = false
|
||||||
|
|
||||||
|
# Remove power management command hints
|
||||||
|
hide_key_hints = false
|
||||||
|
|
||||||
|
# Initial text to show on the info line
|
||||||
|
# If set to null, the info line defaults to the hostname
|
||||||
|
initial_info_text = null
|
||||||
|
|
||||||
|
# Input boxes length
|
||||||
|
input_len = 34
|
||||||
|
|
||||||
|
# Active language
|
||||||
|
# Available languages are found in $CONFIG_DIRECTORY/ly/lang/
|
||||||
|
lang = en
|
||||||
|
|
||||||
|
# Load the saved desktop and username
|
||||||
|
load = true
|
||||||
|
|
||||||
|
# Command executed when logging in
|
||||||
|
# If null, no command will be executed
|
||||||
|
# Important: the code itself must end with `exec "$@"` in order to launch the session!
|
||||||
|
# You can also set environment variables in there, they'll persist until logout
|
||||||
|
login_cmd = null
|
||||||
|
|
||||||
|
# Command executed when logging out
|
||||||
|
# If null, no command will be executed
|
||||||
|
# Important: the session will already be terminated when this command is executed, so
|
||||||
|
# no need to add `exec "$@"` at the end
|
||||||
|
logout_cmd = null
|
||||||
|
|
||||||
|
# Main box horizontal margin
|
||||||
|
margin_box_h = 2
|
||||||
|
|
||||||
|
# Main box vertical margin
|
||||||
|
margin_box_v = 1
|
||||||
|
|
||||||
# Event timeout in milliseconds
|
# Event timeout in milliseconds
|
||||||
min_refresh_delta = 5
|
min_refresh_delta = 5
|
||||||
@@ -128,35 +169,74 @@ min_refresh_delta = 5
|
|||||||
# Set numlock on/off at startup
|
# Set numlock on/off at startup
|
||||||
numlock = false
|
numlock = false
|
||||||
|
|
||||||
|
# Default path
|
||||||
|
# If null, ly doesn't set a path
|
||||||
|
path = /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
|
||||||
|
|
||||||
|
# Command executed when pressing restart_key
|
||||||
|
restart_cmd = /sbin/shutdown -r now
|
||||||
|
|
||||||
|
# Specifies the key used for restart (F1-F12)
|
||||||
|
restart_key = F2
|
||||||
|
|
||||||
|
# Save the current desktop and login as defaults
|
||||||
|
save = true
|
||||||
|
|
||||||
# Service name (set to ly to use the provided pam config file)
|
# Service name (set to ly to use the provided pam config file)
|
||||||
service_name = ly
|
service_name = ly
|
||||||
|
|
||||||
# Terminal reset command (tput is faster)
|
# Session log file path
|
||||||
term_reset_cmd = /usr/bin/tput reset
|
# This will contain stdout and stderr of Wayland sessions
|
||||||
|
# By default it's saved in the user's home directory
|
||||||
|
# Important: due to technical limitations, X11 and shell sessions aren't supported, which
|
||||||
|
# means you won't get any logs from those sessions
|
||||||
|
session_log = ly-session.log
|
||||||
|
|
||||||
# Terminal restore cursor command
|
# Setup command
|
||||||
term_restore_cursor_cmd = /usr/bin/tput cnorm
|
setup_cmd = $CONFIG_DIRECTORY/ly/setup.sh
|
||||||
|
|
||||||
# Cookie generator
|
# Command executed when pressing shutdown_key
|
||||||
mcookie_cmd = /usr/bin/mcookie
|
shutdown_cmd = /sbin/shutdown -a now
|
||||||
|
|
||||||
# Wayland setup command
|
# Specifies the key used for shutdown (F1-F12)
|
||||||
wayland_cmd = /etc/ly/wsetup.sh
|
shutdown_key = F1
|
||||||
|
|
||||||
|
# Command executed when pressing sleep key (can be null)
|
||||||
|
sleep_cmd = null
|
||||||
|
|
||||||
|
# Specifies the key used for sleep (F1-F12)
|
||||||
|
sleep_key = F3
|
||||||
|
|
||||||
|
# Center the session name.
|
||||||
|
text_in_center = false
|
||||||
|
|
||||||
|
# TTY in use
|
||||||
|
tty = $DEFAULT_TTY
|
||||||
|
|
||||||
|
# Default vi mode
|
||||||
|
# normal -> normal mode
|
||||||
|
# insert -> insert mode
|
||||||
|
vi_default_mode = normal
|
||||||
|
|
||||||
|
# Enable vi keybindings
|
||||||
|
vi_mode = false
|
||||||
|
|
||||||
# Wayland desktop environments
|
# Wayland desktop environments
|
||||||
waylandsessions = /usr/share/wayland-sessions
|
# You can specify multiple directories,
|
||||||
|
# e.g. /usr/share/wayland-sessions:/usr/local/share/wayland-sessions
|
||||||
# xinitrc (hidden if null)
|
waylandsessions = $PREFIX_DIRECTORY/share/wayland-sessions
|
||||||
xinitrc = ~/.xinitrc
|
|
||||||
|
|
||||||
# Xorg server command
|
# Xorg server command
|
||||||
x_cmd = /usr/bin/X
|
x_cmd = $PREFIX_DIRECTORY/bin/X
|
||||||
|
|
||||||
# Xorg setup command
|
|
||||||
x_cmd_setup = /etc/ly/xsetup.sh
|
|
||||||
|
|
||||||
# Xorg xauthority edition tool
|
# Xorg xauthority edition tool
|
||||||
xauth_cmd = /usr/bin/xauth
|
xauth_cmd = $PREFIX_DIRECTORY/bin/xauth
|
||||||
|
|
||||||
|
# xinitrc
|
||||||
|
# If null, the xinitrc session will be hidden
|
||||||
|
xinitrc = ~/.xinitrc
|
||||||
|
|
||||||
# Xorg desktop environments
|
# Xorg desktop environments
|
||||||
xsessions = /usr/share/xsessions
|
# You can specify multiple directories,
|
||||||
|
# e.g. /usr/share/xsessions:/usr/local/share/xsessions
|
||||||
|
xsessions = $PREFIX_DIRECTORY/share/xsessions
|
||||||
|
|||||||
64
res/lang/ar.ini
Normal file
64
res/lang/ar.ini
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
authenticating = جاري المصادقة...
|
||||||
|
brightness_down = خفض السطوع
|
||||||
|
brightness_up = رفع السطوع
|
||||||
|
capslock = capslock
|
||||||
|
err_alloc = فشل في تخصيص الذاكرة
|
||||||
|
err_bounds = out-of-bounds index
|
||||||
|
err_brightness_change = فشل في تغيير سطوع الشاشة
|
||||||
|
err_chdir = فشل في فتح مجلد المنزل
|
||||||
|
err_config = فشل في تفسير ملف الإعدادات
|
||||||
|
err_console_dev = فشل في الوصول إلى جهاز وحدة التحكم
|
||||||
|
err_dgn_oob = رسالة سجل (Log)
|
||||||
|
err_domain = اسم نطاق غير صالح
|
||||||
|
err_empty_password = لا يُسمح بكلمة مرور فارغة
|
||||||
|
err_envlist = فشل في جلب قائمة المتغيرات البيئية
|
||||||
|
err_hostname = فشل في جلب اسم المضيف (Hostname)
|
||||||
|
err_mlock = فشل في تأمين ذاكرة كلمة المرور (mlock)
|
||||||
|
err_null = مؤشر فارغ (Null pointer)
|
||||||
|
err_numlock = فشل في ضبط Num Lock
|
||||||
|
err_pam = فشل في معاملة PAM
|
||||||
|
err_pam_abort = تم إلغاء معاملة PAM
|
||||||
|
err_pam_acct_expired = الحساب منتهي الصلاحية
|
||||||
|
err_pam_auth = خطأ في المصادقة (Authentication error)
|
||||||
|
err_pam_authinfo_unavail = فشل في الحصول على معلومات المستخدم
|
||||||
|
err_pam_authok_reqd = انتهت صلاحية رمز المصادقة (Token)
|
||||||
|
err_pam_buf = خطأ في ذاكرة التخزين المؤقت (Buffer)
|
||||||
|
err_pam_cred_err = فشل في تعيين بيانات الاعتماد (Credentials)
|
||||||
|
err_pam_cred_expired = بيانات الاعتماد منتهية الصلاحية
|
||||||
|
err_pam_cred_insufficient = بيانات الاعتماد غير كافية
|
||||||
|
err_pam_cred_unavail = فشل في الحصول على بيانات الاعتماد
|
||||||
|
err_pam_maxtries = تم بلوغ الحد الأقصى لمحاولات المصادقة
|
||||||
|
err_pam_perm_denied = تم رفض الوصول (Permission denied)
|
||||||
|
err_pam_session = خطأ في جلسة المستخدم (Session error)
|
||||||
|
err_pam_sys = خطأ في النظام (System error)
|
||||||
|
err_pam_user_unknown = المستخدم غير موجود
|
||||||
|
err_path = فشل في تعيين متغير PATH
|
||||||
|
err_perm_dir = فشل في تغيير المجلد الحالي
|
||||||
|
err_perm_group = فشل في تخفيض صلاحيات المجموعة (Group permissions)
|
||||||
|
err_perm_user = فشل في تخفيض صلاحيات المستخدم (User permissions)
|
||||||
|
err_pwnam = فشل في جلب معلومات المستخدم
|
||||||
|
err_sleep = فشل في تنفيذ أمر sleep
|
||||||
|
err_tty_ctrl = فشل في نقل تحكم الطرفية (TTY)
|
||||||
|
err_unknown = حدث خطأ غير معروف
|
||||||
|
err_user_gid = فشل في تعيين معرّف المجموعة (GID) للمستخدم
|
||||||
|
err_user_init = فشل في تهيئة بيانات المستخدم
|
||||||
|
err_user_uid = فشل في تعيين معرّف المستخدم (UID)
|
||||||
|
err_xauth = فشل في تنفيذ أمر xauth
|
||||||
|
err_xcb_conn = فشل في الاتصال بمكتبة XCB
|
||||||
|
err_xsessions_dir = فشل في العثور على مجلد Xsessions
|
||||||
|
err_xsessions_open = فشل في فتح مجلد Xsessions
|
||||||
|
insert = ادخال
|
||||||
|
login = تسجيل الدخول
|
||||||
|
logout = تم تسجيل خروجك
|
||||||
|
no_x11_support = تم تعطيل دعم x11 اثناء وقت الـ compile
|
||||||
|
normal = عادي
|
||||||
|
numlock = numlock
|
||||||
|
other = اخر
|
||||||
|
password = كلمة السر
|
||||||
|
restart = اعادة التشغيل
|
||||||
|
shell = shell
|
||||||
|
shutdown = ايقاف التشغيل
|
||||||
|
sleep = وضع السكون
|
||||||
|
wayland = wayland
|
||||||
|
x11 = x11
|
||||||
|
xinitrc = xinitrc
|
||||||
@@ -1,45 +1,64 @@
|
|||||||
|
authenticating = autenticant...
|
||||||
|
brightness_down = abaixar brillantor
|
||||||
|
brightness_up = apujar brillantor
|
||||||
capslock = Bloq Majús
|
capslock = Bloq Majús
|
||||||
err_alloc = falla d'assignació de memòria
|
err_alloc = assignació de memòria fallida
|
||||||
err_bounds = índex fora de límit
|
err_bounds = índex fora de límits
|
||||||
err_chdir = error al obrir carpeta home
|
err_brightness_change = error en canviar la brillantor
|
||||||
err_console_dev = error al accedir a la consola
|
err_chdir = error en obrir la carpeta home
|
||||||
|
|
||||||
|
err_console_dev = error en accedir a la consola
|
||||||
err_dgn_oob = missatge de registre
|
err_dgn_oob = missatge de registre
|
||||||
err_domain = domini invàlid
|
err_domain = domini invàlid
|
||||||
err_hostname = error al obtenir el nom del host
|
|
||||||
err_mlock = error al bloquejar la clau de memòria
|
err_envlist = error en obtenir l'envlist
|
||||||
|
err_hostname = error en obtenir el nom de l'amfitrió
|
||||||
|
err_mlock = error en bloquejar la memòria de clau
|
||||||
err_null = punter nul
|
err_null = punter nul
|
||||||
|
err_numlock = error en establir el Bloq num
|
||||||
err_pam = error en la transacció pam
|
err_pam = error en la transacció pam
|
||||||
err_pam_abort = transacció pam avortada
|
err_pam_abort = transacció pam avortada
|
||||||
err_pam_acct_expired = compte expirat
|
err_pam_acct_expired = compte expirat
|
||||||
err_pam_auth = error d'autenticació
|
err_pam_auth = error d'autenticació
|
||||||
err_pam_authinfo_unavail = error al obtenir informació de l'usuari
|
err_pam_authinfo_unavail = error en obtenir la informació de l'usuari
|
||||||
err_pam_authok_reqd = token expirat
|
err_pam_authok_reqd = token expirat
|
||||||
err_pam_buf = error de la memòria intermitja
|
err_pam_buf = error en la memòria intermèdia
|
||||||
err_pam_cred_err = error al establir les credencials
|
err_pam_cred_err = error en establir les credencials
|
||||||
err_pam_cred_expired = credencials expirades
|
err_pam_cred_expired = credencials expirades
|
||||||
err_pam_cred_insufficient = credencials insuficients
|
err_pam_cred_insufficient = credencials insuficients
|
||||||
err_pam_cred_unavail = error al obtenir credencials
|
err_pam_cred_unavail = error en obtenir credencials
|
||||||
err_pam_maxtries = s'ha assolit al màxim nombre d'intents
|
err_pam_maxtries = s'ha assolit al nombre màxim d'intents
|
||||||
err_pam_perm_denied = permís denegat
|
err_pam_perm_denied = permís denegat
|
||||||
err_pam_session = error de sessió
|
err_pam_session = error de sessió
|
||||||
err_pam_sys = error de sistema
|
err_pam_sys = error de sistema
|
||||||
err_pam_user_unknown = usuari desconegut
|
err_pam_user_unknown = usuari desconegut
|
||||||
err_path = error al establir la ruta
|
err_path = error en establir la ruta
|
||||||
err_perm_dir = error al canviar de directori actual
|
err_perm_dir = error en canviar el directori actual
|
||||||
err_perm_group = error al degradar els permisos de grup
|
err_perm_group = error en degradar els permisos de grup
|
||||||
err_perm_user = error al degradar els permisos de l'usuari
|
err_perm_user = error en degradar els permisos de l'usuari
|
||||||
err_pwnam = error al obtenir la informació de l'usuari
|
err_pwnam = error en obtenir la informació de l'usuari
|
||||||
err_user_gid = error al establir el GID de l'usuari
|
|
||||||
err_user_init = error al inicialitzar usuari
|
|
||||||
err_user_uid = error al establir el UID de l'usuari
|
err_unknown = ha ocorregut un error desconegut
|
||||||
err_xsessions_dir = error al cercar la carpeta de sessions
|
err_user_gid = error en establir el GID de l'usuari
|
||||||
err_xsessions_open = error al obrir la carpeta de sessions
|
err_user_init = error en inicialitzar usuari
|
||||||
|
err_user_uid = error en establir l'UID de l'usuari
|
||||||
|
err_xauth = error en la comanda xauth
|
||||||
|
err_xcb_conn = error en la connexió xcb
|
||||||
|
err_xsessions_dir = error en trobar la carpeta de sessions
|
||||||
|
err_xsessions_open = error en obrir la carpeta de sessions
|
||||||
|
insert = inserir
|
||||||
login = iniciar sessió
|
login = iniciar sessió
|
||||||
logout = tancar sessió
|
logout = sessió tancada
|
||||||
|
no_x11_support = el suport per x11 ha estat desactivat en la compilació
|
||||||
|
normal = normal
|
||||||
numlock = Bloq Num
|
numlock = Bloq Num
|
||||||
|
|
||||||
password = Clau
|
password = Clau
|
||||||
restart = reiniciar
|
restart = reiniciar
|
||||||
shell = shell
|
shell = shell
|
||||||
shutdown = aturar
|
shutdown = aturar
|
||||||
|
sleep = suspendre
|
||||||
wayland = wayland
|
wayland = wayland
|
||||||
|
x11 = x11
|
||||||
xinitrc = xinitrc
|
xinitrc = xinitrc
|
||||||
|
|||||||
@@ -1,13 +1,21 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
capslock = capslock
|
capslock = capslock
|
||||||
err_alloc = alokace paměti selhala
|
err_alloc = alokace paměti selhala
|
||||||
err_bounds = index je mimo hranice pole
|
err_bounds = index je mimo hranice pole
|
||||||
|
|
||||||
err_chdir = nelze otevřít domovský adresář
|
err_chdir = nelze otevřít domovský adresář
|
||||||
|
|
||||||
err_console_dev = chyba při přístupu do konzole
|
err_console_dev = chyba při přístupu do konzole
|
||||||
err_dgn_oob = zpráva protokolu
|
err_dgn_oob = zpráva protokolu
|
||||||
err_domain = neplatná doména
|
err_domain = neplatná doména
|
||||||
|
|
||||||
|
|
||||||
err_hostname = nelze získat název hostitele
|
err_hostname = nelze získat název hostitele
|
||||||
err_mlock = uzamčení paměti hesel selhalo
|
err_mlock = uzamčení paměti hesel selhalo
|
||||||
err_null = nulový ukazatel
|
err_null = nulový ukazatel
|
||||||
|
|
||||||
err_pam = pam transakce selhala
|
err_pam = pam transakce selhala
|
||||||
err_pam_abort = pam transakce přerušena
|
err_pam_abort = pam transakce přerušena
|
||||||
err_pam_acct_expired = platnost účtu vypršela
|
err_pam_acct_expired = platnost účtu vypršela
|
||||||
@@ -29,17 +37,28 @@ err_perm_dir = nepodařilo se změnit adresář
|
|||||||
err_perm_group = nepodařilo se snížit skupinová oprávnění
|
err_perm_group = nepodařilo se snížit skupinová oprávnění
|
||||||
err_perm_user = nepodařilo se snížit uživatelská oprávnění
|
err_perm_user = nepodařilo se snížit uživatelská oprávnění
|
||||||
err_pwnam = nelze získat informace o uživateli
|
err_pwnam = nelze získat informace o uživateli
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
err_user_gid = nastavení GID uživatele selhalo
|
err_user_gid = nastavení GID uživatele selhalo
|
||||||
err_user_init = inicializace uživatele selhala
|
err_user_init = inicializace uživatele selhala
|
||||||
err_user_uid = nastavení UID uživateli selhalo
|
err_user_uid = nastavení UID uživateli selhalo
|
||||||
|
|
||||||
|
|
||||||
err_xsessions_dir = nepodařilo se najít složku relací
|
err_xsessions_dir = nepodařilo se najít složku relací
|
||||||
err_xsessions_open = nepodařilo se otevřít složku relací
|
err_xsessions_open = nepodařilo se otevřít složku relací
|
||||||
|
|
||||||
login = uživatel
|
login = uživatel
|
||||||
logout = odhlášen
|
logout = odhlášen
|
||||||
|
|
||||||
|
|
||||||
numlock = numlock
|
numlock = numlock
|
||||||
|
|
||||||
password = heslo
|
password = heslo
|
||||||
restart = restartovat
|
restart = restartovat
|
||||||
shell = příkazový řádek
|
shell = příkazový řádek
|
||||||
shutdown = vypnout
|
shutdown = vypnout
|
||||||
|
|
||||||
wayland = wayland
|
wayland = wayland
|
||||||
|
|
||||||
xinitrc = xinitrc
|
xinitrc = xinitrc
|
||||||
|
|||||||
@@ -1,13 +1,21 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
capslock = Feststelltaste
|
capslock = Feststelltaste
|
||||||
err_alloc = Speicherzuweisung fehlgeschlagen
|
err_alloc = Speicherzuweisung fehlgeschlagen
|
||||||
err_bounds = Listenindex ist außerhalb des Bereichs
|
err_bounds = Listenindex ist außerhalb des Bereichs
|
||||||
|
|
||||||
err_chdir = Fehler beim oeffnen des home-ordners
|
err_chdir = Fehler beim oeffnen des home-ordners
|
||||||
|
|
||||||
err_console_dev = Zugriff auf die Konsole fehlgeschlagen
|
err_console_dev = Zugriff auf die Konsole fehlgeschlagen
|
||||||
err_dgn_oob = Protokoll Nachricht
|
err_dgn_oob = Protokoll Nachricht
|
||||||
err_domain = Unzulaessige domain
|
err_domain = Unzulaessige domain
|
||||||
|
|
||||||
|
|
||||||
err_hostname = Holen des Hostnames fehlgeschlagen
|
err_hostname = Holen des Hostnames fehlgeschlagen
|
||||||
err_mlock = Abschließen des Passwortspeichers fehlgeschlagen
|
err_mlock = Abschließen des Passwortspeichers fehlgeschlagen
|
||||||
err_null = Null Zeiger
|
err_null = Null Zeiger
|
||||||
|
|
||||||
err_pam = pam Transaktion fehlgeschlagen
|
err_pam = pam Transaktion fehlgeschlagen
|
||||||
err_pam_abort = pam Transaktion abgebrochen
|
err_pam_abort = pam Transaktion abgebrochen
|
||||||
err_pam_acct_expired = Benutzerkonto abgelaufen
|
err_pam_acct_expired = Benutzerkonto abgelaufen
|
||||||
@@ -29,17 +37,28 @@ err_perm_dir = Fehler beim wechseln des Ordners
|
|||||||
err_perm_group = Fehler beim heruntersetzen der Gruppen Berechtigungen
|
err_perm_group = Fehler beim heruntersetzen der Gruppen Berechtigungen
|
||||||
err_perm_user = Fehler beim heruntersetzen der Nutzer Berechtigungen
|
err_perm_user = Fehler beim heruntersetzen der Nutzer Berechtigungen
|
||||||
err_pwnam = Holen der Benutzerinformationen fehlgeschlagen
|
err_pwnam = Holen der Benutzerinformationen fehlgeschlagen
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
err_user_gid = Fehler beim setzen der Gruppen Id des Nutzers
|
err_user_gid = Fehler beim setzen der Gruppen Id des Nutzers
|
||||||
err_user_init = Initialisierung des Nutzers fehlgeschlagen
|
err_user_init = Initialisierung des Nutzers fehlgeschlagen
|
||||||
err_user_uid = Setzen der Benutzer Id fehlgeschlagen
|
err_user_uid = Setzen der Benutzer Id fehlgeschlagen
|
||||||
|
|
||||||
|
|
||||||
err_xsessions_dir = Fehler beim finden des Sitzungsordners
|
err_xsessions_dir = Fehler beim finden des Sitzungsordners
|
||||||
err_xsessions_open = Fehler beim öffnen des Sitzungsordners
|
err_xsessions_open = Fehler beim öffnen des Sitzungsordners
|
||||||
|
|
||||||
login = Anmelden
|
login = Anmelden
|
||||||
logout = Abgemeldet
|
logout = Abgemeldet
|
||||||
|
|
||||||
|
|
||||||
numlock = Numtaste
|
numlock = Numtaste
|
||||||
|
|
||||||
password = Passwort
|
password = Passwort
|
||||||
restart = Neustarten
|
restart = Neustarten
|
||||||
shell = shell
|
shell = shell
|
||||||
shutdown = Herunterfahren
|
shutdown = Herunterfahren
|
||||||
|
|
||||||
wayland = wayland
|
wayland = wayland
|
||||||
|
|
||||||
xinitrc = xinitrc
|
xinitrc = xinitrc
|
||||||
|
|||||||
@@ -1,16 +1,21 @@
|
|||||||
authenticating = authenticating...
|
authenticating = authenticating...
|
||||||
|
brightness_down = decrease brightness
|
||||||
|
brightness_up = increase brightness
|
||||||
capslock = capslock
|
capslock = capslock
|
||||||
err_alloc = failed memory allocation
|
err_alloc = failed memory allocation
|
||||||
err_bounds = out-of-bounds index
|
err_bounds = out-of-bounds index
|
||||||
|
err_brightness_change = failed to change brightness
|
||||||
err_chdir = failed to open home folder
|
err_chdir = failed to open home folder
|
||||||
|
err_config = unable to parse config file
|
||||||
err_console_dev = failed to access console
|
err_console_dev = failed to access console
|
||||||
err_dgn_oob = log message
|
err_dgn_oob = log message
|
||||||
err_domain = invalid domain
|
err_domain = invalid domain
|
||||||
|
err_empty_password = empty password not allowed
|
||||||
err_envlist = failed to get envlist
|
err_envlist = failed to get envlist
|
||||||
err_hostname = failed to get hostname
|
err_hostname = failed to get hostname
|
||||||
err_mcookie = mcookie command failed
|
|
||||||
err_mlock = failed to lock password memory
|
err_mlock = failed to lock password memory
|
||||||
err_null = null pointer
|
err_null = null pointer
|
||||||
|
err_numlock = failed to set numlock
|
||||||
err_pam = pam transaction failed
|
err_pam = pam transaction failed
|
||||||
err_pam_abort = pam transaction aborted
|
err_pam_abort = pam transaction aborted
|
||||||
err_pam_acct_expired = account expired
|
err_pam_acct_expired = account expired
|
||||||
@@ -32,6 +37,8 @@ err_perm_dir = failed to change current directory
|
|||||||
err_perm_group = failed to downgrade group permissions
|
err_perm_group = failed to downgrade group permissions
|
||||||
err_perm_user = failed to downgrade user permissions
|
err_perm_user = failed to downgrade user permissions
|
||||||
err_pwnam = failed to get user info
|
err_pwnam = failed to get user info
|
||||||
|
err_sleep = failed to execute sleep command
|
||||||
|
err_tty_ctrl = tty control transfer failed
|
||||||
err_unknown = an unknown error occurred
|
err_unknown = an unknown error occurred
|
||||||
err_user_gid = failed to set user GID
|
err_user_gid = failed to set user GID
|
||||||
err_user_init = failed to initialize user
|
err_user_init = failed to initialize user
|
||||||
@@ -43,13 +50,15 @@ err_xsessions_open = failed to open sessions folder
|
|||||||
insert = insert
|
insert = insert
|
||||||
login = login
|
login = login
|
||||||
logout = logged out
|
logout = logged out
|
||||||
|
no_x11_support = x11 support disabled at compile-time
|
||||||
normal = normal
|
normal = normal
|
||||||
numlock = numlock
|
numlock = numlock
|
||||||
|
other = other
|
||||||
password = password
|
password = password
|
||||||
restart = reboot
|
restart = reboot
|
||||||
shell = shell
|
shell = shell
|
||||||
shutdown = shutdown
|
shutdown = shutdown
|
||||||
sleep = sleep
|
sleep = sleep
|
||||||
wayland = wayland
|
wayland = wayland
|
||||||
xinitrc = xinitrc
|
|
||||||
x11 = x11
|
x11 = x11
|
||||||
|
xinitrc = xinitrc
|
||||||
|
|||||||
@@ -1,13 +1,21 @@
|
|||||||
|
authenticating = autenticando...
|
||||||
|
brightness_down = bajar brillo
|
||||||
|
brightness_up = subir brillo
|
||||||
capslock = Bloq Mayús
|
capslock = Bloq Mayús
|
||||||
err_alloc = asignación de memoria fallida
|
err_alloc = asignación de memoria fallida
|
||||||
err_bounds = índice fuera de límites
|
err_bounds = índice fuera de límites
|
||||||
|
|
||||||
err_chdir = error al abrir la carpeta home
|
err_chdir = error al abrir la carpeta home
|
||||||
|
|
||||||
err_console_dev = error al acceder a la consola
|
err_console_dev = error al acceder a la consola
|
||||||
err_dgn_oob = mensaje de registro
|
err_dgn_oob = mensaje de registro
|
||||||
err_domain = dominio inválido
|
err_domain = dominio inválido
|
||||||
|
|
||||||
|
|
||||||
err_hostname = error al obtener el nombre de host
|
err_hostname = error al obtener el nombre de host
|
||||||
err_mlock = error al bloquear la contraseña de memoria
|
err_mlock = error al bloquear la contraseña de memoria
|
||||||
err_null = puntero nulo
|
err_null = puntero nulo
|
||||||
|
|
||||||
err_pam = error en la transacción pam
|
err_pam = error en la transacción pam
|
||||||
err_pam_abort = transacción pam abortada
|
err_pam_abort = transacción pam abortada
|
||||||
err_pam_acct_expired = cuenta expirada
|
err_pam_acct_expired = cuenta expirada
|
||||||
@@ -29,17 +37,28 @@ err_perm_dir = error al cambiar el directorio actual
|
|||||||
err_perm_group = error al degradar los permisos del grupo
|
err_perm_group = error al degradar los permisos del grupo
|
||||||
err_perm_user = error al degradar los permisos del usuario
|
err_perm_user = error al degradar los permisos del usuario
|
||||||
err_pwnam = error al obtener la información del usuario
|
err_pwnam = error al obtener la información del usuario
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
err_user_gid = error al establecer el GID del usuario
|
err_user_gid = error al establecer el GID del usuario
|
||||||
err_user_init = error al inicializar usuario
|
err_user_init = error al inicializar usuario
|
||||||
err_user_uid = error al establecer el UID del usuario
|
err_user_uid = error al establecer el UID del usuario
|
||||||
|
|
||||||
|
|
||||||
err_xsessions_dir = error al buscar la carpeta de sesiones
|
err_xsessions_dir = error al buscar la carpeta de sesiones
|
||||||
err_xsessions_open = error al abrir la carpeta de sesiones
|
err_xsessions_open = error al abrir la carpeta de sesiones
|
||||||
login = iniciar sesión
|
insert = insertar
|
||||||
|
login = usuario
|
||||||
logout = cerrar sesión
|
logout = cerrar sesión
|
||||||
|
no_x11_support = soporte para x11 deshabilitado en tiempo de compilación
|
||||||
|
normal = normal
|
||||||
numlock = Bloq Num
|
numlock = Bloq Num
|
||||||
|
other = otro
|
||||||
password = contraseña
|
password = contraseña
|
||||||
restart = reiniciar
|
restart = reiniciar
|
||||||
shell = shell
|
shell = shell
|
||||||
shutdown = apagar
|
shutdown = apagar
|
||||||
|
sleep = suspender
|
||||||
wayland = wayland
|
wayland = wayland
|
||||||
|
|
||||||
xinitrc = xinitrc
|
xinitrc = xinitrc
|
||||||
|
|||||||
@@ -1,19 +1,27 @@
|
|||||||
capslock = verr.maj
|
authenticating = authentification...
|
||||||
|
brightness_down = diminuer la luminosité
|
||||||
|
brightness_up = augmenter la luminosité
|
||||||
|
capslock = verr.maj
|
||||||
err_alloc = échec d'allocation mémoire
|
err_alloc = échec d'allocation mémoire
|
||||||
err_bounds = indice hors-limite
|
err_bounds = indice hors-limite
|
||||||
|
err_brightness_change = échec du changement de luminosité
|
||||||
err_chdir = échec de l'ouverture du répertoire home
|
err_chdir = échec de l'ouverture du répertoire home
|
||||||
|
err_config = échec de lecture du fichier de configuration
|
||||||
err_console_dev = échec d'accès à la console
|
err_console_dev = échec d'accès à la console
|
||||||
err_dgn_oob = message
|
err_dgn_oob = message
|
||||||
err_domain = domaine invalide
|
err_domain = domaine invalide
|
||||||
|
err_empty_password = mot de passe vide non autorisé
|
||||||
|
err_envlist = échec de lecture de la liste d'environnement
|
||||||
err_hostname = échec de lecture du nom d'hôte
|
err_hostname = échec de lecture du nom d'hôte
|
||||||
err_mlock = échec du verrouillage mémoire
|
err_mlock = échec du verrouillage mémoire
|
||||||
err_null = pointeur null
|
err_null = pointeur null
|
||||||
|
err_numlock = échec de modification du verr.num
|
||||||
err_pam = échec de la transaction pam
|
err_pam = échec de la transaction pam
|
||||||
err_pam_abort = transaction pam avortée
|
err_pam_abort = transaction pam avortée
|
||||||
err_pam_acct_expired = compte expiré
|
err_pam_acct_expired = compte expiré
|
||||||
err_pam_auth = erreur d'authentification
|
err_pam_auth = erreur d'authentification
|
||||||
err_pam_authok_reqd = tiquet expiré
|
|
||||||
err_pam_authinfo_unavail = échec de l'obtention des infos utilisateur
|
err_pam_authinfo_unavail = échec de l'obtention des infos utilisateur
|
||||||
|
err_pam_authok_reqd = tiquet expiré
|
||||||
err_pam_buf = erreur de mémoire tampon
|
err_pam_buf = erreur de mémoire tampon
|
||||||
err_pam_cred_err = échec de la modification des identifiants
|
err_pam_cred_err = échec de la modification des identifiants
|
||||||
err_pam_cred_expired = identifiants expirés
|
err_pam_cred_expired = identifiants expirés
|
||||||
@@ -29,17 +37,28 @@ err_perm_dir = échec de changement de répertoire
|
|||||||
err_perm_group = échec du déclassement des permissions de groupe
|
err_perm_group = échec du déclassement des permissions de groupe
|
||||||
err_perm_user = échec du déclassement des permissions utilisateur
|
err_perm_user = échec du déclassement des permissions utilisateur
|
||||||
err_pwnam = échec de lecture des infos utilisateur
|
err_pwnam = échec de lecture des infos utilisateur
|
||||||
|
err_sleep = échec de l'exécution de la commande de veille
|
||||||
|
err_tty_ctrl = échec du transfert de contrôle du terminal
|
||||||
|
err_unknown = une erreur inconnue est survenue
|
||||||
err_user_gid = échec de modification du GID
|
err_user_gid = échec de modification du GID
|
||||||
err_user_init = échec d'initialisation de l'utilisateur
|
err_user_init = échec d'initialisation de l'utilisateur
|
||||||
err_user_uid = échec de modification du UID
|
err_user_uid = échec de modification du UID
|
||||||
|
err_xauth = échec de la commande xauth
|
||||||
|
err_xcb_conn = échec de la connexion xcb
|
||||||
err_xsessions_dir = échec de la recherche du dossier de sessions
|
err_xsessions_dir = échec de la recherche du dossier de sessions
|
||||||
err_xsessions_open = échec de l'ouverture du dossier de sessions
|
err_xsessions_open = échec de l'ouverture du dossier de sessions
|
||||||
|
insert = insertion
|
||||||
login = identifiant
|
login = identifiant
|
||||||
logout = déconnection
|
logout = déconnecté
|
||||||
|
no_x11_support = support pour x11 désactivé lors de la compilation
|
||||||
|
normal = normal
|
||||||
numlock = verr.num
|
numlock = verr.num
|
||||||
|
other = autre
|
||||||
password = mot de passe
|
password = mot de passe
|
||||||
restart = redémarrer
|
restart = redémarrer
|
||||||
shell = shell
|
shell = shell
|
||||||
shutdown = éteindre
|
shutdown = éteindre
|
||||||
|
sleep = veille
|
||||||
wayland = wayland
|
wayland = wayland
|
||||||
|
x11 = x11
|
||||||
xinitrc = xinitrc
|
xinitrc = xinitrc
|
||||||
|
|||||||
@@ -1,13 +1,21 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
capslock = capslock
|
capslock = capslock
|
||||||
err_alloc = impossibile allocare memoria
|
err_alloc = impossibile allocare memoria
|
||||||
err_bounds = indice fuori limite
|
err_bounds = indice fuori limite
|
||||||
|
|
||||||
err_chdir = impossibile aprire home directory
|
err_chdir = impossibile aprire home directory
|
||||||
|
|
||||||
err_console_dev = impossibile aprire console
|
err_console_dev = impossibile aprire console
|
||||||
err_dgn_oob = messaggio log
|
err_dgn_oob = messaggio log
|
||||||
err_domain = dominio non valido
|
err_domain = dominio non valido
|
||||||
|
|
||||||
|
|
||||||
err_hostname = impossibile ottenere hostname
|
err_hostname = impossibile ottenere hostname
|
||||||
err_mlock = impossibile ottenere lock per la password in memoria
|
err_mlock = impossibile ottenere lock per la password in memoria
|
||||||
err_null = puntatore nullo
|
err_null = puntatore nullo
|
||||||
|
|
||||||
err_pam = transazione PAM fallita
|
err_pam = transazione PAM fallita
|
||||||
err_pam_abort = transazione PAM interrotta
|
err_pam_abort = transazione PAM interrotta
|
||||||
err_pam_acct_expired = account scaduto
|
err_pam_acct_expired = account scaduto
|
||||||
@@ -29,17 +37,28 @@ err_perm_dir = impossibile cambiare directory corrente
|
|||||||
err_perm_group = impossibile ridurre permessi gruppo
|
err_perm_group = impossibile ridurre permessi gruppo
|
||||||
err_perm_user = impossibile ridurre permessi utente
|
err_perm_user = impossibile ridurre permessi utente
|
||||||
err_pwnam = impossibile ottenere dati utente
|
err_pwnam = impossibile ottenere dati utente
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
err_user_gid = impossibile impostare GID utente
|
err_user_gid = impossibile impostare GID utente
|
||||||
err_user_init = impossibile inizializzare utente
|
err_user_init = impossibile inizializzare utente
|
||||||
err_user_uid = impossible impostare UID utente
|
err_user_uid = impossible impostare UID utente
|
||||||
|
|
||||||
|
|
||||||
err_xsessions_dir = impossibile localizzare cartella sessioni
|
err_xsessions_dir = impossibile localizzare cartella sessioni
|
||||||
err_xsessions_open = impossibile aprire cartella sessioni
|
err_xsessions_open = impossibile aprire cartella sessioni
|
||||||
|
|
||||||
login = username
|
login = username
|
||||||
logout = scollegato
|
logout = scollegato
|
||||||
|
|
||||||
|
|
||||||
numlock = numlock
|
numlock = numlock
|
||||||
|
|
||||||
password = password
|
password = password
|
||||||
restart = riavvio
|
restart = riavvio
|
||||||
shell = shell
|
shell = shell
|
||||||
shutdown = arresto
|
shutdown = arresto
|
||||||
|
|
||||||
wayland = wayland
|
wayland = wayland
|
||||||
|
|
||||||
xinitrc = xinitrc
|
xinitrc = xinitrc
|
||||||
|
|||||||
49
res/lang/normalize_lang_files.py
Executable file
49
res/lang/normalize_lang_files.py
Executable file
@@ -0,0 +1,49 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
from pathlib import Path
|
||||||
|
from sys import stderr
|
||||||
|
|
||||||
|
|
||||||
|
def process_lang_file(path: Path, lang_keys: list[str]) -> None:
|
||||||
|
# read key-value-pairs from lang file into dict
|
||||||
|
existing_entries = {}
|
||||||
|
with open(path, "r", encoding="UTF-8") as fh:
|
||||||
|
while line := fh.readline():
|
||||||
|
try:
|
||||||
|
key, value = line.split("=", 1)
|
||||||
|
existing_entries[key.strip()] = value.strip()
|
||||||
|
except ValueError: # line does not contain '='
|
||||||
|
continue
|
||||||
|
|
||||||
|
# re-write current lang file with entries in order of occurence in `lang_keys`
|
||||||
|
# and with empty lines for missing translations
|
||||||
|
with open(path, "w", encoding="UTF-8") as fh:
|
||||||
|
for item in lang_keys:
|
||||||
|
try:
|
||||||
|
fh.write(f"{item} = {existing_entries[item]}\n")
|
||||||
|
except KeyError: # no translation for `item` yet
|
||||||
|
fh.write("\n")
|
||||||
|
|
||||||
|
|
||||||
|
def main() -> None:
|
||||||
|
zig_lang_file = Path(__file__).parent.joinpath("../../src/config/Lang.zig").resolve()
|
||||||
|
if not zig_lang_file.exists():
|
||||||
|
print(f"ERROR: File '{zig_lang_file.as_posix()}' does not exist. Exiting.", file=stderr)
|
||||||
|
exit(1)
|
||||||
|
|
||||||
|
# read "language keys" from `zig_lang_file` into list
|
||||||
|
lang_keys = []
|
||||||
|
with open(zig_lang_file, "r", encoding="UTF-8") as fh:
|
||||||
|
while line := fh.readline():
|
||||||
|
# only process lines that are not empty or no comments
|
||||||
|
if not (line.strip() == "" or line.startswith("//")):
|
||||||
|
lang_keys.append(line.split(":")[0].strip())
|
||||||
|
|
||||||
|
lang_files = [f for f in Path.iterdir(Path(__file__).parent) if f.name.endswith(".ini") and f.is_file()]
|
||||||
|
|
||||||
|
for file in lang_files:
|
||||||
|
process_lang_file(file, lang_keys)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
@@ -1,45 +1,64 @@
|
|||||||
|
authenticating = uwierzytelnianie...
|
||||||
|
brightness_down = zmniejsz jasność
|
||||||
|
brightness_up = zwiększ jasność
|
||||||
capslock = capslock
|
capslock = capslock
|
||||||
err_alloc = nieudana alokacja pamięci
|
err_alloc = nieudana alokacja pamięci
|
||||||
err_bounds = indeks poza granicami
|
err_bounds = indeks poza zakresem
|
||||||
|
err_brightness_change = nie udało się zmienić jasności
|
||||||
err_chdir = nie udało się otworzyć folderu domowego
|
err_chdir = nie udało się otworzyć folderu domowego
|
||||||
err_console_dev = nie udało się uzyskać dostępu do konsoli
|
err_config = nie można przetworzyć pliku konfiguracyjnego
|
||||||
|
err_console_dev = nie udało się uzyskać dostępu do konsoli
|
||||||
err_dgn_oob = wiadomość loga
|
err_dgn_oob = wiadomość loga
|
||||||
err_domain = niepoprawna domena
|
err_domain = niepoprawna domena
|
||||||
|
err_empty_password = puste hasło jest niedozwolone
|
||||||
|
err_envlist = nie udało się pobrać listy zmiennych środowiskowych
|
||||||
err_hostname = nie udało się uzyskać nazwy hosta
|
err_hostname = nie udało się uzyskać nazwy hosta
|
||||||
err_mlock = nie udało się zablokować pamięci haseł
|
err_mlock = nie udało się zablokować pamięci haseł
|
||||||
err_null = wskaźnik zerowy
|
err_null = pusty wskaźnik
|
||||||
|
err_numlock = nie udało się ustawić numlock
|
||||||
err_pam = transakcja pam nieudana
|
err_pam = transakcja pam nieudana
|
||||||
err_pam_abort = transakcja pam przerwana
|
err_pam_abort = transakcja pam przerwana
|
||||||
err_pam_acct_expired = konto wygasło
|
err_pam_acct_expired = konto wygasło
|
||||||
err_pam_auth = błąd autentyfikacji
|
err_pam_auth = błąd uwierzytelniania
|
||||||
err_pam_authinfo_unavail = nie udało się zdobyć informacji o użytkowniku
|
err_pam_authinfo_unavail = nie udało się zdobyć informacji o użytkowniku
|
||||||
err_pam_authok_reqd = token wygasł
|
err_pam_authok_reqd = token wygasł
|
||||||
err_pam_buf = błąd bufora pamięci
|
err_pam_buf = błąd bufora pamięci
|
||||||
err_pam_cred_err = nie udało się ustawić uwierzytelnienia
|
err_pam_cred_err = nie udało się ustawić uwierzytelnienia
|
||||||
err_pam_cred_expired = uwierzytelnienie wygasło
|
err_pam_cred_expired = uwierzytelnienie wygasło
|
||||||
err_pam_cred_insufficient = niewystarczające uwierzytelnienie
|
err_pam_cred_insufficient = niewystarczające uwierzytelnienie
|
||||||
err_pam_cred_unavail = nie udało się uzyskać uwierzytelnienia
|
err_pam_cred_unavail = nie udało się uzyskać uwierzytelnienia
|
||||||
err_pam_maxtries = osiągnięto limit prób
|
err_pam_maxtries = osiągnięto limit prób
|
||||||
err_pam_perm_denied = brak uprawnień
|
err_pam_perm_denied = odmowa dostępu
|
||||||
err_pam_session = błąd sesji
|
err_pam_session = błąd sesji
|
||||||
err_pam_sys = błąd systemu
|
err_pam_sys = błąd systemu
|
||||||
err_pam_user_unknown = nieznany użytkownik
|
err_pam_user_unknown = nieznany użytkownik
|
||||||
err_path = nie udało się ustawić ścieżki
|
err_path = nie udało się ustawić ścieżki
|
||||||
err_perm_dir = nie udało się zmienić obecnego katalogu
|
err_perm_dir = nie udało się zmienić obecnego katalogu
|
||||||
err_perm_group = nie udało się obniżyć uprawnień grupy
|
err_perm_group = nie udało się obniżyć uprawnień grupy
|
||||||
err_perm_user = nie udało się obniżyć uprawnień użytkownika
|
err_perm_user = nie udało się obniżyć uprawnień użytkownika
|
||||||
err_pwnam = nie udało się uzyskać informacji o użytkowniku
|
err_pwnam = nie udało się uzyskać informacji o użytkowniku
|
||||||
|
err_sleep = nie udało się wykonać polecenia sleep
|
||||||
|
err_tty_ctrl = nie udało się przekazać kontroli tty
|
||||||
|
err_unknown = wystąpił nieznany błąd
|
||||||
err_user_gid = nie udało się ustawić GID użytkownika
|
err_user_gid = nie udało się ustawić GID użytkownika
|
||||||
err_user_init = nie udało się zainicjalizować użytkownika
|
err_user_init = nie udało się zainicjalizować użytkownika
|
||||||
err_user_uid = nie udało się ustawić UID użytkownika
|
err_user_uid = nie udało się ustawić UID użytkownika
|
||||||
err_xsessions_dir = nie udało się znaleźć folderu sesji
|
err_xauth = polecenie xauth nie powiodło się
|
||||||
err_xsessions_open = nie udało się otworzyć folderu sesji
|
err_xcb_conn = połączenie xcb nie powiodło się
|
||||||
|
err_xsessions_dir = nie udało się znaleźć folderu sesji
|
||||||
|
err_xsessions_open = nie udało się otworzyć folderu sesji
|
||||||
|
insert = wstaw
|
||||||
login = login
|
login = login
|
||||||
logout = wylogowano
|
logout = wylogowano
|
||||||
|
no_x11_support = wsparcie X11 wyłączone podczas kompilacji
|
||||||
|
normal = normalny
|
||||||
numlock = numlock
|
numlock = numlock
|
||||||
|
other = inny
|
||||||
password = hasło
|
password = hasło
|
||||||
restart = uruchom ponownie
|
restart = uruchom ponownie
|
||||||
shell = powłoka
|
shell = powłoka
|
||||||
shutdown = wyłącz
|
shutdown = wyłącz
|
||||||
|
sleep = uśpij
|
||||||
wayland = wayland
|
wayland = wayland
|
||||||
|
x11 = x11
|
||||||
xinitrc = xinitrc
|
xinitrc = xinitrc
|
||||||
|
|||||||
@@ -1,13 +1,21 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
capslock = capslock
|
capslock = capslock
|
||||||
err_alloc = erro na atribuição de memória
|
err_alloc = erro na atribuição de memória
|
||||||
err_bounds = índice fora de limites
|
err_bounds = índice fora de limites
|
||||||
|
|
||||||
err_chdir = erro ao abrir a pasta home
|
err_chdir = erro ao abrir a pasta home
|
||||||
|
|
||||||
err_console_dev = erro ao aceder à consola
|
err_console_dev = erro ao aceder à consola
|
||||||
err_dgn_oob = mensagem de registo
|
err_dgn_oob = mensagem de registo
|
||||||
err_domain = domínio inválido
|
err_domain = domínio inválido
|
||||||
|
|
||||||
|
|
||||||
err_hostname = erro ao obter o nome do host
|
err_hostname = erro ao obter o nome do host
|
||||||
err_mlock = erro de bloqueio de memória
|
err_mlock = erro de bloqueio de memória
|
||||||
err_null = ponteiro nulo
|
err_null = ponteiro nulo
|
||||||
|
|
||||||
err_pam = erro na transação pam
|
err_pam = erro na transação pam
|
||||||
err_pam_abort = transação pam abortada
|
err_pam_abort = transação pam abortada
|
||||||
err_pam_acct_expired = conta expirada
|
err_pam_acct_expired = conta expirada
|
||||||
@@ -29,17 +37,28 @@ err_perm_dir = erro ao alterar o diretório atual
|
|||||||
err_perm_group = erro ao reduzir as permissões do grupo
|
err_perm_group = erro ao reduzir as permissões do grupo
|
||||||
err_perm_user = erro ao reduzir as permissões do utilizador
|
err_perm_user = erro ao reduzir as permissões do utilizador
|
||||||
err_pwnam = erro ao obter informação do utilizador
|
err_pwnam = erro ao obter informação do utilizador
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
err_user_gid = erro ao definir o GID do utilizador
|
err_user_gid = erro ao definir o GID do utilizador
|
||||||
err_user_init = erro ao iniciar o utilizador
|
err_user_init = erro ao iniciar o utilizador
|
||||||
err_user_uid = erro ao definir o UID do utilizador
|
err_user_uid = erro ao definir o UID do utilizador
|
||||||
|
|
||||||
|
|
||||||
err_xsessions_dir = erro ao localizar a pasta das sessões
|
err_xsessions_dir = erro ao localizar a pasta das sessões
|
||||||
err_xsessions_open = erro ao abrir a pasta das sessões
|
err_xsessions_open = erro ao abrir a pasta das sessões
|
||||||
|
|
||||||
login = iniciar sessão
|
login = iniciar sessão
|
||||||
logout = terminar sessão
|
logout = terminar sessão
|
||||||
|
|
||||||
|
|
||||||
numlock = numlock
|
numlock = numlock
|
||||||
|
|
||||||
password = palavra-passe
|
password = palavra-passe
|
||||||
restart = reiniciar
|
restart = reiniciar
|
||||||
shell = shell
|
shell = shell
|
||||||
shutdown = encerrar
|
shutdown = encerrar
|
||||||
|
|
||||||
wayland = wayland
|
wayland = wayland
|
||||||
|
|
||||||
xinitrc = xinitrc
|
xinitrc = xinitrc
|
||||||
|
|||||||
@@ -1,13 +1,21 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
capslock = caixa alta
|
capslock = caixa alta
|
||||||
err_alloc = alocação de memória malsucedida
|
err_alloc = alocação de memória malsucedida
|
||||||
err_bounds = índice fora de limites
|
err_bounds = índice fora de limites
|
||||||
|
|
||||||
err_chdir = não foi possível abrir o diretório home
|
err_chdir = não foi possível abrir o diretório home
|
||||||
|
|
||||||
err_console_dev = não foi possível acessar o console
|
err_console_dev = não foi possível acessar o console
|
||||||
err_dgn_oob = mensagem de log
|
err_dgn_oob = mensagem de log
|
||||||
err_domain = domínio inválido
|
err_domain = domínio inválido
|
||||||
|
|
||||||
|
|
||||||
err_hostname = não foi possível obter o nome do host
|
err_hostname = não foi possível obter o nome do host
|
||||||
err_mlock = bloqueio da memória de senha malsucedido
|
err_mlock = bloqueio da memória de senha malsucedido
|
||||||
err_null = ponteiro nulo
|
err_null = ponteiro nulo
|
||||||
|
|
||||||
err_pam = transação pam malsucedida
|
err_pam = transação pam malsucedida
|
||||||
err_pam_abort = transação pam abortada
|
err_pam_abort = transação pam abortada
|
||||||
err_pam_acct_expired = conta expirada
|
err_pam_acct_expired = conta expirada
|
||||||
@@ -29,17 +37,28 @@ err_perm_dir = não foi possível alterar o diretório atual
|
|||||||
err_perm_group = não foi possível reduzir as permissões de grupo
|
err_perm_group = não foi possível reduzir as permissões de grupo
|
||||||
err_perm_user = não foi possível reduzir as permissões de usuário
|
err_perm_user = não foi possível reduzir as permissões de usuário
|
||||||
err_pwnam = não foi possível obter informações do usuário
|
err_pwnam = não foi possível obter informações do usuário
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
err_user_gid = não foi possível definir o GID do usuário
|
err_user_gid = não foi possível definir o GID do usuário
|
||||||
err_user_init = não foi possível iniciar o usuário
|
err_user_init = não foi possível iniciar o usuário
|
||||||
err_user_uid = não foi possível definir o UID do usuário
|
err_user_uid = não foi possível definir o UID do usuário
|
||||||
|
|
||||||
|
|
||||||
err_xsessions_dir = não foi possível encontrar a pasta das sessões
|
err_xsessions_dir = não foi possível encontrar a pasta das sessões
|
||||||
err_xsessions_open = não foi possível abrir a pasta das sessões
|
err_xsessions_open = não foi possível abrir a pasta das sessões
|
||||||
|
|
||||||
login = conectar
|
login = conectar
|
||||||
logout = desconectado
|
logout = desconectado
|
||||||
|
|
||||||
|
|
||||||
numlock = numlock
|
numlock = numlock
|
||||||
|
|
||||||
password = senha
|
password = senha
|
||||||
restart = reiniciar
|
restart = reiniciar
|
||||||
shell = shell
|
shell = shell
|
||||||
shutdown = desligar
|
shutdown = desligar
|
||||||
|
|
||||||
wayland = wayland
|
wayland = wayland
|
||||||
|
|
||||||
xinitrc = xinitrc
|
xinitrc = xinitrc
|
||||||
|
|||||||
@@ -1,7 +1,12 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
capslock = capslock
|
capslock = capslock
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
err_console_dev = nu s-a putut accesa consola
|
err_console_dev = nu s-a putut accesa consola
|
||||||
|
|
||||||
|
|
||||||
@@ -9,6 +14,9 @@ err_console_dev = nu s-a putut accesa consola
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
err_pam_abort = tranzacţie pam anulată
|
err_pam_abort = tranzacţie pam anulată
|
||||||
err_pam_acct_expired = cont expirat
|
err_pam_acct_expired = cont expirat
|
||||||
err_pam_auth = eroare de autentificare
|
err_pam_auth = eroare de autentificare
|
||||||
@@ -34,12 +42,23 @@ err_perm_user = nu s-a putut face downgrade permisiunilor de utilizator
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
login = utilizator
|
login = utilizator
|
||||||
logout = opreşte sesiunea
|
logout = opreşte sesiunea
|
||||||
|
|
||||||
|
|
||||||
numlock = numlock
|
numlock = numlock
|
||||||
|
|
||||||
password = parolă
|
password = parolă
|
||||||
restart = resetează
|
restart = resetează
|
||||||
shell = shell
|
shell = shell
|
||||||
shutdown = opreşte sistemul
|
shutdown = opreşte sistemul
|
||||||
|
|
||||||
wayland = wayland
|
wayland = wayland
|
||||||
|
|
||||||
xinitrc = xinitrc
|
xinitrc = xinitrc
|
||||||
|
|||||||
@@ -1,13 +1,21 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
capslock = capslock
|
capslock = capslock
|
||||||
err_alloc = не удалось выделить память
|
err_alloc = не удалось выделить память
|
||||||
err_bounds = за пределами индекса
|
err_bounds = за пределами индекса
|
||||||
|
|
||||||
err_chdir = не удалось открыть домашнюю папку
|
err_chdir = не удалось открыть домашнюю папку
|
||||||
|
|
||||||
err_console_dev = не удалось получить доступ к консоли
|
err_console_dev = не удалось получить доступ к консоли
|
||||||
err_dgn_oob = отладочное сообщение (log)
|
err_dgn_oob = отладочное сообщение (log)
|
||||||
err_domain = неверный домен
|
err_domain = неверный домен
|
||||||
|
|
||||||
|
|
||||||
err_hostname = не удалось получить имя хоста
|
err_hostname = не удалось получить имя хоста
|
||||||
err_mlock = сбой блокировки памяти
|
err_mlock = сбой блокировки памяти
|
||||||
err_null = нулевой указатель
|
err_null = нулевой указатель
|
||||||
|
|
||||||
err_pam = pam транзакция не удалась
|
err_pam = pam транзакция не удалась
|
||||||
err_pam_abort = pam транзакция прервана
|
err_pam_abort = pam транзакция прервана
|
||||||
err_pam_acct_expired = срок действия аккаунта истёк
|
err_pam_acct_expired = срок действия аккаунта истёк
|
||||||
@@ -29,17 +37,28 @@ err_perm_dir = не удалось изменить текущий катало
|
|||||||
err_perm_group = не удалось понизить права доступа группы
|
err_perm_group = не удалось понизить права доступа группы
|
||||||
err_perm_user = не удалось понизить права доступа пользователя
|
err_perm_user = не удалось понизить права доступа пользователя
|
||||||
err_pwnam = не удалось получить информацию о пользователе
|
err_pwnam = не удалось получить информацию о пользователе
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
err_user_gid = не удалось установить GID пользователя
|
err_user_gid = не удалось установить GID пользователя
|
||||||
err_user_init = не удалось инициализировать пользователя
|
err_user_init = не удалось инициализировать пользователя
|
||||||
err_user_uid = не удалось установить UID пользователя
|
err_user_uid = не удалось установить UID пользователя
|
||||||
|
|
||||||
|
|
||||||
err_xsessions_dir = не удалось найти сессионную папку
|
err_xsessions_dir = не удалось найти сессионную папку
|
||||||
err_xsessions_open = не удалось открыть сессионную папку
|
err_xsessions_open = не удалось открыть сессионную папку
|
||||||
|
|
||||||
login = логин
|
login = логин
|
||||||
logout = logged out
|
logout = logged out
|
||||||
|
|
||||||
|
|
||||||
numlock = numlock
|
numlock = numlock
|
||||||
|
|
||||||
password = пароль
|
password = пароль
|
||||||
restart = перезагрузить
|
restart = перезагрузить
|
||||||
shell = shell
|
shell = shell
|
||||||
shutdown = выключить
|
shutdown = выключить
|
||||||
|
|
||||||
wayland = wayland
|
wayland = wayland
|
||||||
|
|
||||||
xinitrc = xinitrc
|
xinitrc = xinitrc
|
||||||
|
|||||||
@@ -1,13 +1,21 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
capslock = capslock
|
capslock = capslock
|
||||||
err_alloc = neuspijesna alokacija memorije
|
err_alloc = neuspijesna alokacija memorije
|
||||||
err_bounds = izvan granica indeksa
|
err_bounds = izvan granica indeksa
|
||||||
|
|
||||||
err_chdir = neuspijesno otvaranje home foldera
|
err_chdir = neuspijesno otvaranje home foldera
|
||||||
|
|
||||||
err_console_dev = neuspijesno pristupanje konzoli
|
err_console_dev = neuspijesno pristupanje konzoli
|
||||||
err_dgn_oob = log poruka
|
err_dgn_oob = log poruka
|
||||||
err_domain = nevazeci domen
|
err_domain = nevazeci domen
|
||||||
|
|
||||||
|
|
||||||
err_hostname = neuspijesno trazenje hostname-a
|
err_hostname = neuspijesno trazenje hostname-a
|
||||||
err_mlock = neuspijesno zakljucavanje memorije lozinke
|
err_mlock = neuspijesno zakljucavanje memorije lozinke
|
||||||
err_null = null pokazivac
|
err_null = null pokazivac
|
||||||
|
|
||||||
err_pam = pam transakcija neuspijesna
|
err_pam = pam transakcija neuspijesna
|
||||||
err_pam_abort = pam transakcija prekinuta
|
err_pam_abort = pam transakcija prekinuta
|
||||||
err_pam_acct_expired = nalog istekao
|
err_pam_acct_expired = nalog istekao
|
||||||
@@ -29,17 +37,28 @@ err_perm_dir = neuspjelo mijenjanje foldera
|
|||||||
err_perm_group = neuspjesno snizavanje dozvola grupe
|
err_perm_group = neuspjesno snizavanje dozvola grupe
|
||||||
err_perm_user = neuspijesno snizavanje dozvola korisnika
|
err_perm_user = neuspijesno snizavanje dozvola korisnika
|
||||||
err_pwnam = neuspijesno skupljanje informacija o korisniku
|
err_pwnam = neuspijesno skupljanje informacija o korisniku
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
err_user_gid = neuspijesno postavljanje korisničkog GID-a
|
err_user_gid = neuspijesno postavljanje korisničkog GID-a
|
||||||
err_user_init = neuspijensa inicijalizacija korisnika
|
err_user_init = neuspijensa inicijalizacija korisnika
|
||||||
err_user_uid = neuspijesno postavljanje UID-a korisnika
|
err_user_uid = neuspijesno postavljanje UID-a korisnika
|
||||||
|
|
||||||
|
|
||||||
err_xsessions_dir = neuspijesno pronalazenje foldera sesija
|
err_xsessions_dir = neuspijesno pronalazenje foldera sesija
|
||||||
err_xsessions_open = neuspijesno otvaranje foldera sesija
|
err_xsessions_open = neuspijesno otvaranje foldera sesija
|
||||||
|
|
||||||
login = korisnik
|
login = korisnik
|
||||||
logout = izlogovan
|
logout = izlogovan
|
||||||
|
|
||||||
|
|
||||||
numlock = numlock
|
numlock = numlock
|
||||||
|
|
||||||
password = lozinka
|
password = lozinka
|
||||||
restart = ponovo pokreni
|
restart = ponovo pokreni
|
||||||
shell = shell
|
shell = shell
|
||||||
shutdown = ugasi
|
shutdown = ugasi
|
||||||
|
|
||||||
wayland = wayland
|
wayland = wayland
|
||||||
|
|
||||||
xinitrc = xinitrc
|
xinitrc = xinitrc
|
||||||
|
|||||||
@@ -1,13 +1,21 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
capslock = capslock
|
capslock = capslock
|
||||||
err_alloc = misslyckad minnesallokering
|
err_alloc = misslyckad minnesallokering
|
||||||
err_bounds = utanför banan index
|
err_bounds = utanför banan index
|
||||||
|
|
||||||
err_chdir = misslyckades att öppna hemkatalog
|
err_chdir = misslyckades att öppna hemkatalog
|
||||||
|
|
||||||
err_console_dev = misslyckades att komma åt konsol
|
err_console_dev = misslyckades att komma åt konsol
|
||||||
err_dgn_oob = loggmeddelande
|
err_dgn_oob = loggmeddelande
|
||||||
err_domain = okänd domän
|
err_domain = okänd domän
|
||||||
|
|
||||||
|
|
||||||
err_hostname = misslyckades att hämta värdnamn
|
err_hostname = misslyckades att hämta värdnamn
|
||||||
err_mlock = misslyckades att låsa lösenordsminne
|
err_mlock = misslyckades att låsa lösenordsminne
|
||||||
err_null = nullpekare
|
err_null = nullpekare
|
||||||
|
|
||||||
err_pam = pam-transaktion misslyckades
|
err_pam = pam-transaktion misslyckades
|
||||||
err_pam_abort = pam-transaktion avbröts
|
err_pam_abort = pam-transaktion avbröts
|
||||||
err_pam_acct_expired = konto upphört
|
err_pam_acct_expired = konto upphört
|
||||||
@@ -29,17 +37,28 @@ err_perm_dir = misslyckades att ändra aktuell katalog
|
|||||||
err_perm_group = misslyckades att nergradera gruppbehörigheter
|
err_perm_group = misslyckades att nergradera gruppbehörigheter
|
||||||
err_perm_user = misslyckades att nergradera användarbehörigheter
|
err_perm_user = misslyckades att nergradera användarbehörigheter
|
||||||
err_pwnam = misslyckades att hämta användarinfo
|
err_pwnam = misslyckades att hämta användarinfo
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
err_user_gid = misslyckades att ställa in användar-GID
|
err_user_gid = misslyckades att ställa in användar-GID
|
||||||
err_user_init = misslyckades att initialisera användaren
|
err_user_init = misslyckades att initialisera användaren
|
||||||
err_user_uid = misslyckades att ställa in användar-UID
|
err_user_uid = misslyckades att ställa in användar-UID
|
||||||
|
|
||||||
|
|
||||||
err_xsessions_dir = misslyckades att hitta sessionskatalog
|
err_xsessions_dir = misslyckades att hitta sessionskatalog
|
||||||
err_xsessions_open = misslyckades att öppna sessionskatalog
|
err_xsessions_open = misslyckades att öppna sessionskatalog
|
||||||
|
|
||||||
login = inloggning
|
login = inloggning
|
||||||
logout = utloggad
|
logout = utloggad
|
||||||
|
|
||||||
|
|
||||||
numlock = numlock
|
numlock = numlock
|
||||||
|
|
||||||
password = lösenord
|
password = lösenord
|
||||||
restart = starta om
|
restart = starta om
|
||||||
shell = skal
|
shell = skal
|
||||||
shutdown = stäng av
|
shutdown = stäng av
|
||||||
|
|
||||||
wayland = wayland
|
wayland = wayland
|
||||||
|
|
||||||
xinitrc = xinitrc
|
xinitrc = xinitrc
|
||||||
|
|||||||
@@ -1,13 +1,21 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
capslock = capslock
|
capslock = capslock
|
||||||
err_alloc = basarisiz bellek ayirma
|
err_alloc = basarisiz bellek ayirma
|
||||||
err_bounds = sinirlarin disinda dizin
|
err_bounds = sinirlarin disinda dizin
|
||||||
|
|
||||||
err_chdir = ev klasoru acilamadi
|
err_chdir = ev klasoru acilamadi
|
||||||
|
|
||||||
err_console_dev = konsola erisilemedi
|
err_console_dev = konsola erisilemedi
|
||||||
err_dgn_oob = log mesaji
|
err_dgn_oob = log mesaji
|
||||||
err_domain = gecersiz etki alani
|
err_domain = gecersiz etki alani
|
||||||
|
|
||||||
|
|
||||||
err_hostname = ana bilgisayar adi alinamadi
|
err_hostname = ana bilgisayar adi alinamadi
|
||||||
err_mlock = parola bellegi kilitlenemedi
|
err_mlock = parola bellegi kilitlenemedi
|
||||||
err_null = bos isaretci hatasi
|
err_null = bos isaretci hatasi
|
||||||
|
|
||||||
err_pam = pam islemi basarisiz oldu
|
err_pam = pam islemi basarisiz oldu
|
||||||
err_pam_abort = pam islemi durduruldu
|
err_pam_abort = pam islemi durduruldu
|
||||||
err_pam_acct_expired = hesabin suresi dolmus
|
err_pam_acct_expired = hesabin suresi dolmus
|
||||||
@@ -29,17 +37,28 @@ err_perm_dir = gecerli dizin degistirilemedi
|
|||||||
err_perm_group = grup izinleri dusurulemedi
|
err_perm_group = grup izinleri dusurulemedi
|
||||||
err_perm_user = kullanici izinleri dusurulemedi
|
err_perm_user = kullanici izinleri dusurulemedi
|
||||||
err_pwnam = kullanici bilgileri alinamadi
|
err_pwnam = kullanici bilgileri alinamadi
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
err_user_gid = kullanici icin GID ayarlanamadi
|
err_user_gid = kullanici icin GID ayarlanamadi
|
||||||
err_user_init = kullanici oturumu baslatilamadi
|
err_user_init = kullanici oturumu baslatilamadi
|
||||||
err_user_uid = kullanici icin UID ayarlanamadi
|
err_user_uid = kullanici icin UID ayarlanamadi
|
||||||
|
|
||||||
|
|
||||||
err_xsessions_dir = oturumlar klasoru bulunamadi
|
err_xsessions_dir = oturumlar klasoru bulunamadi
|
||||||
err_xsessions_open = oturumlar klasoru acilamadi
|
err_xsessions_open = oturumlar klasoru acilamadi
|
||||||
|
|
||||||
login = kullanici
|
login = kullanici
|
||||||
logout = oturumdan cikis yapildi
|
logout = oturumdan cikis yapildi
|
||||||
|
|
||||||
|
|
||||||
numlock = numlock
|
numlock = numlock
|
||||||
|
|
||||||
password = sifre
|
password = sifre
|
||||||
restart = yeniden baslat
|
restart = yeniden baslat
|
||||||
shell = shell
|
shell = shell
|
||||||
shutdown = makineyi kapat
|
shutdown = makineyi kapat
|
||||||
|
|
||||||
wayland = wayland
|
wayland = wayland
|
||||||
|
|
||||||
xinitrc = xinitrc
|
xinitrc = xinitrc
|
||||||
|
|||||||
@@ -1,13 +1,21 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
capslock = capslock
|
capslock = capslock
|
||||||
err_alloc = невдале виділення пам'яті
|
err_alloc = невдале виділення пам'яті
|
||||||
err_bounds = поза межами індексу
|
err_bounds = поза межами індексу
|
||||||
|
|
||||||
err_chdir = не вдалося відкрити домашній каталог
|
err_chdir = не вдалося відкрити домашній каталог
|
||||||
|
|
||||||
err_console_dev = невдалий доступ до консолі
|
err_console_dev = невдалий доступ до консолі
|
||||||
err_dgn_oob = повідомлення журналу (log)
|
err_dgn_oob = повідомлення журналу (log)
|
||||||
err_domain = недійсний домен
|
err_domain = недійсний домен
|
||||||
|
|
||||||
|
|
||||||
err_hostname = не вдалося отримати ім'я хосту
|
err_hostname = не вдалося отримати ім'я хосту
|
||||||
err_mlock = збій блокування пам'яті
|
err_mlock = збій блокування пам'яті
|
||||||
err_null = нульовий вказівник
|
err_null = нульовий вказівник
|
||||||
|
|
||||||
err_pam = невдала pam транзакція
|
err_pam = невдала pam транзакція
|
||||||
err_pam_abort = pam транзакція перервана
|
err_pam_abort = pam транзакція перервана
|
||||||
err_pam_acct_expired = термін дії акаунту вичерпано
|
err_pam_acct_expired = термін дії акаунту вичерпано
|
||||||
@@ -29,17 +37,28 @@ err_perm_dir = не вдалося змінити поточний катало
|
|||||||
err_perm_group = не вдалося понизити права доступу групи
|
err_perm_group = не вдалося понизити права доступу групи
|
||||||
err_perm_user = не вдалося понизити права доступу користувача
|
err_perm_user = не вдалося понизити права доступу користувача
|
||||||
err_pwnam = не вдалося отримати дані користувача
|
err_pwnam = не вдалося отримати дані користувача
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
err_user_gid = не вдалося змінити GID користувача
|
err_user_gid = не вдалося змінити GID користувача
|
||||||
err_user_init = не вдалося ініціалізувати користувача
|
err_user_init = не вдалося ініціалізувати користувача
|
||||||
err_user_uid = не вдалося змінити UID користувача
|
err_user_uid = не вдалося змінити UID користувача
|
||||||
|
|
||||||
|
|
||||||
err_xsessions_dir = не вдалося знайти каталог сесій
|
err_xsessions_dir = не вдалося знайти каталог сесій
|
||||||
err_xsessions_open = не вдалося відкрити каталог сесій
|
err_xsessions_open = не вдалося відкрити каталог сесій
|
||||||
|
|
||||||
login = логін
|
login = логін
|
||||||
logout = вийти
|
logout = вийти
|
||||||
|
|
||||||
|
|
||||||
numlock = numlock
|
numlock = numlock
|
||||||
|
|
||||||
password = пароль
|
password = пароль
|
||||||
restart = перезавантажити
|
restart = перезавантажити
|
||||||
shell = оболонка
|
shell = оболонка
|
||||||
shutdown = вимкнути
|
shutdown = вимкнути
|
||||||
|
|
||||||
wayland = wayland
|
wayland = wayland
|
||||||
|
|
||||||
xinitrc = xinitrc
|
xinitrc = xinitrc
|
||||||
|
|||||||
64
res/lang/zh_CN.ini
Normal file
64
res/lang/zh_CN.ini
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
capslock = 大写锁定
|
||||||
|
err_alloc = 内存分配失败
|
||||||
|
err_bounds = 索引越界
|
||||||
|
|
||||||
|
err_chdir = 无法打开home文件夹
|
||||||
|
|
||||||
|
err_console_dev = 无法访问控制台
|
||||||
|
err_dgn_oob = 日志消息
|
||||||
|
err_domain = 无效的域
|
||||||
|
|
||||||
|
|
||||||
|
err_hostname = 获取主机名失败
|
||||||
|
err_mlock = 锁定密码存储器失败
|
||||||
|
err_null = 空指针
|
||||||
|
|
||||||
|
err_pam = PAM事件失败
|
||||||
|
err_pam_abort = PAM事务已中止
|
||||||
|
err_pam_acct_expired = 帐户已过期
|
||||||
|
err_pam_auth = 身份验证错误
|
||||||
|
err_pam_authinfo_unavail = 获取用户信息失败
|
||||||
|
err_pam_authok_reqd = 口令已过期
|
||||||
|
err_pam_buf = 内存缓冲区错误
|
||||||
|
err_pam_cred_err = 设置凭据失败
|
||||||
|
err_pam_cred_expired = 凭据已过期
|
||||||
|
err_pam_cred_insufficient = 凭据不足
|
||||||
|
err_pam_cred_unavail = 无法获取凭据
|
||||||
|
err_pam_maxtries = 已达到最大尝试次数限制
|
||||||
|
err_pam_perm_denied = 拒绝访问
|
||||||
|
err_pam_session = 会话错误
|
||||||
|
err_pam_sys = 系统错误
|
||||||
|
err_pam_user_unknown = 未知用户
|
||||||
|
err_path = 无法设置路径
|
||||||
|
err_perm_dir = 更改当前目录失败
|
||||||
|
err_perm_group = 组权限降级失败
|
||||||
|
err_perm_user = 用户权限降级失败
|
||||||
|
err_pwnam = 获取用户信息失败
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
err_user_gid = 设置用户GID失败
|
||||||
|
err_user_init = 初始化用户失败
|
||||||
|
err_user_uid = 设置用户UID失败
|
||||||
|
|
||||||
|
|
||||||
|
err_xsessions_dir = 找不到会话文件夹
|
||||||
|
err_xsessions_open = 无法打开会话文件夹
|
||||||
|
|
||||||
|
login = 登录
|
||||||
|
logout = 注销
|
||||||
|
|
||||||
|
|
||||||
|
numlock = 数字锁定
|
||||||
|
|
||||||
|
password = 密码
|
||||||
|
|
||||||
|
shell = shell
|
||||||
|
|
||||||
|
|
||||||
|
wayland = wayland
|
||||||
|
x11 = x11
|
||||||
|
xinitrc = xinitrc
|
||||||
8
res/ly-dinit
Normal file
8
res/ly-dinit
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
type = process
|
||||||
|
restart = true
|
||||||
|
smooth-recovery = true
|
||||||
|
command = $PREFIX_DIRECTORY/bin/$EXE_NAME
|
||||||
|
depends-on = loginready
|
||||||
|
termsignal = HUP
|
||||||
|
# ly needs access to the console while loginready already occupies it
|
||||||
|
options = shares-console
|
||||||
@@ -20,16 +20,16 @@ then
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
## Get the tty from the conf file
|
## Get the tty from the conf file
|
||||||
CONFTTY=$(cat /etc/ly/config.ini | sed -n 's/^tty.*=[^1-9]*// p')
|
CONFTTY=$(cat $CONFIG_DIRECTORY/ly/config.ini | sed -n 's/^tty.*=[^1-9]*// p')
|
||||||
|
|
||||||
## The execution vars
|
## The execution vars
|
||||||
# If CONFTTY is empty then default to 2
|
# If CONFTTY is empty then default to $DEFAULT_TTY
|
||||||
TTY="tty${CONFTTY:-2}"
|
TTY="tty${CONFTTY:-$DEFAULT_TTY}"
|
||||||
TERM=linux
|
TERM=linux
|
||||||
BAUD=38400
|
BAUD=38400
|
||||||
# If we don't have getty then we should have agetty
|
# If we don't have getty then we should have agetty
|
||||||
command=${commandB:-$commandUL}
|
command=${commandB:-$commandUL}
|
||||||
command_args_foreground="-nl /usr/bin/ly $TTY $BAUD $TERM"
|
command_args_foreground="-nl $PREFIX_DIRECTORY/bin/$EXECUTABLE_NAME $TTY $BAUD $TERM"
|
||||||
|
|
||||||
depend() {
|
depend() {
|
||||||
after agetty
|
after agetty
|
||||||
|
|||||||
@@ -8,5 +8,5 @@ fi
|
|||||||
BAUD_RATE=38400
|
BAUD_RATE=38400
|
||||||
TERM_NAME=linux
|
TERM_NAME=linux
|
||||||
|
|
||||||
auxtty=$(/bin/cat /etc/ly/config.ini 2>/dev/null 1| /bin/sed -n 's/\(^[[:space:]]*tty[[:space:]]*=[[:space:]]*\)\([[:digit:]][[:digit:]]*\)\(.*\)/\2/p')
|
auxtty=$(/bin/cat $CONFIG_DIRECTORY/ly/config.ini 2>/dev/null 1| /bin/sed -n 's/\(^[[:space:]]*tty[[:space:]]*=[[:space:]]*\)\([[:digit:]][[:digit:]]*\)\(.*\)/\2/p')
|
||||||
TTY=tty${auxtty:-2}
|
TTY=tty${auxtty:-$DEFAULT_TTY}
|
||||||
|
|||||||
@@ -10,4 +10,4 @@ elif [ -x /sbin/agetty -o -x /bin/agetty ]; then
|
|||||||
GETTY=agetty
|
GETTY=agetty
|
||||||
fi
|
fi
|
||||||
|
|
||||||
exec setsid ${GETTY} ${GETTY_ARGS} -nl /usr/bin/ly "${TTY}" "${BAUD_RATE}" "${TERM_NAME}"
|
exec setsid ${GETTY} ${GETTY_ARGS} -nl $PREFIX_DIRECTORY/bin/$EXECUTABLE_NAME "${TTY}" "${BAUD_RATE}" "${TERM_NAME}"
|
||||||
|
|||||||
2
res/ly-s6/run
Normal file
2
res/ly-s6/run
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
#!/bin/execlineb -P
|
||||||
|
exec agetty -L -8 -n -l $PREFIX_DIRECTORY/bin/$EXE_NAME tty$DEFAULT_TTY 115200
|
||||||
1
res/ly-s6/type
Normal file
1
res/ly-s6/type
Normal file
@@ -0,0 +1 @@
|
|||||||
|
longrun
|
||||||
@@ -1,15 +1,14 @@
|
|||||||
[Unit]
|
[Unit]
|
||||||
Description=TUI display manager
|
Description=TUI display manager
|
||||||
After=systemd-user-sessions.service plymouth-quit-wait.service
|
After=systemd-user-sessions.service plymouth-quit-wait.service
|
||||||
After=getty@tty2.service
|
After=getty@tty$DEFAULT_TTY.service
|
||||||
Conflicts=getty@tty2.service
|
Conflicts=getty@tty$DEFAULT_TTY.service
|
||||||
|
|
||||||
[Service]
|
[Service]
|
||||||
Type=idle
|
Type=idle
|
||||||
ExecStart=/usr/bin/ly
|
ExecStart=$PREFIX_DIRECTORY/bin/$EXECUTABLE_NAME
|
||||||
StandardError=journal
|
|
||||||
StandardInput=tty
|
StandardInput=tty
|
||||||
TTYPath=/dev/tty2
|
TTYPath=/dev/tty$DEFAULT_TTY
|
||||||
TTYReset=yes
|
TTYReset=yes
|
||||||
TTYVHangup=yes
|
TTYVHangup=yes
|
||||||
|
|
||||||
|
|||||||
10
res/pam.d/ly
10
res/pam.d/ly
@@ -1,6 +1,16 @@
|
|||||||
#%PAM-1.0
|
#%PAM-1.0
|
||||||
|
|
||||||
auth include login
|
auth include login
|
||||||
|
-auth optional pam_gnome_keyring.so
|
||||||
|
-auth optional pam_kwallet5.so
|
||||||
|
|
||||||
account include login
|
account include login
|
||||||
|
|
||||||
password include login
|
password include login
|
||||||
|
-password optional pam_gnome_keyring.so use_authtok
|
||||||
|
|
||||||
|
-session optional pam_systemd.so class=greeter
|
||||||
|
-session optional pam_elogind.so
|
||||||
session include login
|
session include login
|
||||||
|
-session optional pam_gnome_keyring.so auto_start
|
||||||
|
-session optional pam_kwallet5.so auto_start
|
||||||
|
|||||||
107
res/setup.sh
Executable file
107
res/setup.sh
Executable file
@@ -0,0 +1,107 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
# Shell environment setup after login
|
||||||
|
# Copyright (C) 2015-2016 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com>
|
||||||
|
|
||||||
|
# This file is extracted from kde-workspace (kdm/kfrontend/genkdmconf.c)
|
||||||
|
# Copyright (C) 2001-2005 Oswald Buddenhagen <ossi@kde.org>
|
||||||
|
|
||||||
|
# Copyright (C) 2024 The Fairy Glade
|
||||||
|
# This work is free. You can redistribute it and/or modify it under the
|
||||||
|
# terms of the Do What The Fuck You Want To Public License, Version 2,
|
||||||
|
# as published by Sam Hocevar. See the LICENSE file for more details.
|
||||||
|
|
||||||
|
# Note that the respective logout scripts are not sourced.
|
||||||
|
case $SHELL in
|
||||||
|
*/bash)
|
||||||
|
[ -z "$BASH" ] && exec $SHELL "$0" "$@"
|
||||||
|
set +o posix
|
||||||
|
[ -f "$CONFIG_DIRECTORY"/profile ] && . "$CONFIG_DIRECTORY"/profile
|
||||||
|
if [ -f "$HOME"/.bash_profile ]; then
|
||||||
|
. "$HOME"/.bash_profile
|
||||||
|
elif [ -f "$HOME"/.bash_login ]; then
|
||||||
|
. "$HOME"/.bash_login
|
||||||
|
elif [ -f "$HOME"/.profile ]; then
|
||||||
|
. "$HOME"/.profile
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
*/zsh)
|
||||||
|
[ -z "$ZSH_NAME" ] && exec $SHELL "$0" "$@"
|
||||||
|
[ -d "$CONFIG_DIRECTORY"/zsh ] && zdir="$CONFIG_DIRECTORY"/zsh || zdir="$CONFIG_DIRECTORY"
|
||||||
|
zhome=${ZDOTDIR:-"$HOME"}
|
||||||
|
# zshenv is always sourced automatically.
|
||||||
|
[ -f "$zdir"/zprofile ] && . "$zdir"/zprofile
|
||||||
|
[ -f "$zhome"/.zprofile ] && . "$zhome"/.zprofile
|
||||||
|
[ -f "$zdir"/zlogin ] && . "$zdir"/zlogin
|
||||||
|
[ -f "$zhome"/.zlogin ] && . "$zhome"/.zlogin
|
||||||
|
emulate -R sh
|
||||||
|
;;
|
||||||
|
*/csh|*/tcsh)
|
||||||
|
# [t]cshrc is always sourced automatically.
|
||||||
|
# Note that sourcing csh.login after .cshrc is non-standard.
|
||||||
|
sess_tmp=$(mktemp /tmp/sess-env-XXXXXX)
|
||||||
|
$SHELL -c "if (-f $CONFIG_DIRECTORY/csh.login) source $CONFIG_DIRECTORY/csh.login; if (-f ~/.login) source ~/.login; /bin/sh -c 'export -p' >! $sess_tmp"
|
||||||
|
. "$sess_tmp"
|
||||||
|
rm -f "$sess_tmp"
|
||||||
|
;;
|
||||||
|
*/fish)
|
||||||
|
[ -f "$CONFIG_DIRECTORY"/profile ] && . "$CONFIG_DIRECTORY"/profile
|
||||||
|
[ -f "$HOME"/.profile ] && . "$HOME"/.profile
|
||||||
|
sess_tmp=$(mktemp /tmp/sess-env-XXXXXX)
|
||||||
|
$SHELL --login -c "/bin/sh -c 'export -p' > $sess_tmp"
|
||||||
|
. "$sess_tmp"
|
||||||
|
rm -f "$sess_tmp"
|
||||||
|
;;
|
||||||
|
*) # Plain sh, ksh, and anything we do not know.
|
||||||
|
[ -f "$CONFIG_DIRECTORY"/profile ] && . "$CONFIG_DIRECTORY"/profile
|
||||||
|
[ -f "$HOME"/.profile ] && . "$HOME"/.profile
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
if [ "$XDG_SESSION_TYPE" = "x11" ]; then
|
||||||
|
[ -f "$CONFIG_DIRECTORY"/xprofile ] && . "$CONFIG_DIRECTORY"/xprofile
|
||||||
|
[ -f "$HOME"/.xprofile ] && . "$HOME"/.xprofile
|
||||||
|
|
||||||
|
# run all system xinitrc shell scripts.
|
||||||
|
if [ -d "$CONFIG_DIRECTORY"/X11/xinit/xinitrc.d ]; then
|
||||||
|
for i in "$CONFIG_DIRECTORY"/X11/xinit/xinitrc.d/* ; do
|
||||||
|
if [ -x "$i" ]; then
|
||||||
|
. "$i"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Load Xsession scripts
|
||||||
|
# OPTIONFILE, USERXSESSION, USERXSESSIONRC and ALTUSERXSESSION are required
|
||||||
|
# by the scripts to work
|
||||||
|
xsessionddir="$CONFIG_DIRECTORY"/X11/Xsession.d
|
||||||
|
export OPTIONFILE="$CONFIG_DIRECTORY"/X11/Xsession.options
|
||||||
|
export USERXSESSION="$HOME"/.xsession
|
||||||
|
export USERXSESSIONRC="$HOME"/.xsessionrc
|
||||||
|
export ALTUSERXSESSION="$HOME"/.Xsession
|
||||||
|
|
||||||
|
if [ -d "$xsessionddir" ]; then
|
||||||
|
for i in $(ls "$xsessionddir"); do
|
||||||
|
script="$xsessionddir/$i"
|
||||||
|
echo "Loading X session script $script"
|
||||||
|
if [ -r "$script" ] && [ -f "$script" ] && expr "$i" : '^[[:alnum:]_-]\+$' > /dev/null; then
|
||||||
|
. "$script"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -f "$USERXSESSION" ]; then
|
||||||
|
. "$USERXSESSION"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -d "$CONFIG_DIRECTORY"/X11/Xresources ]; then
|
||||||
|
for i in "$CONFIG_DIRECTORY"/X11/Xresources/*; do
|
||||||
|
[ -f "$i" ] && xrdb -merge "$i"
|
||||||
|
done
|
||||||
|
elif [ -f "$CONFIG_DIRECTORY"/X11/Xresources ]; then
|
||||||
|
xrdb -merge "$CONFIG_DIRECTORY"/X11/Xresources
|
||||||
|
fi
|
||||||
|
[ -f "$HOME"/.Xresources ] && xrdb -merge "$HOME"/.Xresources
|
||||||
|
[ -f "$XDG_CONFIG_HOME"/X11/Xresources ] && xrdb -merge "$XDG_CONFIG_HOME"/X11/Xresources
|
||||||
|
fi
|
||||||
|
|
||||||
|
exec "$@"
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
{
|
|
||||||
pam
|
|
||||||
Memcheck:Leak
|
|
||||||
...
|
|
||||||
obj:/usr/lib/libpam.so.0.84.2
|
|
||||||
...
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
termbox
|
|
||||||
Memcheck:Leak
|
|
||||||
...
|
|
||||||
fun:tb_init
|
|
||||||
...
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
libc/dynamic
|
|
||||||
Memcheck:Leak
|
|
||||||
...
|
|
||||||
fun:_dl_catch_exception
|
|
||||||
...
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
libc/groups
|
|
||||||
Memcheck:Leak
|
|
||||||
...
|
|
||||||
fun:initgroups
|
|
||||||
...
|
|
||||||
}
|
|
||||||
@@ -1,54 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
# wayland-session - run as user
|
|
||||||
# Copyright (C) 2015-2016 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com>
|
|
||||||
|
|
||||||
# This file is extracted from kde-workspace (kdm/kfrontend/genkdmconf.c)
|
|
||||||
# Copyright (C) 2001-2005 Oswald Buddenhagen <ossi@kde.org>
|
|
||||||
|
|
||||||
# Note that the respective logout scripts are not sourced.
|
|
||||||
case $SHELL in
|
|
||||||
*/bash)
|
|
||||||
[ -z "$BASH" ] && exec $SHELL $0 "$@"
|
|
||||||
set +o posix
|
|
||||||
[ -f /etc/profile ] && . /etc/profile
|
|
||||||
if [ -f $HOME/.bash_profile ]; then
|
|
||||||
. $HOME/.bash_profile
|
|
||||||
elif [ -f $HOME/.bash_login ]; then
|
|
||||||
. $HOME/.bash_login
|
|
||||||
elif [ -f $HOME/.profile ]; then
|
|
||||||
. $HOME/.profile
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
*/zsh)
|
|
||||||
[ -z "$ZSH_NAME" ] && exec $SHELL $0 "$@"
|
|
||||||
[ -d /etc/zsh ] && zdir=/etc/zsh || zdir=/etc
|
|
||||||
zhome=${ZDOTDIR:-$HOME}
|
|
||||||
# zshenv is always sourced automatically.
|
|
||||||
[ -f $zdir/zprofile ] && . $zdir/zprofile
|
|
||||||
[ -f $zhome/.zprofile ] && . $zhome/.zprofile
|
|
||||||
[ -f $zdir/zlogin ] && . $zdir/zlogin
|
|
||||||
[ -f $zhome/.zlogin ] && . $zhome/.zlogin
|
|
||||||
emulate -R sh
|
|
||||||
;;
|
|
||||||
*/csh|*/tcsh)
|
|
||||||
# [t]cshrc is always sourced automatically.
|
|
||||||
# Note that sourcing csh.login after .cshrc is non-standard.
|
|
||||||
wlsess_tmp=`mktemp /tmp/wlsess-env-XXXXXX`
|
|
||||||
$SHELL -c "if (-f /etc/csh.login) source /etc/csh.login; if (-f ~/.login) source ~/.login; /bin/sh -c 'export -p' >! $wlsess_tmp"
|
|
||||||
. $wlsess_tmp
|
|
||||||
rm -f $wlsess_tmp
|
|
||||||
;;
|
|
||||||
*/fish)
|
|
||||||
[ -f /etc/profile ] && . /etc/profile
|
|
||||||
xsess_tmp=`mktemp /tmp/xsess-env-XXXXXX`
|
|
||||||
$SHELL --login -c "/bin/sh -c 'export -p' > $xsess_tmp"
|
|
||||||
. $xsess_tmp
|
|
||||||
rm -f $xsess_tmp
|
|
||||||
;;
|
|
||||||
*) # Plain sh, ksh, and anything we do not know.
|
|
||||||
[ -f /etc/profile ] && . /etc/profile
|
|
||||||
[ -f $HOME/.profile ] && . $HOME/.profile
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
exec "$@"
|
|
||||||
103
res/xsetup.sh
103
res/xsetup.sh
@@ -1,103 +0,0 @@
|
|||||||
#! /bin/sh
|
|
||||||
# Xsession - run as user
|
|
||||||
# Copyright (C) 2016 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com>
|
|
||||||
|
|
||||||
# This file is extracted from kde-workspace (kdm/kfrontend/genkdmconf.c)
|
|
||||||
# Copyright (C) 2001-2005 Oswald Buddenhagen <ossi@kde.org>
|
|
||||||
|
|
||||||
# Note that the respective logout scripts are not sourced.
|
|
||||||
case $SHELL in
|
|
||||||
*/bash)
|
|
||||||
[ -z "$BASH" ] && exec $SHELL $0 "$@"
|
|
||||||
set +o posix
|
|
||||||
[ -f /etc/profile ] && . /etc/profile
|
|
||||||
if [ -f $HOME/.bash_profile ]; then
|
|
||||||
. $HOME/.bash_profile
|
|
||||||
elif [ -f $HOME/.bash_login ]; then
|
|
||||||
. $HOME/.bash_login
|
|
||||||
elif [ -f $HOME/.profile ]; then
|
|
||||||
. $HOME/.profile
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
*/zsh)
|
|
||||||
[ -z "$ZSH_NAME" ] && exec $SHELL $0 "$@"
|
|
||||||
[ -d /etc/zsh ] && zdir=/etc/zsh || zdir=/etc
|
|
||||||
zhome=${ZDOTDIR:-$HOME}
|
|
||||||
# zshenv is always sourced automatically.
|
|
||||||
[ -f $zdir/zprofile ] && . $zdir/zprofile
|
|
||||||
[ -f $zhome/.zprofile ] && . $zhome/.zprofile
|
|
||||||
[ -f $zdir/zlogin ] && . $zdir/zlogin
|
|
||||||
[ -f $zhome/.zlogin ] && . $zhome/.zlogin
|
|
||||||
emulate -R sh
|
|
||||||
;;
|
|
||||||
*/csh|*/tcsh)
|
|
||||||
# [t]cshrc is always sourced automatically.
|
|
||||||
# Note that sourcing csh.login after .cshrc is non-standard.
|
|
||||||
xsess_tmp=`mktemp /tmp/xsess-env-XXXXXX`
|
|
||||||
$SHELL -c "if (-f /etc/csh.login) source /etc/csh.login; if (-f ~/.login) source ~/.login; /bin/sh -c 'export -p' >! $xsess_tmp"
|
|
||||||
. $xsess_tmp
|
|
||||||
rm -f $xsess_tmp
|
|
||||||
;;
|
|
||||||
*/fish)
|
|
||||||
[ -f /etc/profile ] && . /etc/profile
|
|
||||||
xsess_tmp=`mktemp /tmp/xsess-env-XXXXXX`
|
|
||||||
$SHELL --login -c "/bin/sh -c 'export -p' > $xsess_tmp"
|
|
||||||
. $xsess_tmp
|
|
||||||
rm -f $xsess_tmp
|
|
||||||
;;
|
|
||||||
*) # Plain sh, ksh, and anything we do not know.
|
|
||||||
[ -f /etc/profile ] && . /etc/profile
|
|
||||||
[ -f $HOME/.profile ] && . $HOME/.profile
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
[ -f /etc/xprofile ] && . /etc/xprofile
|
|
||||||
[ -f $HOME/.xprofile ] && . $HOME/.xprofile
|
|
||||||
|
|
||||||
# run all system xinitrc shell scripts.
|
|
||||||
if [ -d /etc/X11/xinit/xinitrc.d ]; then
|
|
||||||
for i in /etc/X11/xinit/xinitrc.d/* ; do
|
|
||||||
if [ -x "$i" ]; then
|
|
||||||
. "$i"
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Load Xsession scripts
|
|
||||||
# OPTIONFILE, USERXSESSION, USERXSESSIONRC and ALTUSERXSESSION are required
|
|
||||||
# by the scripts to work
|
|
||||||
xsessionddir="/etc/X11/Xsession.d"
|
|
||||||
OPTIONFILE=/etc/X11/Xsession.options
|
|
||||||
USERXSESSION=$HOME/.xsession
|
|
||||||
USERXSESSIONRC=$HOME/.xsessionrc
|
|
||||||
ALTUSERXSESSION=$HOME/.Xsession
|
|
||||||
|
|
||||||
if [ -d "$xsessionddir" ]; then
|
|
||||||
for i in `ls $xsessionddir`; do
|
|
||||||
script="$xsessionddir/$i"
|
|
||||||
echo "Loading X session script $script"
|
|
||||||
if [ -r "$script" -a -f "$script" ] && expr "$i" : '^[[:alnum:]_-]\+$' > /dev/null; then
|
|
||||||
. "$script"
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ -d /etc/X11/Xresources ]; then
|
|
||||||
for i in /etc/X11/Xresources/*; do
|
|
||||||
[ -f $i ] && xrdb -merge $i
|
|
||||||
done
|
|
||||||
elif [ -f /etc/X11/Xresources ]; then
|
|
||||||
xrdb -merge /etc/X11/Xresources
|
|
||||||
fi
|
|
||||||
[ -f $HOME/.Xresources ] && xrdb -merge $HOME/.Xresources
|
|
||||||
[ -f $XDG_CONFIG_HOME/X11/Xresources ] && xrdb -merge $XDG_CONFIG_HOME/X11/Xresources
|
|
||||||
|
|
||||||
if [ -f "$USERXSESSION" ]; then
|
|
||||||
. "$USERXSESSION"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ -z "$*" ]; then
|
|
||||||
exec xmessage -center -buttons OK:0 -default OK "Sorry, $DESKTOP_SESSION is no valid session."
|
|
||||||
else
|
|
||||||
exec $@
|
|
||||||
fi
|
|
||||||
21
src/Environment.zig
Normal file
21
src/Environment.zig
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
const enums = @import("enums.zig");
|
||||||
|
const ini = @import("zigini");
|
||||||
|
|
||||||
|
const DisplayServer = enums.DisplayServer;
|
||||||
|
const Ini = ini.Ini;
|
||||||
|
|
||||||
|
pub const DesktopEntry = struct {
|
||||||
|
Exec: []const u8 = "",
|
||||||
|
Name: [:0]const u8 = "",
|
||||||
|
DesktopNames: ?[:0]u8 = null,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const Entry = struct { @"Desktop Entry": DesktopEntry = .{} };
|
||||||
|
|
||||||
|
entry_ini: ?Ini(Entry) = null,
|
||||||
|
name: [:0]const u8 = "",
|
||||||
|
xdg_session_desktop: ?[:0]const u8 = null,
|
||||||
|
xdg_desktop_names: ?[:0]const u8 = null,
|
||||||
|
cmd: []const u8 = "",
|
||||||
|
specifier: []const u8 = "",
|
||||||
|
display_server: DisplayServer = .wayland,
|
||||||
@@ -9,7 +9,7 @@ const ErrorHandler = packed struct {
|
|||||||
|
|
||||||
const SharedError = @This();
|
const SharedError = @This();
|
||||||
|
|
||||||
data: []align(std.mem.page_size) u8,
|
data: []align(std.heap.page_size_min) u8,
|
||||||
|
|
||||||
pub fn init() !SharedError {
|
pub fn init() !SharedError {
|
||||||
const data = try std.posix.mmap(null, @sizeOf(ErrorHandler), std.posix.PROT.READ | std.posix.PROT.WRITE, .{ .TYPE = .SHARED, .ANONYMOUS = true }, -1, 0);
|
const data = try std.posix.mmap(null, @sizeOf(ErrorHandler), std.posix.PROT.READ | std.posix.PROT.WRITE, .{ .TYPE = .SHARED, .ANONYMOUS = true }, -1, 0);
|
||||||
|
|||||||
86
src/animations/ColorMix.zig
Normal file
86
src/animations/ColorMix.zig
Normal file
@@ -0,0 +1,86 @@
|
|||||||
|
const std = @import("std");
|
||||||
|
const Animation = @import("../tui/Animation.zig");
|
||||||
|
const Cell = @import("../tui/Cell.zig");
|
||||||
|
const TerminalBuffer = @import("../tui/TerminalBuffer.zig");
|
||||||
|
|
||||||
|
const ColorMix = @This();
|
||||||
|
|
||||||
|
const math = std.math;
|
||||||
|
const Vec2 = @Vector(2, f32);
|
||||||
|
|
||||||
|
const time_scale: f32 = 0.01;
|
||||||
|
const palette_len: usize = 12;
|
||||||
|
|
||||||
|
fn length(vec: Vec2) f32 {
|
||||||
|
return math.sqrt(vec[0] * vec[0] + vec[1] * vec[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
terminal_buffer: *TerminalBuffer,
|
||||||
|
frames: u64,
|
||||||
|
pattern_cos_mod: f32,
|
||||||
|
pattern_sin_mod: f32,
|
||||||
|
palette: [palette_len]Cell,
|
||||||
|
|
||||||
|
pub fn init(terminal_buffer: *TerminalBuffer, col1: u32, col2: u32, col3: u32) ColorMix {
|
||||||
|
return .{
|
||||||
|
.terminal_buffer = terminal_buffer,
|
||||||
|
.frames = 0,
|
||||||
|
.pattern_cos_mod = terminal_buffer.random.float(f32) * math.pi * 2.0,
|
||||||
|
.pattern_sin_mod = terminal_buffer.random.float(f32) * math.pi * 2.0,
|
||||||
|
.palette = [palette_len]Cell{
|
||||||
|
Cell.init(0x2588, col1, col2),
|
||||||
|
Cell.init(0x2593, col1, col2),
|
||||||
|
Cell.init(0x2592, col1, col2),
|
||||||
|
Cell.init(0x2591, col1, col2),
|
||||||
|
Cell.init(0x2588, col2, col3),
|
||||||
|
Cell.init(0x2593, col2, col3),
|
||||||
|
Cell.init(0x2592, col2, col3),
|
||||||
|
Cell.init(0x2591, col2, col3),
|
||||||
|
Cell.init(0x2588, col3, col1),
|
||||||
|
Cell.init(0x2593, col3, col1),
|
||||||
|
Cell.init(0x2592, col3, col1),
|
||||||
|
Cell.init(0x2591, col3, col1),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn animation(self: *ColorMix) Animation {
|
||||||
|
return Animation.init(self, deinit, realloc, draw);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deinit(_: *ColorMix) void {}
|
||||||
|
|
||||||
|
fn realloc(_: *ColorMix) anyerror!void {}
|
||||||
|
|
||||||
|
fn draw(self: *ColorMix) void {
|
||||||
|
self.frames +%= 1;
|
||||||
|
const time: f32 = @as(f32, @floatFromInt(self.frames)) * time_scale;
|
||||||
|
|
||||||
|
for (0..self.terminal_buffer.width) |x| {
|
||||||
|
for (0..self.terminal_buffer.height) |y| {
|
||||||
|
const xi: i32 = @intCast(x);
|
||||||
|
const yi: i32 = @intCast(y);
|
||||||
|
const wi: i32 = @intCast(self.terminal_buffer.width);
|
||||||
|
const hi: i32 = @intCast(self.terminal_buffer.height);
|
||||||
|
|
||||||
|
var uv: Vec2 = .{
|
||||||
|
@as(f32, @floatFromInt(xi * 2 - wi)) / @as(f32, @floatFromInt(self.terminal_buffer.height * 2)),
|
||||||
|
@as(f32, @floatFromInt(yi * 2 - hi)) / @as(f32, @floatFromInt(self.terminal_buffer.height)),
|
||||||
|
};
|
||||||
|
|
||||||
|
var uv2: Vec2 = @splat(uv[0] + uv[1]);
|
||||||
|
|
||||||
|
for (0..3) |_| {
|
||||||
|
uv2 += uv + @as(Vec2, @splat(length(uv)));
|
||||||
|
uv += @as(Vec2, @splat(0.5)) * Vec2{
|
||||||
|
math.cos(self.pattern_cos_mod + uv2[1] * 0.2 + time * 0.1),
|
||||||
|
math.sin(self.pattern_sin_mod + uv2[0] - time * 0.1),
|
||||||
|
};
|
||||||
|
uv -= @splat(1.0 * math.cos(uv[0] + uv[1]) - math.sin(uv[0] * 0.7 - uv[1]));
|
||||||
|
}
|
||||||
|
|
||||||
|
const cell = self.palette[@as(usize, @intFromFloat(math.floor(length(uv) * 5.0))) % palette_len];
|
||||||
|
cell.put(x, y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,35 +1,19 @@
|
|||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const Allocator = std.mem.Allocator;
|
const Allocator = std.mem.Allocator;
|
||||||
|
const Animation = @import("../tui/Animation.zig");
|
||||||
|
const Cell = @import("../tui/Cell.zig");
|
||||||
const TerminalBuffer = @import("../tui/TerminalBuffer.zig");
|
const TerminalBuffer = @import("../tui/TerminalBuffer.zig");
|
||||||
const utils = @import("../tui/utils.zig");
|
|
||||||
|
|
||||||
const interop = @import("../interop.zig");
|
|
||||||
const termbox = interop.termbox;
|
|
||||||
|
|
||||||
const Doom = @This();
|
const Doom = @This();
|
||||||
|
|
||||||
pub const STEPS = 13;
|
pub const STEPS = 12;
|
||||||
pub const FIRE = [_]termbox.tb_cell{
|
|
||||||
utils.initCell(' ', 9, 0),
|
|
||||||
utils.initCell(0x2591, 2, 0), // Red
|
|
||||||
utils.initCell(0x2592, 2, 0), // Red
|
|
||||||
utils.initCell(0x2593, 2, 0), // Red
|
|
||||||
utils.initCell(0x2588, 2, 0), // Red
|
|
||||||
utils.initCell(0x2591, 4, 2), // Yellow
|
|
||||||
utils.initCell(0x2592, 4, 2), // Yellow
|
|
||||||
utils.initCell(0x2593, 4, 2), // Yellow
|
|
||||||
utils.initCell(0x2588, 4, 2), // Yellow
|
|
||||||
utils.initCell(0x2591, 8, 4), // White
|
|
||||||
utils.initCell(0x2592, 8, 4), // White
|
|
||||||
utils.initCell(0x2593, 8, 4), // White
|
|
||||||
utils.initCell(0x2588, 8, 4), // White
|
|
||||||
};
|
|
||||||
|
|
||||||
allocator: Allocator,
|
allocator: Allocator,
|
||||||
terminal_buffer: *TerminalBuffer,
|
terminal_buffer: *TerminalBuffer,
|
||||||
buffer: []u8,
|
buffer: []u8,
|
||||||
|
fire: [STEPS + 1]Cell,
|
||||||
|
|
||||||
pub fn init(allocator: Allocator, terminal_buffer: *TerminalBuffer) !Doom {
|
pub fn init(allocator: Allocator, terminal_buffer: *TerminalBuffer, top_color: u32, middle_color: u32, bottom_color: u32) !Doom {
|
||||||
const buffer = try allocator.alloc(u8, terminal_buffer.width * terminal_buffer.height);
|
const buffer = try allocator.alloc(u8, terminal_buffer.width * terminal_buffer.height);
|
||||||
initBuffer(buffer, terminal_buffer.width);
|
initBuffer(buffer, terminal_buffer.width);
|
||||||
|
|
||||||
@@ -37,48 +21,66 @@ pub fn init(allocator: Allocator, terminal_buffer: *TerminalBuffer) !Doom {
|
|||||||
.allocator = allocator,
|
.allocator = allocator,
|
||||||
.terminal_buffer = terminal_buffer,
|
.terminal_buffer = terminal_buffer,
|
||||||
.buffer = buffer,
|
.buffer = buffer,
|
||||||
|
.fire = [_]Cell{
|
||||||
|
Cell.init(' ', TerminalBuffer.Color.DEFAULT, TerminalBuffer.Color.DEFAULT),
|
||||||
|
Cell.init(0x2591, top_color, TerminalBuffer.Color.DEFAULT),
|
||||||
|
Cell.init(0x2592, top_color, TerminalBuffer.Color.DEFAULT),
|
||||||
|
Cell.init(0x2593, top_color, TerminalBuffer.Color.DEFAULT),
|
||||||
|
Cell.init(0x2588, top_color, TerminalBuffer.Color.DEFAULT),
|
||||||
|
Cell.init(0x2591, middle_color, top_color),
|
||||||
|
Cell.init(0x2592, middle_color, top_color),
|
||||||
|
Cell.init(0x2593, middle_color, top_color),
|
||||||
|
Cell.init(0x2588, middle_color, top_color),
|
||||||
|
Cell.init(0x2591, bottom_color, middle_color),
|
||||||
|
Cell.init(0x2592, bottom_color, middle_color),
|
||||||
|
Cell.init(0x2593, bottom_color, middle_color),
|
||||||
|
Cell.init(0x2588, bottom_color, middle_color),
|
||||||
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn deinit(self: Doom) void {
|
pub fn animation(self: *Doom) Animation {
|
||||||
|
return Animation.init(self, deinit, realloc, draw);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deinit(self: *Doom) void {
|
||||||
self.allocator.free(self.buffer);
|
self.allocator.free(self.buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn realloc(self: *Doom) !void {
|
fn realloc(self: *Doom) anyerror!void {
|
||||||
const buffer = try self.allocator.realloc(self.buffer, self.terminal_buffer.width * self.terminal_buffer.height);
|
const buffer = try self.allocator.realloc(self.buffer, self.terminal_buffer.width * self.terminal_buffer.height);
|
||||||
initBuffer(buffer, self.terminal_buffer.width);
|
initBuffer(buffer, self.terminal_buffer.width);
|
||||||
self.buffer = buffer;
|
self.buffer = buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn draw(self: Doom) void {
|
fn draw(self: *Doom) void {
|
||||||
for (0..self.terminal_buffer.width) |x| {
|
for (0..self.terminal_buffer.width) |x| {
|
||||||
|
// We start from 1 so that we always have the topmost line when spreading fire
|
||||||
for (1..self.terminal_buffer.height) |y| {
|
for (1..self.terminal_buffer.height) |y| {
|
||||||
const source = y * self.terminal_buffer.width + x;
|
// Get current cell
|
||||||
const random = (self.terminal_buffer.random.int(u16) % 7) & 3;
|
const from = y * self.terminal_buffer.width + x;
|
||||||
|
const cell_index = self.buffer[from];
|
||||||
|
|
||||||
var dest = (source - @min(source, random)) + 1;
|
// Spread fire
|
||||||
if (self.terminal_buffer.width > dest) dest = 0 else dest -= self.terminal_buffer.width;
|
const propagate = self.terminal_buffer.random.int(u1);
|
||||||
|
const to = from - self.terminal_buffer.width; // Get the line above
|
||||||
|
|
||||||
const buffer_source = self.buffer[source];
|
self.buffer[to] = if (cell_index > 0) cell_index - propagate else cell_index;
|
||||||
const buffer_dest_offset = random & 1;
|
|
||||||
|
|
||||||
if (buffer_source < buffer_dest_offset) continue;
|
// Put the cell
|
||||||
|
const cell = self.fire[cell_index];
|
||||||
var buffer_dest = buffer_source - buffer_dest_offset;
|
cell.put(x, y);
|
||||||
if (buffer_dest > 12) buffer_dest = 0;
|
|
||||||
self.buffer[dest] = @intCast(buffer_dest);
|
|
||||||
|
|
||||||
self.terminal_buffer.buffer[dest] = FIRE[buffer_dest];
|
|
||||||
self.terminal_buffer.buffer[source] = FIRE[buffer_source];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn initBuffer(buffer: []u8, width: u64) void {
|
fn initBuffer(buffer: []u8, width: usize) void {
|
||||||
const length = buffer.len - width;
|
const length = buffer.len - width;
|
||||||
const slice_start = buffer[0..length];
|
const slice_start = buffer[0..length];
|
||||||
const slice_end = buffer[length..];
|
const slice_end = buffer[length..];
|
||||||
|
|
||||||
|
// Initialize the framebuffer in black, except for the "fire source" as the
|
||||||
|
// last color
|
||||||
@memset(slice_start, 0);
|
@memset(slice_start, 0);
|
||||||
@memset(slice_end, STEPS - 1);
|
@memset(slice_end, STEPS);
|
||||||
}
|
}
|
||||||
|
|||||||
14
src/animations/Dummy.zig
Normal file
14
src/animations/Dummy.zig
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
const std = @import("std");
|
||||||
|
const Animation = @import("../tui/Animation.zig");
|
||||||
|
|
||||||
|
const Dummy = @This();
|
||||||
|
|
||||||
|
pub fn animation(self: *Dummy) Animation {
|
||||||
|
return Animation.init(self, deinit, realloc, draw);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deinit(_: *Dummy) void {}
|
||||||
|
|
||||||
|
fn realloc(_: *Dummy) anyerror!void {}
|
||||||
|
|
||||||
|
fn draw(_: *Dummy) void {}
|
||||||
@@ -1,41 +1,43 @@
|
|||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const Allocator = std.mem.Allocator;
|
const Animation = @import("../tui/Animation.zig");
|
||||||
const Random = std.rand.Random;
|
const Cell = @import("../tui/Cell.zig");
|
||||||
const TerminalBuffer = @import("../tui/TerminalBuffer.zig");
|
const TerminalBuffer = @import("../tui/TerminalBuffer.zig");
|
||||||
|
|
||||||
const interop = @import("../interop.zig");
|
const Allocator = std.mem.Allocator;
|
||||||
const termbox = interop.termbox;
|
const Random = std.Random;
|
||||||
|
|
||||||
pub const FRAME_DELAY: u64 = 8;
|
pub const FRAME_DELAY: usize = 8;
|
||||||
|
|
||||||
// Allowed codepoints
|
|
||||||
pub const MIN_CODEPOINT: isize = 33;
|
|
||||||
pub const MAX_CODEPOINT: isize = 123 - MIN_CODEPOINT;
|
|
||||||
|
|
||||||
// Characters change mid-scroll
|
// Characters change mid-scroll
|
||||||
pub const MID_SCROLL_CHANGE = true;
|
pub const MID_SCROLL_CHANGE = true;
|
||||||
|
|
||||||
|
const DOT_HEAD_COLOR: u32 = @intCast(TerminalBuffer.Color.WHITE | TerminalBuffer.Styling.BOLD);
|
||||||
|
|
||||||
const Matrix = @This();
|
const Matrix = @This();
|
||||||
|
|
||||||
pub const Dot = struct {
|
pub const Dot = struct {
|
||||||
value: isize,
|
value: ?usize,
|
||||||
is_head: bool,
|
is_head: bool,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const Line = struct {
|
pub const Line = struct {
|
||||||
space: isize,
|
space: usize,
|
||||||
length: isize,
|
length: usize,
|
||||||
update: isize,
|
update: usize,
|
||||||
};
|
};
|
||||||
|
|
||||||
allocator: Allocator,
|
allocator: Allocator,
|
||||||
terminal_buffer: *TerminalBuffer,
|
terminal_buffer: *TerminalBuffer,
|
||||||
dots: []Dot,
|
dots: []Dot,
|
||||||
lines: []Line,
|
lines: []Line,
|
||||||
frame: u64,
|
frame: usize,
|
||||||
count: u64,
|
count: usize,
|
||||||
|
fg: u32,
|
||||||
|
min_codepoint: u16,
|
||||||
|
max_codepoint: u16,
|
||||||
|
default_cell: Cell,
|
||||||
|
|
||||||
pub fn init(allocator: Allocator, terminal_buffer: *TerminalBuffer) !Matrix {
|
pub fn init(allocator: Allocator, terminal_buffer: *TerminalBuffer, fg: u32, min_codepoint: u16, max_codepoint: u16) !Matrix {
|
||||||
const dots = try allocator.alloc(Dot, terminal_buffer.width * (terminal_buffer.height + 1));
|
const dots = try allocator.alloc(Dot, terminal_buffer.width * (terminal_buffer.height + 1));
|
||||||
const lines = try allocator.alloc(Line, terminal_buffer.width);
|
const lines = try allocator.alloc(Line, terminal_buffer.width);
|
||||||
|
|
||||||
@@ -48,15 +50,23 @@ pub fn init(allocator: Allocator, terminal_buffer: *TerminalBuffer) !Matrix {
|
|||||||
.lines = lines,
|
.lines = lines,
|
||||||
.frame = 3,
|
.frame = 3,
|
||||||
.count = 0,
|
.count = 0,
|
||||||
|
.fg = fg,
|
||||||
|
.min_codepoint = min_codepoint,
|
||||||
|
.max_codepoint = max_codepoint - min_codepoint,
|
||||||
|
.default_cell = .{ .ch = ' ', .fg = fg, .bg = terminal_buffer.bg },
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn deinit(self: Matrix) void {
|
pub fn animation(self: *Matrix) Animation {
|
||||||
|
return Animation.init(self, deinit, realloc, draw);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deinit(self: *Matrix) void {
|
||||||
self.allocator.free(self.dots);
|
self.allocator.free(self.dots);
|
||||||
self.allocator.free(self.lines);
|
self.allocator.free(self.lines);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn realloc(self: *Matrix) !void {
|
fn realloc(self: *Matrix) anyerror!void {
|
||||||
const dots = try self.allocator.realloc(self.dots, self.terminal_buffer.width * (self.terminal_buffer.height + 1));
|
const dots = try self.allocator.realloc(self.dots, self.terminal_buffer.width * (self.terminal_buffer.height + 1));
|
||||||
const lines = try self.allocator.realloc(self.lines, self.terminal_buffer.width);
|
const lines = try self.allocator.realloc(self.lines, self.terminal_buffer.width);
|
||||||
|
|
||||||
@@ -66,7 +76,7 @@ pub fn realloc(self: *Matrix) !void {
|
|||||||
self.lines = lines;
|
self.lines = lines;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn draw(self: *Matrix) void {
|
fn draw(self: *Matrix) void {
|
||||||
const buf_height = self.terminal_buffer.height;
|
const buf_height = self.terminal_buffer.height;
|
||||||
const buf_width = self.terminal_buffer.width;
|
const buf_width = self.terminal_buffer.width;
|
||||||
self.count += 1;
|
self.count += 1;
|
||||||
@@ -75,31 +85,31 @@ pub fn draw(self: *Matrix) void {
|
|||||||
if (self.frame > 4) self.frame = 1;
|
if (self.frame > 4) self.frame = 1;
|
||||||
self.count = 0;
|
self.count = 0;
|
||||||
|
|
||||||
var x: u64 = 0;
|
var x: usize = 0;
|
||||||
while (x < self.terminal_buffer.width) : (x += 2) {
|
while (x < self.terminal_buffer.width) : (x += 2) {
|
||||||
var tail: u64 = 0;
|
var tail: usize = 0;
|
||||||
var line = &self.lines[x];
|
var line = &self.lines[x];
|
||||||
if (self.frame <= line.update) continue;
|
if (self.frame <= line.update) continue;
|
||||||
|
|
||||||
if (self.dots[x].value == -1 and self.dots[self.terminal_buffer.width + x].value == ' ') {
|
if (self.dots[x].value == null and self.dots[self.terminal_buffer.width + x].value == ' ') {
|
||||||
if (line.space > 0) {
|
if (line.space > 0) {
|
||||||
line.space -= 1;
|
line.space -= 1;
|
||||||
} else {
|
} else {
|
||||||
const randint = self.terminal_buffer.random.int(i16);
|
const randint = self.terminal_buffer.random.int(u16);
|
||||||
const h: isize = @intCast(self.terminal_buffer.height);
|
const h = self.terminal_buffer.height;
|
||||||
line.length = @mod(randint, h - 3) + 3;
|
line.length = @mod(randint, h - 3) + 3;
|
||||||
self.dots[x].value = @mod(randint, MAX_CODEPOINT) + MIN_CODEPOINT;
|
self.dots[x].value = @mod(randint, self.max_codepoint) + self.min_codepoint;
|
||||||
line.space = @mod(randint, h + 1);
|
line.space = @mod(randint, h + 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var y: u64 = 0;
|
var y: usize = 0;
|
||||||
var first_col = true;
|
var first_col = true;
|
||||||
var seg_len: u64 = 0;
|
var seg_len: u64 = 0;
|
||||||
height_it: while (y <= buf_height) : (y += 1) {
|
height_it: while (y <= buf_height) : (y += 1) {
|
||||||
var dot = &self.dots[buf_width * y + x];
|
var dot = &self.dots[buf_width * y + x];
|
||||||
// Skip over spaces
|
// Skip over spaces
|
||||||
while (y <= buf_height and (dot.value == ' ' or dot.value == -1)) {
|
while (y <= buf_height and (dot.value == ' ' or dot.value == null)) {
|
||||||
y += 1;
|
y += 1;
|
||||||
if (y > buf_height) break :height_it;
|
if (y > buf_height) break :height_it;
|
||||||
dot = &self.dots[buf_width * y + x];
|
dot = &self.dots[buf_width * y + x];
|
||||||
@@ -108,12 +118,12 @@ pub fn draw(self: *Matrix) void {
|
|||||||
// Find the head of this column
|
// Find the head of this column
|
||||||
tail = y;
|
tail = y;
|
||||||
seg_len = 0;
|
seg_len = 0;
|
||||||
while (y <= buf_height and dot.value != ' ' and dot.value != -1) {
|
while (y <= buf_height and dot.value != ' ' and dot.value != null) {
|
||||||
dot.is_head = false;
|
dot.is_head = false;
|
||||||
if (MID_SCROLL_CHANGE) {
|
if (MID_SCROLL_CHANGE) {
|
||||||
const randint = self.terminal_buffer.random.int(i16);
|
const randint = self.terminal_buffer.random.int(u16);
|
||||||
if (@mod(randint, 8) == 0) {
|
if (@mod(randint, 8) == 0) {
|
||||||
dot.value = @mod(randint, MAX_CODEPOINT) + MIN_CODEPOINT;
|
dot.value = @mod(randint, self.max_codepoint) + self.min_codepoint;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -127,53 +137,50 @@ pub fn draw(self: *Matrix) void {
|
|||||||
dot = &self.dots[buf_width * y + x];
|
dot = &self.dots[buf_width * y + x];
|
||||||
}
|
}
|
||||||
|
|
||||||
const randint = self.terminal_buffer.random.int(i16);
|
const randint = self.terminal_buffer.random.int(u16);
|
||||||
dot.value = @mod(randint, MAX_CODEPOINT) + MIN_CODEPOINT;
|
dot.value = @mod(randint, self.max_codepoint) + self.min_codepoint;
|
||||||
dot.is_head = true;
|
dot.is_head = true;
|
||||||
|
|
||||||
if (seg_len > line.length or !first_col) {
|
if (seg_len > line.length or !first_col) {
|
||||||
self.dots[buf_width * tail + x].value = ' ';
|
self.dots[buf_width * tail + x].value = ' ';
|
||||||
self.dots[x].value = -1;
|
self.dots[x].value = null;
|
||||||
}
|
}
|
||||||
first_col = false;
|
first_col = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var x: u64 = 0;
|
var x: usize = 0;
|
||||||
while (x < buf_width) : (x += 2) {
|
while (x < buf_width) : (x += 2) {
|
||||||
var y: u64 = 1;
|
var y: usize = 1;
|
||||||
while (y <= self.terminal_buffer.height) : (y += 1) {
|
while (y <= self.terminal_buffer.height) : (y += 1) {
|
||||||
const dot = self.dots[buf_width * y + x];
|
const dot = self.dots[buf_width * y + x];
|
||||||
var fg: u16 = @intCast(termbox.TB_GREEN);
|
const cell = if (dot.value == null or dot.value == ' ') self.default_cell else Cell{
|
||||||
|
.ch = @intCast(dot.value.?),
|
||||||
|
.fg = if (dot.is_head) DOT_HEAD_COLOR else self.fg,
|
||||||
|
.bg = self.terminal_buffer.bg,
|
||||||
|
};
|
||||||
|
|
||||||
if (dot.value == -1 or dot.value == ' ') {
|
cell.put(x, y - 1);
|
||||||
_ = termbox.tb_set_cell(@intCast(x), @intCast(y - 1), ' ', fg, termbox.TB_DEFAULT);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dot.is_head) fg = @intCast(termbox.TB_WHITE | termbox.TB_BOLD);
|
|
||||||
_ = termbox.tb_set_cell(@intCast(x), @intCast(y - 1), @intCast(dot.value), fg, termbox.TB_DEFAULT);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn initBuffers(dots: []Dot, lines: []Line, width: u64, height: u64, random: Random) void {
|
fn initBuffers(dots: []Dot, lines: []Line, width: usize, height: usize, random: Random) void {
|
||||||
var y: u64 = 0;
|
var y: usize = 0;
|
||||||
while (y <= height) : (y += 1) {
|
while (y <= height) : (y += 1) {
|
||||||
var x: u64 = 0;
|
var x: usize = 0;
|
||||||
while (x < width) : (x += 2) {
|
while (x < width) : (x += 2) {
|
||||||
dots[y * width + x].value = -1;
|
dots[y * width + x].value = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var x: u64 = 0;
|
var x: usize = 0;
|
||||||
while (x < width) : (x += 2) {
|
while (x < width) : (x += 2) {
|
||||||
var line = lines[x];
|
var line = lines[x];
|
||||||
const h: isize = @intCast(height);
|
line.space = @mod(random.int(u16), height) + 1;
|
||||||
line.space = @mod(random.int(i16), h) + 1;
|
line.length = @mod(random.int(u16), height - 3) + 3;
|
||||||
line.length = @mod(random.int(i16), h - 3) + 3;
|
line.update = @mod(random.int(u16), 3) + 1;
|
||||||
line.update = @mod(random.int(i16), 3) + 1;
|
|
||||||
lines[x] = line;
|
lines[x] = line;
|
||||||
|
|
||||||
dots[width + x].value = ' ';
|
dots[width + x].value = ' ';
|
||||||
|
|||||||
283
src/auth.zig
283
src/auth.zig
@@ -1,15 +1,28 @@
|
|||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
|
const build_options = @import("build_options");
|
||||||
|
const builtin = @import("builtin");
|
||||||
const enums = @import("enums.zig");
|
const enums = @import("enums.zig");
|
||||||
|
const Environment = @import("Environment.zig");
|
||||||
const interop = @import("interop.zig");
|
const interop = @import("interop.zig");
|
||||||
const TerminalBuffer = @import("tui/TerminalBuffer.zig");
|
|
||||||
const Desktop = @import("tui/components/Desktop.zig");
|
|
||||||
const Text = @import("tui/components/Text.zig");
|
|
||||||
const Config = @import("config/Config.zig");
|
|
||||||
const Allocator = std.mem.Allocator;
|
|
||||||
const utmp = interop.utmp;
|
|
||||||
const Utmp = utmp.utmp;
|
|
||||||
const SharedError = @import("SharedError.zig");
|
const SharedError = @import("SharedError.zig");
|
||||||
|
|
||||||
|
const Allocator = std.mem.Allocator;
|
||||||
|
const Md5 = std.crypto.hash.Md5;
|
||||||
|
const utmp = interop.utmp;
|
||||||
|
const Utmp = utmp.utmpx;
|
||||||
|
|
||||||
|
pub const AuthOptions = struct {
|
||||||
|
tty: u8,
|
||||||
|
service_name: [:0]const u8,
|
||||||
|
path: ?[:0]const u8,
|
||||||
|
session_log: []const u8,
|
||||||
|
xauth_cmd: []const u8,
|
||||||
|
setup_cmd: []const u8,
|
||||||
|
login_cmd: ?[]const u8,
|
||||||
|
x_cmd: []const u8,
|
||||||
|
session_pid: std.posix.pid_t,
|
||||||
|
};
|
||||||
|
|
||||||
var xorg_pid: std.posix.pid_t = 0;
|
var xorg_pid: std.posix.pid_t = 0;
|
||||||
pub fn xorgSignalHandler(i: c_int) callconv(.C) void {
|
pub fn xorgSignalHandler(i: c_int) callconv(.C) void {
|
||||||
if (xorg_pid > 0) _ = std.c.kill(xorg_pid, i);
|
if (xorg_pid > 0) _ = std.c.kill(xorg_pid, i);
|
||||||
@@ -20,13 +33,16 @@ pub fn sessionSignalHandler(i: c_int) callconv(.C) void {
|
|||||||
if (child_pid > 0) _ = std.c.kill(child_pid, i);
|
if (child_pid > 0) _ = std.c.kill(child_pid, i);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn authenticate(config: Config, current_environment: Desktop.Environment, login: [:0]const u8, password: [:0]const u8) !void {
|
pub fn authenticate(options: AuthOptions, current_environment: Environment, login: [:0]const u8, password: [:0]const u8) !void {
|
||||||
var tty_buffer: [2]u8 = undefined;
|
var tty_buffer: [3]u8 = undefined;
|
||||||
const tty_str = try std.fmt.bufPrintZ(&tty_buffer, "{d}", .{config.tty});
|
const tty_str = try std.fmt.bufPrintZ(&tty_buffer, "{d}", .{options.tty});
|
||||||
|
|
||||||
|
var pam_tty_buffer: [6]u8 = undefined;
|
||||||
|
const pam_tty_str = try std.fmt.bufPrintZ(&pam_tty_buffer, "tty{d}", .{options.tty});
|
||||||
|
|
||||||
// Set the XDG environment variables
|
// Set the XDG environment variables
|
||||||
setXdgSessionEnv(current_environment.display_server);
|
setXdgSessionEnv(current_environment.display_server);
|
||||||
try setXdgEnv(tty_str, current_environment.xdg_session_desktop, current_environment.xdg_desktop_names orelse "");
|
try setXdgEnv(tty_str, current_environment.xdg_session_desktop, current_environment.xdg_desktop_names);
|
||||||
|
|
||||||
// Open the PAM session
|
// Open the PAM session
|
||||||
var credentials = [_:null]?[*:0]const u8{ login, password };
|
var credentials = [_:null]?[*:0]const u8{ login, password };
|
||||||
@@ -37,10 +53,14 @@ pub fn authenticate(config: Config, current_environment: Desktop.Environment, lo
|
|||||||
};
|
};
|
||||||
var handle: ?*interop.pam.pam_handle = undefined;
|
var handle: ?*interop.pam.pam_handle = undefined;
|
||||||
|
|
||||||
var status = interop.pam.pam_start(config.service_name.ptr, null, &conv, &handle);
|
var status = interop.pam.pam_start(options.service_name, null, &conv, &handle);
|
||||||
if (status != interop.pam.PAM_SUCCESS) return pamDiagnose(status);
|
if (status != interop.pam.PAM_SUCCESS) return pamDiagnose(status);
|
||||||
defer _ = interop.pam.pam_end(handle, status);
|
defer _ = interop.pam.pam_end(handle, status);
|
||||||
|
|
||||||
|
// Set PAM_TTY as the current TTY. This is required in case it isn't being set by another PAM module
|
||||||
|
status = interop.pam.pam_set_item(handle, interop.pam.PAM_TTY, pam_tty_str.ptr);
|
||||||
|
if (status != interop.pam.PAM_SUCCESS) return pamDiagnose(status);
|
||||||
|
|
||||||
// Do the PAM routine
|
// Do the PAM routine
|
||||||
status = interop.pam.pam_authenticate(handle, 0);
|
status = interop.pam.pam_authenticate(handle, 0);
|
||||||
if (status != interop.pam.PAM_SUCCESS) return pamDiagnose(status);
|
if (status != interop.pam.PAM_SUCCESS) return pamDiagnose(status);
|
||||||
@@ -56,19 +76,19 @@ pub fn authenticate(config: Config, current_environment: Desktop.Environment, lo
|
|||||||
if (status != interop.pam.PAM_SUCCESS) return pamDiagnose(status);
|
if (status != interop.pam.PAM_SUCCESS) return pamDiagnose(status);
|
||||||
defer status = interop.pam.pam_close_session(handle, 0);
|
defer status = interop.pam.pam_close_session(handle, 0);
|
||||||
|
|
||||||
var pwd: *interop.passwd = undefined;
|
var pwd: *interop.pwd.passwd = undefined;
|
||||||
{
|
{
|
||||||
defer interop.endpwent();
|
defer interop.pwd.endpwent();
|
||||||
|
|
||||||
// Get password structure from username
|
// Get password structure from username
|
||||||
pwd = interop.getpwnam(login.ptr) orelse return error.GetPasswordNameFailed;
|
pwd = interop.pwd.getpwnam(login) orelse return error.GetPasswordNameFailed;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set user shell if it hasn't already been set
|
// Set user shell if it hasn't already been set
|
||||||
if (pwd.pw_shell[0] == 0) {
|
if (pwd.pw_shell == null) {
|
||||||
interop.setusershell();
|
interop.unistd.setusershell();
|
||||||
pwd.pw_shell = interop.getusershell();
|
pwd.pw_shell = interop.unistd.getusershell();
|
||||||
interop.endusershell();
|
interop.unistd.endusershell();
|
||||||
}
|
}
|
||||||
|
|
||||||
var shared_err = try SharedError.init();
|
var shared_err = try SharedError.init();
|
||||||
@@ -76,7 +96,7 @@ pub fn authenticate(config: Config, current_environment: Desktop.Environment, lo
|
|||||||
|
|
||||||
child_pid = try std.posix.fork();
|
child_pid = try std.posix.fork();
|
||||||
if (child_pid == 0) {
|
if (child_pid == 0) {
|
||||||
startSession(config, pwd, handle, current_environment) catch |e| {
|
startSession(options, tty_str, pwd, handle, current_environment) catch |e| {
|
||||||
shared_err.writeError(e);
|
shared_err.writeError(e);
|
||||||
std.process.exit(1);
|
std.process.exit(1);
|
||||||
};
|
};
|
||||||
@@ -98,91 +118,113 @@ pub fn authenticate(config: Config, current_environment: Desktop.Environment, lo
|
|||||||
.mask = std.posix.empty_sigset,
|
.mask = std.posix.empty_sigset,
|
||||||
.flags = 0,
|
.flags = 0,
|
||||||
};
|
};
|
||||||
try std.posix.sigaction(std.posix.SIG.TERM, &act, null);
|
std.posix.sigaction(std.posix.SIG.TERM, &act, null);
|
||||||
|
|
||||||
try addUtmpEntry(&entry, pwd.pw_name, child_pid);
|
try addUtmpEntry(&entry, pwd.pw_name.?, child_pid);
|
||||||
}
|
}
|
||||||
// Wait for the session to stop
|
// Wait for the session to stop
|
||||||
_ = std.posix.waitpid(child_pid, 0);
|
_ = std.posix.waitpid(child_pid, 0);
|
||||||
|
|
||||||
removeUtmpEntry(&entry);
|
removeUtmpEntry(&entry);
|
||||||
|
|
||||||
try resetTerminal(pwd.pw_shell, config.term_reset_cmd);
|
|
||||||
|
|
||||||
if (shared_err.readError()) |err| return err;
|
if (shared_err.readError()) |err| return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn startSession(
|
fn startSession(
|
||||||
config: Config,
|
options: AuthOptions,
|
||||||
pwd: *interop.passwd,
|
tty_str: [:0]u8,
|
||||||
|
pwd: *interop.pwd.passwd,
|
||||||
handle: ?*interop.pam.pam_handle,
|
handle: ?*interop.pam.pam_handle,
|
||||||
current_environment: Desktop.Environment,
|
current_environment: Environment,
|
||||||
) !void {
|
) !void {
|
||||||
const status = interop.initgroups(pwd.pw_name, pwd.pw_gid);
|
if (builtin.os.tag == .freebsd) {
|
||||||
if (status != 0) return error.GroupInitializationFailed;
|
// FreeBSD has initgroups() in unistd
|
||||||
|
const status = interop.unistd.initgroups(pwd.pw_name, pwd.pw_gid);
|
||||||
|
if (status != 0) return error.GroupInitializationFailed;
|
||||||
|
|
||||||
std.posix.setgid(pwd.pw_gid) catch return error.SetUserGidFailed;
|
// FreeBSD sets the GID and UID with setusercontext()
|
||||||
std.posix.setuid(pwd.pw_uid) catch return error.SetUserUidFailed;
|
const result = interop.pwd.setusercontext(null, pwd, pwd.pw_uid, interop.pwd.LOGIN_SETALL);
|
||||||
|
if (result != 0) return error.SetUserUidFailed;
|
||||||
|
} else {
|
||||||
|
const status = interop.grp.initgroups(pwd.pw_name, pwd.pw_gid);
|
||||||
|
if (status != 0) return error.GroupInitializationFailed;
|
||||||
|
|
||||||
|
std.posix.setgid(pwd.pw_gid) catch return error.SetUserGidFailed;
|
||||||
|
std.posix.setuid(pwd.pw_uid) catch return error.SetUserUidFailed;
|
||||||
|
}
|
||||||
|
|
||||||
// Set up the environment
|
// Set up the environment
|
||||||
try initEnv(pwd, config.path);
|
try initEnv(pwd, options.path);
|
||||||
|
|
||||||
|
// Reset the XDG environment variables
|
||||||
|
setXdgSessionEnv(current_environment.display_server);
|
||||||
|
try setXdgEnv(tty_str, current_environment.xdg_session_desktop, current_environment.xdg_desktop_names);
|
||||||
|
|
||||||
// Set the PAM variables
|
// Set the PAM variables
|
||||||
const pam_env_vars: ?[*:null]?[*:0]u8 = interop.pam.pam_getenvlist(handle);
|
const pam_env_vars: ?[*:null]?[*:0]u8 = interop.pam.pam_getenvlist(handle);
|
||||||
if (pam_env_vars == null) return error.GetEnvListFailed;
|
if (pam_env_vars == null) return error.GetEnvListFailed;
|
||||||
|
|
||||||
const env_list = std.mem.span(pam_env_vars.?);
|
const env_list = std.mem.span(pam_env_vars.?);
|
||||||
for (env_list) |env_var| _ = interop.putenv(env_var.?);
|
for (env_list) |env_var| _ = interop.stdlib.putenv(env_var);
|
||||||
|
|
||||||
|
// Change to the user's home directory
|
||||||
|
std.posix.chdirZ(pwd.pw_dir.?) catch return error.ChangeDirectoryFailed;
|
||||||
|
|
||||||
|
// Signal to the session process to give up control on the TTY
|
||||||
|
_ = std.posix.kill(options.session_pid, std.posix.SIG.CHLD) catch return error.TtyControlTransferFailed;
|
||||||
|
|
||||||
// Execute what the user requested
|
// Execute what the user requested
|
||||||
std.posix.chdirZ(pwd.pw_dir) catch return error.ChangeDirectoryFailed;
|
|
||||||
|
|
||||||
try resetTerminal(pwd.pw_shell, config.term_reset_cmd);
|
|
||||||
|
|
||||||
switch (current_environment.display_server) {
|
switch (current_environment.display_server) {
|
||||||
.wayland => try executeWaylandCmd(pwd.pw_shell, config.wayland_cmd, current_environment.cmd),
|
.wayland => try executeWaylandCmd(pwd.pw_shell.?, options, current_environment.cmd),
|
||||||
.shell => try executeShellCmd(pwd.pw_shell),
|
.shell => try executeShellCmd(pwd.pw_shell.?, options),
|
||||||
.xinitrc, .x11 => {
|
.xinitrc, .x11 => if (build_options.enable_x11_support) {
|
||||||
var vt_buf: [5]u8 = undefined;
|
var vt_buf: [5]u8 = undefined;
|
||||||
const vt = try std.fmt.bufPrint(&vt_buf, "vt{d}", .{config.tty});
|
const vt = try std.fmt.bufPrint(&vt_buf, "vt{d}", .{options.tty});
|
||||||
try executeX11Cmd(pwd.pw_shell, pwd.pw_dir, config, current_environment.cmd, vt);
|
try executeX11Cmd(pwd.pw_shell.?, pwd.pw_dir.?, options, current_environment.cmd, vt);
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn initEnv(pwd: *interop.passwd, path_env: ?[:0]const u8) !void {
|
fn initEnv(pwd: *interop.pwd.passwd, path_env: ?[:0]const u8) !void {
|
||||||
_ = interop.setenv("HOME", pwd.pw_dir, 1);
|
_ = interop.stdlib.setenv("HOME", pwd.pw_dir, 1);
|
||||||
_ = interop.setenv("PWD", pwd.pw_dir, 1);
|
_ = interop.stdlib.setenv("PWD", pwd.pw_dir, 1);
|
||||||
_ = interop.setenv("SHELL", pwd.pw_shell, 1);
|
_ = interop.stdlib.setenv("SHELL", pwd.pw_shell, 1);
|
||||||
_ = interop.setenv("USER", pwd.pw_name, 1);
|
_ = interop.stdlib.setenv("USER", pwd.pw_name, 1);
|
||||||
_ = interop.setenv("LOGNAME", pwd.pw_name, 1);
|
_ = interop.stdlib.setenv("LOGNAME", pwd.pw_name, 1);
|
||||||
|
|
||||||
if (path_env) |path| {
|
if (path_env) |path| {
|
||||||
const status = interop.setenv("PATH", path, 1);
|
const status = interop.stdlib.setenv("PATH", path, 1);
|
||||||
if (status != 0) return error.SetPathFailed;
|
if (status != 0) return error.SetPathFailed;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn setXdgSessionEnv(display_server: enums.DisplayServer) void {
|
fn setXdgSessionEnv(display_server: enums.DisplayServer) void {
|
||||||
_ = interop.setenv("XDG_SESSION_TYPE", switch (display_server) {
|
_ = interop.stdlib.setenv("XDG_SESSION_TYPE", switch (display_server) {
|
||||||
.wayland => "wayland",
|
.wayland => "wayland",
|
||||||
.shell => "tty",
|
.shell => "tty",
|
||||||
.xinitrc, .x11 => "x11",
|
.xinitrc, .x11 => "x11",
|
||||||
}, 0);
|
}, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn setXdgEnv(tty_str: [:0]u8, desktop_name: [:0]const u8, xdg_desktop_names: [:0]const u8) !void {
|
fn setXdgEnv(tty_str: [:0]u8, maybe_desktop_name: ?[:0]const u8, maybe_xdg_desktop_names: ?[:0]const u8) !void {
|
||||||
const uid = interop.getuid();
|
// The "/run/user/%d" directory is not available on FreeBSD. It is much
|
||||||
var uid_buffer: [10 + @sizeOf(u32) + 1]u8 = undefined;
|
// better to stick to the defaults and let applications using
|
||||||
const uid_str = try std.fmt.bufPrintZ(&uid_buffer, "/run/user/{d}", .{uid});
|
// XDG_RUNTIME_DIR to fall back to directories inside user's home
|
||||||
|
// directory.
|
||||||
|
if (builtin.os.tag != .freebsd) {
|
||||||
|
const uid = interop.unistd.getuid();
|
||||||
|
var uid_buffer: [32]u8 = undefined; // No UID can be larger than this
|
||||||
|
const uid_str = try std.fmt.bufPrintZ(&uid_buffer, "/run/user/{d}", .{uid});
|
||||||
|
|
||||||
_ = interop.setenv("XDG_CURRENT_DESKTOP", xdg_desktop_names.ptr, 0);
|
_ = interop.stdlib.setenv("XDG_RUNTIME_DIR", uid_str, 0);
|
||||||
_ = interop.setenv("XDG_RUNTIME_DIR", uid_str.ptr, 0);
|
}
|
||||||
_ = interop.setenv("XDG_SESSION_CLASS", "user", 0);
|
|
||||||
_ = interop.setenv("XDG_SESSION_ID", "1", 0);
|
if (maybe_xdg_desktop_names) |xdg_desktop_names| _ = interop.stdlib.setenv("XDG_CURRENT_DESKTOP", xdg_desktop_names, 0);
|
||||||
_ = interop.setenv("XDG_SESSION_DESKTOP", desktop_name.ptr, 0);
|
_ = interop.stdlib.setenv("XDG_SESSION_CLASS", "user", 0);
|
||||||
_ = interop.setenv("XDG_SEAT", "seat0", 0);
|
_ = interop.stdlib.setenv("XDG_SESSION_ID", "1", 0);
|
||||||
_ = interop.setenv("XDG_VTNR", tty_str.ptr, 0);
|
if (maybe_desktop_name) |desktop_name| _ = interop.stdlib.setenv("XDG_SESSION_DESKTOP", desktop_name, 0);
|
||||||
|
_ = interop.stdlib.setenv("XDG_SEAT", "seat0", 0);
|
||||||
|
_ = interop.stdlib.setenv("XDG_VTNR", tty_str, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn loginConv(
|
fn loginConv(
|
||||||
@@ -213,7 +255,7 @@ fn loginConv(
|
|||||||
status = interop.pam.PAM_BUF_ERR;
|
status = interop.pam.PAM_BUF_ERR;
|
||||||
break :set_credentials;
|
break :set_credentials;
|
||||||
};
|
};
|
||||||
response[i].resp = username.?.ptr;
|
response[i].resp = username.?;
|
||||||
},
|
},
|
||||||
interop.pam.PAM_PROMPT_ECHO_OFF => {
|
interop.pam.PAM_PROMPT_ECHO_OFF => {
|
||||||
const data: [*][*:0]u8 = @ptrCast(@alignCast(appdata_ptr));
|
const data: [*][*:0]u8 = @ptrCast(@alignCast(appdata_ptr));
|
||||||
@@ -221,7 +263,7 @@ fn loginConv(
|
|||||||
status = interop.pam.PAM_BUF_ERR;
|
status = interop.pam.PAM_BUF_ERR;
|
||||||
break :set_credentials;
|
break :set_credentials;
|
||||||
};
|
};
|
||||||
response[i].resp = password.?.ptr;
|
response[i].resp = password.?;
|
||||||
},
|
},
|
||||||
interop.pam.PAM_ERROR_MSG => {
|
interop.pam.PAM_ERROR_MSG => {
|
||||||
status = interop.pam.PAM_CONV_ERR;
|
status = interop.pam.PAM_CONV_ERR;
|
||||||
@@ -243,17 +285,6 @@ fn loginConv(
|
|||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn resetTerminal(shell: [*:0]const u8, term_reset_cmd: [:0]const u8) !void {
|
|
||||||
const pid = try std.posix.fork();
|
|
||||||
if (pid == 0) {
|
|
||||||
const args = [_:null]?[*:0]const u8{ shell, "-c", term_reset_cmd };
|
|
||||||
std.posix.execveZ(shell, &args, std.c.environ) catch {};
|
|
||||||
std.process.exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
_ = std.posix.waitpid(pid, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn getFreeDisplay() !u8 {
|
fn getFreeDisplay() !u8 {
|
||||||
var buf: [15]u8 = undefined;
|
var buf: [15]u8 = undefined;
|
||||||
var i: u8 = 0;
|
var i: u8 = 0;
|
||||||
@@ -327,49 +358,30 @@ fn createXauthFile(pwd: [:0]const u8) ![:0]const u8 {
|
|||||||
return xauthority;
|
return xauthority;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn mcookie(cmd: [:0]const u8) ![32]u8 {
|
fn mcookie() [Md5.digest_length * 2]u8 {
|
||||||
const pipe = try std.posix.pipe();
|
var buf: [4096]u8 = undefined;
|
||||||
defer std.posix.close(pipe[1]);
|
std.crypto.random.bytes(&buf);
|
||||||
|
|
||||||
const output = std.fs.File{ .handle = pipe[0] };
|
var out: [Md5.digest_length]u8 = undefined;
|
||||||
defer output.close();
|
Md5.hash(&buf, &out, .{});
|
||||||
|
|
||||||
const pid = try std.posix.fork();
|
return std.fmt.bytesToHex(&out, .lower);
|
||||||
if (pid == 0) {
|
|
||||||
std.posix.close(pipe[0]);
|
|
||||||
|
|
||||||
std.posix.dup2(pipe[1], std.posix.STDOUT_FILENO) catch std.process.exit(1);
|
|
||||||
std.posix.close(pipe[1]);
|
|
||||||
|
|
||||||
const args = [_:null]?[*:0]u8{};
|
|
||||||
std.posix.execveZ(cmd.ptr, &args, std.c.environ) catch {};
|
|
||||||
std.process.exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
const result = std.posix.waitpid(pid, 0);
|
|
||||||
|
|
||||||
if (result.status != 0) return error.McookieFailed;
|
|
||||||
|
|
||||||
var buf: [32]u8 = undefined;
|
|
||||||
const len = try output.read(&buf);
|
|
||||||
if (len != 32) return error.McookieFailed;
|
|
||||||
return buf;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn xauth(display_name: [:0]u8, shell: [*:0]const u8, pw_dir: [*:0]const u8, xauth_cmd: []const u8, mcookie_cmd: [:0]const u8) !void {
|
fn xauth(display_name: [:0]u8, shell: [*:0]const u8, pw_dir: [*:0]const u8, options: AuthOptions) !void {
|
||||||
var pwd_buf: [100]u8 = undefined;
|
var pwd_buf: [100]u8 = undefined;
|
||||||
const pwd = try std.fmt.bufPrintZ(&pwd_buf, "{s}", .{pw_dir});
|
const pwd = try std.fmt.bufPrintZ(&pwd_buf, "{s}", .{pw_dir});
|
||||||
|
|
||||||
const xauthority = try createXauthFile(pwd);
|
const xauthority = try createXauthFile(pwd);
|
||||||
_ = interop.setenv("XAUTHORITY", xauthority, 1);
|
_ = interop.stdlib.setenv("XAUTHORITY", xauthority, 1);
|
||||||
_ = interop.setenv("DISPLAY", display_name, 1);
|
_ = interop.stdlib.setenv("DISPLAY", display_name, 1);
|
||||||
|
|
||||||
const mcookie_output = try mcookie(mcookie_cmd);
|
const magic_cookie = mcookie();
|
||||||
|
|
||||||
const pid = try std.posix.fork();
|
const pid = try std.posix.fork();
|
||||||
if (pid == 0) {
|
if (pid == 0) {
|
||||||
var cmd_buffer: [1024]u8 = undefined;
|
var cmd_buffer: [1024]u8 = undefined;
|
||||||
const cmd_str = std.fmt.bufPrintZ(&cmd_buffer, "{s} add {s} . {s}", .{ xauth_cmd, display_name, mcookie_output }) catch std.process.exit(1);
|
const cmd_str = std.fmt.bufPrintZ(&cmd_buffer, "{s} add {s} . {s}", .{ options.xauth_cmd, display_name, magic_cookie }) catch std.process.exit(1);
|
||||||
const args = [_:null]?[*:0]const u8{ shell, "-c", cmd_str };
|
const args = [_:null]?[*:0]const u8{ shell, "-c", cmd_str };
|
||||||
std.posix.execveZ(shell, &args, std.c.environ) catch {};
|
std.posix.execveZ(shell, &args, std.c.environ) catch {};
|
||||||
std.process.exit(1);
|
std.process.exit(1);
|
||||||
@@ -379,28 +391,35 @@ fn xauth(display_name: [:0]u8, shell: [*:0]const u8, pw_dir: [*:0]const u8, xaut
|
|||||||
if (status.status != 0) return error.XauthFailed;
|
if (status.status != 0) return error.XauthFailed;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn executeShellCmd(shell: [*:0]const u8) !void {
|
fn executeShellCmd(shell: [*:0]const u8, options: AuthOptions) !void {
|
||||||
const args = [_:null]?[*:0]const u8{shell};
|
// We don't want to redirect stdout and stderr in a shell session
|
||||||
return std.posix.execveZ(shell, &args, std.c.environ);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn executeWaylandCmd(shell: [*:0]const u8, wayland_cmd: []const u8, desktop_cmd: []const u8) !void {
|
|
||||||
var cmd_buffer: [1024]u8 = undefined;
|
var cmd_buffer: [1024]u8 = undefined;
|
||||||
const cmd_str = try std.fmt.bufPrintZ(&cmd_buffer, "{s} {s}", .{ wayland_cmd, desktop_cmd });
|
const cmd_str = try std.fmt.bufPrintZ(&cmd_buffer, "{s} {s} {s}", .{ options.setup_cmd, options.login_cmd orelse "", shell });
|
||||||
const args = [_:null]?[*:0]const u8{ shell, "-c", cmd_str };
|
const args = [_:null]?[*:0]const u8{ shell, "-c", cmd_str };
|
||||||
return std.posix.execveZ(shell, &args, std.c.environ);
|
return std.posix.execveZ(shell, &args, std.c.environ);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn executeX11Cmd(shell: [*:0]const u8, pw_dir: [*:0]const u8, config: Config, desktop_cmd: []const u8, vt: []const u8) !void {
|
fn executeWaylandCmd(shell: [*:0]const u8, options: AuthOptions, desktop_cmd: []const u8) !void {
|
||||||
|
const log_file = try redirectStandardStreams(options.session_log, true);
|
||||||
|
defer log_file.close();
|
||||||
|
|
||||||
|
var cmd_buffer: [1024]u8 = undefined;
|
||||||
|
const cmd_str = try std.fmt.bufPrintZ(&cmd_buffer, "{s} {s} {s}", .{ options.setup_cmd, options.login_cmd orelse "", desktop_cmd });
|
||||||
|
const args = [_:null]?[*:0]const u8{ shell, "-c", cmd_str };
|
||||||
|
return std.posix.execveZ(shell, &args, std.c.environ);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn executeX11Cmd(shell: [*:0]const u8, pw_dir: [*:0]const u8, options: AuthOptions, desktop_cmd: []const u8, vt: []const u8) !void {
|
||||||
const display_num = try getFreeDisplay();
|
const display_num = try getFreeDisplay();
|
||||||
var buf: [5]u8 = undefined;
|
var buf: [5]u8 = undefined;
|
||||||
const display_name = try std.fmt.bufPrintZ(&buf, ":{d}", .{display_num});
|
const display_name = try std.fmt.bufPrintZ(&buf, ":{d}", .{display_num});
|
||||||
try xauth(display_name, shell, pw_dir, config.xauth_cmd, config.mcookie_cmd);
|
try xauth(display_name, shell, pw_dir, options);
|
||||||
|
|
||||||
const pid = try std.posix.fork();
|
const pid = try std.posix.fork();
|
||||||
if (pid == 0) {
|
if (pid == 0) {
|
||||||
var cmd_buffer: [1024]u8 = undefined;
|
var cmd_buffer: [1024]u8 = undefined;
|
||||||
const cmd_str = std.fmt.bufPrintZ(&cmd_buffer, "{s} {s} {s}", .{ config.x_cmd, display_name, vt }) catch std.process.exit(1);
|
const cmd_str = std.fmt.bufPrintZ(&cmd_buffer, "{s} {s} {s}", .{ options.x_cmd, display_name, vt }) catch std.process.exit(1);
|
||||||
const args = [_:null]?[*:0]const u8{ shell, "-c", cmd_str };
|
const args = [_:null]?[*:0]const u8{ shell, "-c", cmd_str };
|
||||||
std.posix.execveZ(shell, &args, std.c.environ) catch {};
|
std.posix.execveZ(shell, &args, std.c.environ) catch {};
|
||||||
std.process.exit(1);
|
std.process.exit(1);
|
||||||
@@ -423,7 +442,7 @@ fn executeX11Cmd(shell: [*:0]const u8, pw_dir: [*:0]const u8, config: Config, de
|
|||||||
xorg_pid = try std.posix.fork();
|
xorg_pid = try std.posix.fork();
|
||||||
if (xorg_pid == 0) {
|
if (xorg_pid == 0) {
|
||||||
var cmd_buffer: [1024]u8 = undefined;
|
var cmd_buffer: [1024]u8 = undefined;
|
||||||
const cmd_str = std.fmt.bufPrintZ(&cmd_buffer, "{s} {s}", .{ config.x_cmd_setup, desktop_cmd }) catch std.process.exit(1);
|
const cmd_str = std.fmt.bufPrintZ(&cmd_buffer, "{s} {s} {s}", .{ options.setup_cmd, options.login_cmd orelse "", desktop_cmd }) catch std.process.exit(1);
|
||||||
const args = [_:null]?[*:0]const u8{ shell, "-c", cmd_str };
|
const args = [_:null]?[*:0]const u8{ shell, "-c", cmd_str };
|
||||||
std.posix.execveZ(shell, &args, std.c.environ) catch {};
|
std.posix.execveZ(shell, &args, std.c.environ) catch {};
|
||||||
std.process.exit(1);
|
std.process.exit(1);
|
||||||
@@ -435,18 +454,28 @@ fn executeX11Cmd(shell: [*:0]const u8, pw_dir: [*:0]const u8, config: Config, de
|
|||||||
.mask = std.posix.empty_sigset,
|
.mask = std.posix.empty_sigset,
|
||||||
.flags = 0,
|
.flags = 0,
|
||||||
};
|
};
|
||||||
try std.posix.sigaction(std.posix.SIG.TERM, &act, null);
|
std.posix.sigaction(std.posix.SIG.TERM, &act, null);
|
||||||
|
|
||||||
_ = std.posix.waitpid(xorg_pid, 0);
|
_ = std.posix.waitpid(xorg_pid, 0);
|
||||||
interop.xcb.xcb_disconnect(xcb);
|
interop.xcb.xcb_disconnect(xcb);
|
||||||
|
|
||||||
std.posix.kill(x_pid, 0) catch return;
|
|
||||||
std.posix.kill(x_pid, std.posix.SIG.TERM) catch {};
|
std.posix.kill(x_pid, std.posix.SIG.TERM) catch {};
|
||||||
|
std.Thread.sleep(std.time.ns_per_s * 1); // Wait 1 second before sending SIGKILL
|
||||||
|
std.posix.kill(x_pid, std.posix.SIG.KILL) catch return;
|
||||||
|
|
||||||
var status: c_int = 0;
|
var status: c_int = 0;
|
||||||
_ = std.c.waitpid(x_pid, &status, 0);
|
_ = std.c.waitpid(x_pid, &status, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn redirectStandardStreams(session_log: []const u8, create: bool) !std.fs.File {
|
||||||
|
const log_file = if (create) (try std.fs.cwd().createFile(session_log, .{ .mode = 0o666 })) else (try std.fs.cwd().openFile(session_log, .{ .mode = .read_write }));
|
||||||
|
|
||||||
|
try std.posix.dup2(std.posix.STDOUT_FILENO, std.posix.STDERR_FILENO);
|
||||||
|
try std.posix.dup2(log_file.handle, std.posix.STDOUT_FILENO);
|
||||||
|
|
||||||
|
return log_file;
|
||||||
|
}
|
||||||
|
|
||||||
fn addUtmpEntry(entry: *Utmp, username: [*:0]const u8, pid: c_int) !void {
|
fn addUtmpEntry(entry: *Utmp, username: [*:0]const u8, pid: c_int) !void {
|
||||||
entry.ut_type = utmp.USER_PROCESS;
|
entry.ut_type = utmp.USER_PROCESS;
|
||||||
entry.ut_pid = pid;
|
entry.ut_pid = pid;
|
||||||
@@ -454,23 +483,23 @@ fn addUtmpEntry(entry: *Utmp, username: [*:0]const u8, pid: c_int) !void {
|
|||||||
var buf: [4096]u8 = undefined;
|
var buf: [4096]u8 = undefined;
|
||||||
const ttyname = try std.os.getFdPath(std.posix.STDIN_FILENO, &buf);
|
const ttyname = try std.os.getFdPath(std.posix.STDIN_FILENO, &buf);
|
||||||
|
|
||||||
var ttyname_buf: [32]u8 = undefined;
|
var ttyname_buf: [@sizeOf(@TypeOf(entry.ut_line))]u8 = undefined;
|
||||||
_ = try std.fmt.bufPrintZ(&ttyname_buf, "{s}", .{ttyname["/dev/".len..]});
|
_ = try std.fmt.bufPrintZ(&ttyname_buf, "{s}", .{ttyname["/dev/".len..]});
|
||||||
|
|
||||||
entry.ut_line = ttyname_buf;
|
entry.ut_line = ttyname_buf;
|
||||||
entry.ut_id = ttyname_buf["tty".len..7].*;
|
entry.ut_id = ttyname_buf["tty".len..7].*;
|
||||||
|
|
||||||
var username_buf: [32]u8 = undefined;
|
var username_buf: [@sizeOf(@TypeOf(entry.ut_user))]u8 = undefined;
|
||||||
_ = try std.fmt.bufPrintZ(&username_buf, "{s}", .{username});
|
_ = try std.fmt.bufPrintZ(&username_buf, "{s}", .{username});
|
||||||
|
|
||||||
entry.ut_user = username_buf;
|
entry.ut_user = username_buf;
|
||||||
|
|
||||||
var host: [256]u8 = undefined;
|
var host: [@sizeOf(@TypeOf(entry.ut_host))]u8 = undefined;
|
||||||
host[0] = 0;
|
host[0] = 0;
|
||||||
entry.ut_host = host;
|
entry.ut_host = host;
|
||||||
|
|
||||||
var tv: std.c.timeval = undefined;
|
var tv: interop.system_time.timeval = undefined;
|
||||||
_ = std.c.gettimeofday(&tv, null);
|
_ = interop.system_time.gettimeofday(&tv, null);
|
||||||
|
|
||||||
entry.ut_tv = .{
|
entry.ut_tv = .{
|
||||||
.tv_sec = @intCast(tv.tv_sec),
|
.tv_sec = @intCast(tv.tv_sec),
|
||||||
@@ -478,18 +507,18 @@ fn addUtmpEntry(entry: *Utmp, username: [*:0]const u8, pid: c_int) !void {
|
|||||||
};
|
};
|
||||||
entry.ut_addr_v6[0] = 0;
|
entry.ut_addr_v6[0] = 0;
|
||||||
|
|
||||||
utmp.setutent();
|
utmp.setutxent();
|
||||||
_ = utmp.pututline(entry);
|
_ = utmp.pututxline(entry);
|
||||||
utmp.endutent();
|
utmp.endutxent();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn removeUtmpEntry(entry: *Utmp) void {
|
fn removeUtmpEntry(entry: *Utmp) void {
|
||||||
entry.ut_type = utmp.DEAD_PROCESS;
|
entry.ut_type = utmp.DEAD_PROCESS;
|
||||||
entry.ut_line[0] = 0;
|
entry.ut_line[0] = 0;
|
||||||
entry.ut_user[0] = 0;
|
entry.ut_user[0] = 0;
|
||||||
utmp.setutent();
|
utmp.setutxent();
|
||||||
_ = utmp.pututline(entry);
|
_ = utmp.pututxline(entry);
|
||||||
utmp.endutent();
|
utmp.endutxent();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn pamDiagnose(status: c_int) anyerror {
|
fn pamDiagnose(status: c_int) anyerror {
|
||||||
|
|||||||
153
src/bigclock.zig
153
src/bigclock.zig
@@ -1,140 +1,57 @@
|
|||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const builtin = @import("builtin");
|
|
||||||
const interop = @import("interop.zig");
|
const interop = @import("interop.zig");
|
||||||
const utils = @import("tui/utils.zig");
|
const enums = @import("enums.zig");
|
||||||
|
const Lang = @import("bigclock/Lang.zig");
|
||||||
|
const en = @import("bigclock/en.zig");
|
||||||
|
const fa = @import("bigclock/fa.zig");
|
||||||
|
const Cell = @import("tui/Cell.zig");
|
||||||
|
|
||||||
const termbox = interop.termbox;
|
const Bigclock = enums.Bigclock;
|
||||||
|
pub const WIDTH = Lang.WIDTH;
|
||||||
|
pub const HEIGHT = Lang.HEIGHT;
|
||||||
|
pub const SIZE = Lang.SIZE;
|
||||||
|
|
||||||
const X: u32 = if (builtin.os.tag == .linux or builtin.os.tag.isBSD()) 0x2593 else '#';
|
pub fn clockCell(animate: bool, char: u8, fg: u32, bg: u32, bigclock: Bigclock) [SIZE]Cell {
|
||||||
const O: u32 = 0;
|
var cells: [SIZE]Cell = undefined;
|
||||||
|
|
||||||
pub const WIDTH = 5;
|
var tv: interop.system_time.timeval = undefined;
|
||||||
pub const HEIGHT = 5;
|
_ = interop.system_time.gettimeofday(&tv, null);
|
||||||
pub const SIZE = WIDTH * HEIGHT;
|
|
||||||
|
|
||||||
// zig fmt: off
|
const clock_chars = toBigNumber(if (animate and char == ':' and @divTrunc(tv.tv_usec, 500000) != 0) ' ' else char, bigclock);
|
||||||
const ZERO = [_]u21{
|
for (0..cells.len) |i| cells[i] = Cell.init(clock_chars[i], fg, bg);
|
||||||
X,X,X,X,X,
|
|
||||||
X,X,O,X,X,
|
|
||||||
X,X,O,X,X,
|
|
||||||
X,X,O,X,X,
|
|
||||||
X,X,X,X,X,
|
|
||||||
};
|
|
||||||
const ONE = [_]u21{
|
|
||||||
O,O,O,X,X,
|
|
||||||
O,O,O,X,X,
|
|
||||||
O,O,O,X,X,
|
|
||||||
O,O,O,X,X,
|
|
||||||
O,O,O,X,X,
|
|
||||||
};
|
|
||||||
const TWO = [_]u21{
|
|
||||||
X,X,X,X,X,
|
|
||||||
O,O,O,X,X,
|
|
||||||
X,X,X,X,X,
|
|
||||||
X,X,O,O,O,
|
|
||||||
X,X,X,X,X,
|
|
||||||
};
|
|
||||||
const THREE = [_]u21{
|
|
||||||
X,X,X,X,X,
|
|
||||||
O,O,O,X,X,
|
|
||||||
X,X,X,X,X,
|
|
||||||
O,O,O,X,X,
|
|
||||||
X,X,X,X,X,
|
|
||||||
};
|
|
||||||
const FOUR = [_]u21{
|
|
||||||
X,X,O,X,X,
|
|
||||||
X,X,O,X,X,
|
|
||||||
X,X,X,X,X,
|
|
||||||
O,O,O,X,X,
|
|
||||||
O,O,O,X,X,
|
|
||||||
};
|
|
||||||
const FIVE = [_]u21{
|
|
||||||
X,X,X,X,X,
|
|
||||||
X,X,O,O,O,
|
|
||||||
X,X,X,X,X,
|
|
||||||
O,O,O,X,X,
|
|
||||||
X,X,X,X,X,
|
|
||||||
};
|
|
||||||
const SIX = [_]u21{
|
|
||||||
X,X,X,X,X,
|
|
||||||
X,X,O,O,O,
|
|
||||||
X,X,X,X,X,
|
|
||||||
X,X,O,X,X,
|
|
||||||
X,X,X,X,X,
|
|
||||||
};
|
|
||||||
const SEVEN = [_]u21{
|
|
||||||
X,X,X,X,X,
|
|
||||||
O,O,O,X,X,
|
|
||||||
O,O,O,X,X,
|
|
||||||
O,O,O,X,X,
|
|
||||||
O,O,O,X,X,
|
|
||||||
};
|
|
||||||
const EIGHT = [_]u21{
|
|
||||||
X,X,X,X,X,
|
|
||||||
X,X,O,X,X,
|
|
||||||
X,X,X,X,X,
|
|
||||||
X,X,O,X,X,
|
|
||||||
X,X,X,X,X,
|
|
||||||
};
|
|
||||||
const NINE = [_]u21{
|
|
||||||
X,X,X,X,X,
|
|
||||||
X,X,O,X,X,
|
|
||||||
X,X,X,X,X,
|
|
||||||
O,O,O,X,X,
|
|
||||||
X,X,X,X,X,
|
|
||||||
};
|
|
||||||
const S = [_]u21{
|
|
||||||
O,O,O,O,O,
|
|
||||||
O,O,X,O,O,
|
|
||||||
O,O,O,O,O,
|
|
||||||
O,O,X,O,O,
|
|
||||||
O,O,O,O,O,
|
|
||||||
};
|
|
||||||
const E = [_]u21{
|
|
||||||
O,O,O,O,O,
|
|
||||||
O,O,O,O,O,
|
|
||||||
O,O,O,O,O,
|
|
||||||
O,O,O,O,O,
|
|
||||||
O,O,O,O,O,
|
|
||||||
};
|
|
||||||
// zig fmt: on
|
|
||||||
|
|
||||||
pub fn clockCell(animate: bool, char: u8, fg: u8, bg: u8) [SIZE]termbox.tb_cell {
|
|
||||||
var cells: [SIZE]termbox.tb_cell = undefined;
|
|
||||||
|
|
||||||
var tv: std.c.timeval = undefined;
|
|
||||||
_ = std.c.gettimeofday(&tv, null);
|
|
||||||
|
|
||||||
const clock_chars = toBigNumber(if (animate and char == ':' and @divTrunc(tv.tv_usec, 500000) != 0) ' ' else char);
|
|
||||||
for (0..cells.len) |i| cells[i] = utils.initCell(clock_chars[i], fg, bg);
|
|
||||||
|
|
||||||
return cells;
|
return cells;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn alphaBlit(buffer: [*]termbox.tb_cell, x: u64, y: u64, tb_width: u64, tb_height: u64, cells: [SIZE]termbox.tb_cell) void {
|
pub fn alphaBlit(x: usize, y: usize, tb_width: usize, tb_height: usize, cells: [SIZE]Cell) void {
|
||||||
if (x + WIDTH >= tb_width or y + HEIGHT >= tb_height) return;
|
if (x + WIDTH >= tb_width or y + HEIGHT >= tb_height) return;
|
||||||
|
|
||||||
for (0..HEIGHT) |yy| {
|
for (0..HEIGHT) |yy| {
|
||||||
for (0..WIDTH) |xx| {
|
for (0..WIDTH) |xx| {
|
||||||
const cell = cells[yy * WIDTH + xx];
|
const cell = cells[yy * WIDTH + xx];
|
||||||
if (cell.ch != 0) buffer[(y + yy) * tb_width + (x + xx)] = cell;
|
cell.put(x + xx, y + yy);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn toBigNumber(char: u8) []const u21 {
|
fn toBigNumber(char: u8, bigclock: Bigclock) [SIZE]u21 {
|
||||||
|
const locale_chars = switch (bigclock) {
|
||||||
|
.fa => fa.locale_chars,
|
||||||
|
.en => en.locale_chars,
|
||||||
|
.none => unreachable,
|
||||||
|
};
|
||||||
return switch (char) {
|
return switch (char) {
|
||||||
'0' => &ZERO,
|
'0' => locale_chars.ZERO,
|
||||||
'1' => &ONE,
|
'1' => locale_chars.ONE,
|
||||||
'2' => &TWO,
|
'2' => locale_chars.TWO,
|
||||||
'3' => &THREE,
|
'3' => locale_chars.THREE,
|
||||||
'4' => &FOUR,
|
'4' => locale_chars.FOUR,
|
||||||
'5' => &FIVE,
|
'5' => locale_chars.FIVE,
|
||||||
'6' => &SIX,
|
'6' => locale_chars.SIX,
|
||||||
'7' => &SEVEN,
|
'7' => locale_chars.SEVEN,
|
||||||
'8' => &EIGHT,
|
'8' => locale_chars.EIGHT,
|
||||||
'9' => &NINE,
|
'9' => locale_chars.NINE,
|
||||||
':' => &S,
|
':' => locale_chars.S,
|
||||||
else => &E,
|
else => locale_chars.E,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
23
src/bigclock/Lang.zig
Normal file
23
src/bigclock/Lang.zig
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
const builtin = @import("builtin");
|
||||||
|
|
||||||
|
pub const WIDTH = 5;
|
||||||
|
pub const HEIGHT = 5;
|
||||||
|
pub const SIZE = WIDTH * HEIGHT;
|
||||||
|
|
||||||
|
pub const X: u32 = if (builtin.os.tag == .linux or builtin.os.tag.isBSD()) 0x2593 else '#';
|
||||||
|
pub const O: u32 = 0;
|
||||||
|
|
||||||
|
pub const LocaleChars = struct {
|
||||||
|
ZERO: [SIZE]u21,
|
||||||
|
ONE: [SIZE]u21,
|
||||||
|
TWO: [SIZE]u21,
|
||||||
|
THREE: [SIZE]u21,
|
||||||
|
FOUR: [SIZE]u21,
|
||||||
|
FIVE: [SIZE]u21,
|
||||||
|
SIX: [SIZE]u21,
|
||||||
|
SEVEN: [SIZE]u21,
|
||||||
|
EIGHT: [SIZE]u21,
|
||||||
|
NINE: [SIZE]u21,
|
||||||
|
S: [SIZE]u21,
|
||||||
|
E: [SIZE]u21,
|
||||||
|
};
|
||||||
94
src/bigclock/en.zig
Normal file
94
src/bigclock/en.zig
Normal file
@@ -0,0 +1,94 @@
|
|||||||
|
const Lang = @import("Lang.zig");
|
||||||
|
|
||||||
|
const LocaleChars = Lang.LocaleChars;
|
||||||
|
const X = Lang.X;
|
||||||
|
const O = Lang.O;
|
||||||
|
|
||||||
|
// zig fmt: off
|
||||||
|
pub const locale_chars = LocaleChars{
|
||||||
|
.ZERO = [_]u21{
|
||||||
|
X,X,X,X,X,
|
||||||
|
X,X,O,X,X,
|
||||||
|
X,X,O,X,X,
|
||||||
|
X,X,O,X,X,
|
||||||
|
X,X,X,X,X,
|
||||||
|
},
|
||||||
|
.ONE = [_]u21{
|
||||||
|
O,O,O,X,X,
|
||||||
|
O,O,O,X,X,
|
||||||
|
O,O,O,X,X,
|
||||||
|
O,O,O,X,X,
|
||||||
|
O,O,O,X,X,
|
||||||
|
},
|
||||||
|
.TWO = [_]u21{
|
||||||
|
X,X,X,X,X,
|
||||||
|
O,O,O,X,X,
|
||||||
|
X,X,X,X,X,
|
||||||
|
X,X,O,O,O,
|
||||||
|
X,X,X,X,X,
|
||||||
|
},
|
||||||
|
.THREE = [_]u21{
|
||||||
|
X,X,X,X,X,
|
||||||
|
O,O,O,X,X,
|
||||||
|
X,X,X,X,X,
|
||||||
|
O,O,O,X,X,
|
||||||
|
X,X,X,X,X,
|
||||||
|
},
|
||||||
|
.FOUR = [_]u21{
|
||||||
|
X,X,O,X,X,
|
||||||
|
X,X,O,X,X,
|
||||||
|
X,X,X,X,X,
|
||||||
|
O,O,O,X,X,
|
||||||
|
O,O,O,X,X,
|
||||||
|
},
|
||||||
|
.FIVE = [_]u21{
|
||||||
|
X,X,X,X,X,
|
||||||
|
X,X,O,O,O,
|
||||||
|
X,X,X,X,X,
|
||||||
|
O,O,O,X,X,
|
||||||
|
X,X,X,X,X,
|
||||||
|
},
|
||||||
|
.SIX = [_]u21{
|
||||||
|
X,X,X,X,X,
|
||||||
|
X,X,O,O,O,
|
||||||
|
X,X,X,X,X,
|
||||||
|
X,X,O,X,X,
|
||||||
|
X,X,X,X,X,
|
||||||
|
},
|
||||||
|
.SEVEN = [_]u21{
|
||||||
|
X,X,X,X,X,
|
||||||
|
O,O,O,X,X,
|
||||||
|
O,O,O,X,X,
|
||||||
|
O,O,O,X,X,
|
||||||
|
O,O,O,X,X,
|
||||||
|
},
|
||||||
|
.EIGHT = [_]u21{
|
||||||
|
X,X,X,X,X,
|
||||||
|
X,X,O,X,X,
|
||||||
|
X,X,X,X,X,
|
||||||
|
X,X,O,X,X,
|
||||||
|
X,X,X,X,X,
|
||||||
|
},
|
||||||
|
.NINE = [_]u21{
|
||||||
|
X,X,X,X,X,
|
||||||
|
X,X,O,X,X,
|
||||||
|
X,X,X,X,X,
|
||||||
|
O,O,O,X,X,
|
||||||
|
X,X,X,X,X,
|
||||||
|
},
|
||||||
|
.S = [_]u21{
|
||||||
|
O,O,O,O,O,
|
||||||
|
O,O,X,O,O,
|
||||||
|
O,O,O,O,O,
|
||||||
|
O,O,X,O,O,
|
||||||
|
O,O,O,O,O,
|
||||||
|
},
|
||||||
|
.E = [_]u21{
|
||||||
|
O,O,O,O,O,
|
||||||
|
O,O,O,O,O,
|
||||||
|
O,O,O,O,O,
|
||||||
|
O,O,O,O,O,
|
||||||
|
O,O,O,O,O,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
// zig fmt: on
|
||||||
94
src/bigclock/fa.zig
Normal file
94
src/bigclock/fa.zig
Normal file
@@ -0,0 +1,94 @@
|
|||||||
|
const Lang = @import("Lang.zig");
|
||||||
|
|
||||||
|
const LocaleChars = Lang.LocaleChars;
|
||||||
|
const X = Lang.X;
|
||||||
|
const O = Lang.O;
|
||||||
|
|
||||||
|
// zig fmt: off
|
||||||
|
pub const locale_chars = LocaleChars{
|
||||||
|
.ZERO = [_]u21{
|
||||||
|
O,O,O,O,O,
|
||||||
|
O,O,X,O,O,
|
||||||
|
O,X,O,X,O,
|
||||||
|
O,O,X,O,O,
|
||||||
|
O,O,O,O,O,
|
||||||
|
},
|
||||||
|
.ONE = [_]u21{
|
||||||
|
O,O,X,O,O,
|
||||||
|
O,X,X,O,O,
|
||||||
|
O,O,X,O,O,
|
||||||
|
O,O,X,O,O,
|
||||||
|
O,O,X,O,O,
|
||||||
|
},
|
||||||
|
.TWO = [_]u21{
|
||||||
|
O,X,O,X,O,
|
||||||
|
O,X,X,X,O,
|
||||||
|
O,X,O,O,O,
|
||||||
|
O,X,O,O,O,
|
||||||
|
O,X,O,O,O,
|
||||||
|
},
|
||||||
|
.THREE = [_]u21{
|
||||||
|
X,O,X,O,X,
|
||||||
|
X,X,X,X,X,
|
||||||
|
X,O,O,O,O,
|
||||||
|
X,O,O,O,O,
|
||||||
|
X,O,O,O,O,
|
||||||
|
},
|
||||||
|
.FOUR = [_]u21{
|
||||||
|
O,X,O,X,X,
|
||||||
|
O,X,X,O,O,
|
||||||
|
O,X,X,X,X,
|
||||||
|
O,X,O,O,O,
|
||||||
|
O,X,O,O,O,
|
||||||
|
},
|
||||||
|
.FIVE = [_]u21{
|
||||||
|
O,O,X,X,O,
|
||||||
|
O,X,O,O,X,
|
||||||
|
X,O,O,O,X,
|
||||||
|
X,O,X,O,X,
|
||||||
|
O,X,O,X,O,
|
||||||
|
},
|
||||||
|
.SIX = [_]u21{
|
||||||
|
O,X,X,O,O,
|
||||||
|
O,X,O,O,X,
|
||||||
|
O,O,X,O,O,
|
||||||
|
O,X,O,O,O,
|
||||||
|
X,O,O,O,O,
|
||||||
|
},
|
||||||
|
.SEVEN = [_]u21{
|
||||||
|
X,O,O,O,X,
|
||||||
|
X,O,O,O,X,
|
||||||
|
O,X,O,X,O,
|
||||||
|
O,X,O,X,O,
|
||||||
|
O,O,X,O,O,
|
||||||
|
},
|
||||||
|
.EIGHT = [_]u21{
|
||||||
|
O,O,O,X,O,
|
||||||
|
O,O,X,O,X,
|
||||||
|
O,O,X,O,X,
|
||||||
|
O,X,O,O,X,
|
||||||
|
O,X,O,O,X,
|
||||||
|
},
|
||||||
|
.NINE = [_]u21{
|
||||||
|
O,X,X,X,O,
|
||||||
|
O,X,O,X,O,
|
||||||
|
O,X,X,X,O,
|
||||||
|
O,O,O,X,O,
|
||||||
|
O,O,O,X,O,
|
||||||
|
},
|
||||||
|
.S = [_]u21{
|
||||||
|
O,O,O,O,O,
|
||||||
|
O,O,X,O,O,
|
||||||
|
O,O,O,O,O,
|
||||||
|
O,O,X,O,O,
|
||||||
|
O,O,O,O,O,
|
||||||
|
},
|
||||||
|
.E = [_]u21{
|
||||||
|
O,O,O,O,O,
|
||||||
|
O,O,O,O,O,
|
||||||
|
O,O,O,O,O,
|
||||||
|
O,O,O,O,O,
|
||||||
|
O,O,O,O,O,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
// zig fmt: on
|
||||||
@@ -3,51 +3,68 @@ const enums = @import("../enums.zig");
|
|||||||
|
|
||||||
const Animation = enums.Animation;
|
const Animation = enums.Animation;
|
||||||
const Input = enums.Input;
|
const Input = enums.Input;
|
||||||
|
const ViMode = enums.ViMode;
|
||||||
|
const Bigclock = enums.Bigclock;
|
||||||
|
|
||||||
|
allow_empty_password: bool = true,
|
||||||
animation: Animation = .none,
|
animation: Animation = .none,
|
||||||
asterisk: u8 = '*',
|
animation_timeout_sec: u12 = 0,
|
||||||
bg: u8 = 0,
|
asterisk: ?u32 = '*',
|
||||||
bigclock: bool = false,
|
auth_fails: u64 = 10,
|
||||||
|
bg: u32 = 0x00000000,
|
||||||
|
bigclock: Bigclock = .none,
|
||||||
blank_box: bool = true,
|
blank_box: bool = true,
|
||||||
border_fg: u8 = 8,
|
border_fg: u32 = 0x00FFFFFF,
|
||||||
box_title: ?[]const u8 = null,
|
box_title: ?[]const u8 = null,
|
||||||
|
brightness_down_cmd: [:0]const u8 = build_options.prefix_directory ++ "/bin/brightnessctl -q s 10%-",
|
||||||
|
brightness_down_key: ?[]const u8 = "F5",
|
||||||
|
brightness_up_cmd: [:0]const u8 = build_options.prefix_directory ++ "/bin/brightnessctl -q s +10%",
|
||||||
|
brightness_up_key: ?[]const u8 = "F6",
|
||||||
clear_password: bool = false,
|
clear_password: bool = false,
|
||||||
clock: ?[:0]const u8 = null,
|
clock: ?[:0]const u8 = null,
|
||||||
console_dev: [:0]const u8 = "/dev/console",
|
cmatrix_fg: u32 = 0x0000FF00,
|
||||||
|
cmatrix_min_codepoint: u16 = 0x21,
|
||||||
|
cmatrix_max_codepoint: u16 = 0x7B,
|
||||||
|
colormix_col1: u32 = 0x00FF0000,
|
||||||
|
colormix_col2: u32 = 0x000000FF,
|
||||||
|
colormix_col3: u32 = 0x20000000,
|
||||||
|
console_dev: []const u8 = "/dev/console",
|
||||||
default_input: Input = .login,
|
default_input: Input = .login,
|
||||||
fg: u8 = 8,
|
doom_top_color: u32 = 0x00FF0000,
|
||||||
|
doom_middle_color: u32 = 0x00FFFF00,
|
||||||
|
doom_bottom_color: u32 = 0x00FFFFFF,
|
||||||
|
error_bg: u32 = 0x00000000,
|
||||||
|
error_fg: u32 = 0x01FF0000,
|
||||||
|
fg: u32 = 0x00FFFFFF,
|
||||||
hide_borders: bool = false,
|
hide_borders: bool = false,
|
||||||
hide_key_hints: bool = false,
|
hide_key_hints: bool = false,
|
||||||
initial_info_text: ?[]const u8 = null,
|
initial_info_text: ?[]const u8 = null,
|
||||||
input_len: u8 = 34,
|
input_len: u8 = 34,
|
||||||
lang: []const u8 = "en",
|
lang: []const u8 = "en",
|
||||||
load: bool = true,
|
load: bool = true,
|
||||||
|
login_cmd: ?[]const u8 = null,
|
||||||
|
logout_cmd: ?[]const u8 = null,
|
||||||
margin_box_h: u8 = 2,
|
margin_box_h: u8 = 2,
|
||||||
margin_box_v: u8 = 1,
|
margin_box_v: u8 = 1,
|
||||||
max_desktop_len: u8 = 100,
|
|
||||||
max_login_len: u8 = 255,
|
|
||||||
max_password_len: u8 = 255,
|
|
||||||
mcookie_cmd: [:0]const u8 = "/usr/bin/mcookie",
|
|
||||||
min_refresh_delta: u16 = 5,
|
min_refresh_delta: u16 = 5,
|
||||||
numlock: bool = false,
|
numlock: bool = false,
|
||||||
path: ?[:0]const u8 = "/sbin:/bin:/usr/local/sbin:/usr/local/bin:/usr/bin:/usr/sbin",
|
path: ?[:0]const u8 = "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
|
||||||
restart_cmd: []const u8 = "/sbin/shutdown -r now",
|
restart_cmd: []const u8 = "/sbin/shutdown -r now",
|
||||||
restart_key: []const u8 = "F2",
|
restart_key: []const u8 = "F2",
|
||||||
save: bool = true,
|
save: bool = true,
|
||||||
save_file: []const u8 = "/etc/ly/save",
|
|
||||||
service_name: [:0]const u8 = "ly",
|
service_name: [:0]const u8 = "ly",
|
||||||
|
session_log: []const u8 = "ly-session.log",
|
||||||
|
setup_cmd: []const u8 = build_options.config_directory ++ "/ly/setup.sh",
|
||||||
shutdown_cmd: []const u8 = "/sbin/shutdown -a now",
|
shutdown_cmd: []const u8 = "/sbin/shutdown -a now",
|
||||||
shutdown_key: []const u8 = "F1",
|
shutdown_key: []const u8 = "F1",
|
||||||
sleep_cmd: ?[]const u8 = null,
|
sleep_cmd: ?[]const u8 = null,
|
||||||
sleep_key: []const u8 = "F3",
|
sleep_key: []const u8 = "F3",
|
||||||
term_reset_cmd: [:0]const u8 = "/usr/bin/tput reset",
|
text_in_center: bool = false,
|
||||||
term_restore_cursor_cmd: []const u8 = "/usr/bin/tput cnorm",
|
tty: u8 = build_options.tty,
|
||||||
tty: u8 = 2,
|
vi_default_mode: ViMode = .normal,
|
||||||
vi_mode: bool = false,
|
vi_mode: bool = false,
|
||||||
wayland_cmd: []const u8 = build_options.data_directory ++ "/wsetup.sh",
|
waylandsessions: []const u8 = build_options.prefix_directory ++ "/share/wayland-sessions",
|
||||||
waylandsessions: []const u8 = "/usr/share/wayland-sessions",
|
x_cmd: []const u8 = build_options.prefix_directory ++ "/bin/X",
|
||||||
x_cmd: []const u8 = "/usr/bin/X",
|
xauth_cmd: []const u8 = build_options.prefix_directory ++ "/bin/xauth",
|
||||||
xinitrc: ?[]const u8 = "~/.xinitrc",
|
xinitrc: ?[]const u8 = "~/.xinitrc",
|
||||||
x_cmd_setup: []const u8 = build_options.data_directory ++ "/xsetup.sh",
|
xsessions: []const u8 = build_options.prefix_directory ++ "/share/xsessions",
|
||||||
xauth_cmd: []const u8 = "/usr/bin/xauth",
|
|
||||||
xsessions: []const u8 = "/usr/share/xsessions",
|
|
||||||
|
|||||||
@@ -1,16 +1,26 @@
|
|||||||
|
//
|
||||||
|
// NOTE: After editing this file, please run `/res/lang/normalize_lang_files.py`
|
||||||
|
// to update all the language files accordingly.
|
||||||
|
//
|
||||||
|
|
||||||
authenticating: []const u8 = "authenticating...",
|
authenticating: []const u8 = "authenticating...",
|
||||||
|
brightness_down: []const u8 = "decrease brightness",
|
||||||
|
brightness_up: []const u8 = "increase brightness",
|
||||||
capslock: []const u8 = "capslock",
|
capslock: []const u8 = "capslock",
|
||||||
err_alloc: []const u8 = "failed memory allocation",
|
err_alloc: []const u8 = "failed memory allocation",
|
||||||
err_bounds: []const u8 = "out-of-bounds index",
|
err_bounds: []const u8 = "out-of-bounds index",
|
||||||
|
err_brightness_change: []const u8 = "failed to change brightness",
|
||||||
err_chdir: []const u8 = "failed to open home folder",
|
err_chdir: []const u8 = "failed to open home folder",
|
||||||
|
err_config: []const u8 = "unable to parse config file",
|
||||||
err_console_dev: []const u8 = "failed to access console",
|
err_console_dev: []const u8 = "failed to access console",
|
||||||
err_dgn_oob: []const u8 = "log message",
|
err_dgn_oob: []const u8 = "log message",
|
||||||
err_domain: []const u8 = "invalid domain",
|
err_domain: []const u8 = "invalid domain",
|
||||||
|
err_empty_password: []const u8 = "empty password not allowed",
|
||||||
err_envlist: []const u8 = "failed to get envlist",
|
err_envlist: []const u8 = "failed to get envlist",
|
||||||
err_hostname: []const u8 = "failed to get hostname",
|
err_hostname: []const u8 = "failed to get hostname",
|
||||||
err_mcookie: []const u8 = "mcookie command failed",
|
|
||||||
err_mlock: []const u8 = "failed to lock password memory",
|
err_mlock: []const u8 = "failed to lock password memory",
|
||||||
err_null: []const u8 = "null pointer",
|
err_null: []const u8 = "null pointer",
|
||||||
|
err_numlock: []const u8 = "failed to set numlock",
|
||||||
err_pam: []const u8 = "pam transaction failed",
|
err_pam: []const u8 = "pam transaction failed",
|
||||||
err_pam_abort: []const u8 = "pam transaction aborted",
|
err_pam_abort: []const u8 = "pam transaction aborted",
|
||||||
err_pam_acct_expired: []const u8 = "account expired",
|
err_pam_acct_expired: []const u8 = "account expired",
|
||||||
@@ -32,6 +42,8 @@ err_perm_dir: []const u8 = "failed to change current directory",
|
|||||||
err_perm_group: []const u8 = "failed to downgrade group permissions",
|
err_perm_group: []const u8 = "failed to downgrade group permissions",
|
||||||
err_perm_user: []const u8 = "failed to downgrade user permissions",
|
err_perm_user: []const u8 = "failed to downgrade user permissions",
|
||||||
err_pwnam: []const u8 = "failed to get user info",
|
err_pwnam: []const u8 = "failed to get user info",
|
||||||
|
err_sleep: []const u8 = "failed to execute sleep command",
|
||||||
|
err_tty_ctrl: []const u8 = "tty control transfer failed",
|
||||||
err_unknown: []const u8 = "an unknown error occurred",
|
err_unknown: []const u8 = "an unknown error occurred",
|
||||||
err_user_gid: []const u8 = "failed to set user GID",
|
err_user_gid: []const u8 = "failed to set user GID",
|
||||||
err_user_init: []const u8 = "failed to initialize user",
|
err_user_init: []const u8 = "failed to initialize user",
|
||||||
@@ -43,6 +55,7 @@ err_xsessions_open: []const u8 = "failed to open sessions folder",
|
|||||||
insert: []const u8 = "insert",
|
insert: []const u8 = "insert",
|
||||||
login: []const u8 = "login:",
|
login: []const u8 = "login:",
|
||||||
logout: []const u8 = "logged out",
|
logout: []const u8 = "logged out",
|
||||||
|
no_x11_support: []const u8 = "x11 support disabled at compile-time",
|
||||||
normal: []const u8 = "normal",
|
normal: []const u8 = "normal",
|
||||||
numlock: []const u8 = "numlock",
|
numlock: []const u8 = "numlock",
|
||||||
other: []const u8 = "other",
|
other: []const u8 = "other",
|
||||||
@@ -52,5 +65,5 @@ shell: [:0]const u8 = "shell",
|
|||||||
shutdown: []const u8 = "shutdown",
|
shutdown: []const u8 = "shutdown",
|
||||||
sleep: []const u8 = "sleep",
|
sleep: []const u8 = "sleep",
|
||||||
wayland: []const u8 = "wayland",
|
wayland: []const u8 = "wayland",
|
||||||
xinitrc: [:0]const u8 = "xinitrc",
|
|
||||||
x11: []const u8 = "x11",
|
x11: []const u8 = "x11",
|
||||||
|
xinitrc: [:0]const u8 = "xinitrc",
|
||||||
|
|||||||
@@ -1,2 +1,2 @@
|
|||||||
user: ?[]const u8 = null,
|
user: ?[]const u8 = null,
|
||||||
session_index: ?u64 = null,
|
session_index: ?usize = null,
|
||||||
|
|||||||
@@ -1,30 +1,203 @@
|
|||||||
|
// The migrator ensures compatibility with <=0.6.0 configuration files
|
||||||
|
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const ini = @import("zigini");
|
const ini = @import("zigini");
|
||||||
const Save = @import("Save.zig");
|
const Save = @import("Save.zig");
|
||||||
|
const enums = @import("../enums.zig");
|
||||||
|
|
||||||
pub fn tryMigrateSaveFile(user_buf: *[32]u8, path: []const u8) Save {
|
const color_properties = [_][]const u8{
|
||||||
|
"bg",
|
||||||
|
"border_fg",
|
||||||
|
"cmatrix_fg",
|
||||||
|
"colormix_col1",
|
||||||
|
"colormix_col2",
|
||||||
|
"colormix_col3",
|
||||||
|
"error_bg",
|
||||||
|
"error_fg",
|
||||||
|
"fg",
|
||||||
|
};
|
||||||
|
const removed_properties = [_][]const u8{
|
||||||
|
"wayland_specifier",
|
||||||
|
"max_desktop_len",
|
||||||
|
"max_login_len",
|
||||||
|
"max_password_len",
|
||||||
|
"mcookie_cmd",
|
||||||
|
"term_reset_cmd",
|
||||||
|
"term_restore_cursor_cmd",
|
||||||
|
"x_cmd_setup",
|
||||||
|
"wayland_cmd",
|
||||||
|
};
|
||||||
|
|
||||||
|
var temporary_allocator = std.heap.page_allocator;
|
||||||
|
var buffer = std.mem.zeroes([10 * color_properties.len]u8);
|
||||||
|
|
||||||
|
pub var maybe_animate: ?bool = null;
|
||||||
|
pub var maybe_save_file: ?[]const u8 = null;
|
||||||
|
|
||||||
|
pub var mapped_config_fields = false;
|
||||||
|
|
||||||
|
pub fn configFieldHandler(_: std.mem.Allocator, field: ini.IniField) ?ini.IniField {
|
||||||
|
if (std.mem.eql(u8, field.key, "animate")) {
|
||||||
|
// The option doesn't exist anymore, but we save its value for "animation"
|
||||||
|
maybe_animate = std.mem.eql(u8, field.value, "true");
|
||||||
|
|
||||||
|
mapped_config_fields = true;
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (std.mem.eql(u8, field.key, "animation")) {
|
||||||
|
// The option now uses a string (which then gets converted into an enum) instead of an integer
|
||||||
|
// It also combines the previous "animate" and "animation" options
|
||||||
|
const animation = std.fmt.parseInt(u8, field.value, 10) catch return field;
|
||||||
|
var mapped_field = field;
|
||||||
|
|
||||||
|
mapped_field.value = switch (animation) {
|
||||||
|
0 => "doom",
|
||||||
|
1 => "matrix",
|
||||||
|
else => "none",
|
||||||
|
};
|
||||||
|
|
||||||
|
mapped_config_fields = true;
|
||||||
|
return mapped_field;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline for (color_properties) |property| {
|
||||||
|
if (std.mem.eql(u8, field.key, property)) {
|
||||||
|
// These options now uses a 32-bit RGB value instead of an arbitrary 16-bit integer
|
||||||
|
const color = std.fmt.parseInt(u16, field.value, 0) catch return field;
|
||||||
|
var mapped_field = field;
|
||||||
|
|
||||||
|
mapped_field.value = mapColor(color) catch return field;
|
||||||
|
mapped_config_fields = true;
|
||||||
|
return mapped_field;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (std.mem.eql(u8, field.key, "blank_password")) {
|
||||||
|
// The option has simply been renamed
|
||||||
|
var mapped_field = field;
|
||||||
|
mapped_field.key = "clear_password";
|
||||||
|
|
||||||
|
mapped_config_fields = true;
|
||||||
|
return mapped_field;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (std.mem.eql(u8, field.key, "default_input")) {
|
||||||
|
// The option now uses a string (which then gets converted into an enum) instead of an integer
|
||||||
|
const default_input = std.fmt.parseInt(u8, field.value, 10) catch return field;
|
||||||
|
var mapped_field = field;
|
||||||
|
|
||||||
|
mapped_field.value = switch (default_input) {
|
||||||
|
0 => "session",
|
||||||
|
1 => "login",
|
||||||
|
2 => "password",
|
||||||
|
else => "login",
|
||||||
|
};
|
||||||
|
|
||||||
|
mapped_config_fields = true;
|
||||||
|
return mapped_field;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (std.mem.eql(u8, field.key, "save_file")) {
|
||||||
|
// The option doesn't exist anymore, but we save its value for migration later on
|
||||||
|
maybe_save_file = temporary_allocator.dupe(u8, field.value) catch return null;
|
||||||
|
|
||||||
|
mapped_config_fields = true;
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline for (removed_properties) |property| {
|
||||||
|
if (std.mem.eql(u8, field.key, property)) {
|
||||||
|
// The options don't exist anymore
|
||||||
|
mapped_config_fields = true;
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (std.mem.eql(u8, field.key, "bigclock")) {
|
||||||
|
// The option now uses a string (which then gets converted into an enum) instead of an boolean
|
||||||
|
// It also includes the ability to change active bigclock's language
|
||||||
|
var mapped_field = field;
|
||||||
|
|
||||||
|
if (std.mem.eql(u8, field.value, "true")) {
|
||||||
|
mapped_field.value = "en";
|
||||||
|
mapped_config_fields = true;
|
||||||
|
} else if (std.mem.eql(u8, field.value, "false")) {
|
||||||
|
mapped_field.value = "none";
|
||||||
|
mapped_config_fields = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return mapped_field;
|
||||||
|
}
|
||||||
|
|
||||||
|
return field;
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is the stuff we only handle after reading the config.
|
||||||
|
// For example, the "animate" field could come after "animation"
|
||||||
|
pub fn lateConfigFieldHandler(animation: *enums.Animation) void {
|
||||||
|
if (maybe_animate) |animate| {
|
||||||
|
if (!animate) animation.* = .none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn tryMigrateSaveFile(user_buf: *[32]u8) Save {
|
||||||
var save = Save{};
|
var save = Save{};
|
||||||
|
|
||||||
var file = std.fs.openFileAbsolute(path, .{}) catch return save;
|
if (maybe_save_file) |path| {
|
||||||
defer file.close();
|
defer temporary_allocator.free(path);
|
||||||
|
|
||||||
const reader = file.reader();
|
var file = std.fs.openFileAbsolute(path, .{}) catch return save;
|
||||||
|
defer file.close();
|
||||||
|
|
||||||
var user_fbs = std.io.fixedBufferStream(user_buf);
|
const reader = file.reader();
|
||||||
reader.streamUntilDelimiter(user_fbs.writer(), '\n', 32) catch return save;
|
|
||||||
const user = user_fbs.getWritten();
|
|
||||||
if (user.len > 0) save.user = user;
|
|
||||||
|
|
||||||
var session_buf: [20]u8 = undefined;
|
var user_fbs = std.io.fixedBufferStream(user_buf);
|
||||||
var session_fbs = std.io.fixedBufferStream(&session_buf);
|
reader.streamUntilDelimiter(user_fbs.writer(), '\n', user_buf.len) catch return save;
|
||||||
reader.streamUntilDelimiter(session_fbs.writer(), '\n', 20) catch {};
|
const user = user_fbs.getWritten();
|
||||||
|
if (user.len > 0) save.user = user;
|
||||||
|
|
||||||
const session_index_str = session_fbs.getWritten();
|
var session_buf: [20]u8 = undefined;
|
||||||
var session_index: ?u64 = null;
|
var session_fbs = std.io.fixedBufferStream(&session_buf);
|
||||||
if (session_index_str.len > 0) {
|
reader.streamUntilDelimiter(session_fbs.writer(), '\n', session_buf.len) catch return save;
|
||||||
session_index = std.fmt.parseUnsigned(u64, session_index_str, 10) catch return save;
|
|
||||||
|
const session_index_str = session_fbs.getWritten();
|
||||||
|
var session_index: ?usize = null;
|
||||||
|
if (session_index_str.len > 0) {
|
||||||
|
session_index = std.fmt.parseUnsigned(usize, session_index_str, 10) catch return save;
|
||||||
|
}
|
||||||
|
save.session_index = session_index;
|
||||||
}
|
}
|
||||||
save.session_index = session_index;
|
|
||||||
|
|
||||||
return save;
|
return save;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn mapColor(color: u16) ![]const u8 {
|
||||||
|
const color_no_styling = color & 0x00FF;
|
||||||
|
const styling_only = color & 0xFF00;
|
||||||
|
|
||||||
|
// If color is "greater" than TB_WHITE, or the styling is "greater" than TB_DIM,
|
||||||
|
// we have an invalid color, so return an error
|
||||||
|
if (color_no_styling > 0x0008 or styling_only > 0x8000) return error.InvalidColor;
|
||||||
|
|
||||||
|
var new_color: u32 = switch (color_no_styling) {
|
||||||
|
0x0000 => 0x00000000, // Default
|
||||||
|
0x0001 => 0x20000000, // "Hi-black" styling
|
||||||
|
0x0002 => 0x00FF0000, // Red
|
||||||
|
0x0003 => 0x0000FF00, // Green
|
||||||
|
0x0004 => 0x00FFFF00, // Yellow
|
||||||
|
0x0005 => 0x000000FF, // Blue
|
||||||
|
0x0006 => 0x00FF00FF, // Magenta
|
||||||
|
0x0007 => 0x0000FFFF, // Cyan
|
||||||
|
0x0008 => 0x00FFFFFF, // White
|
||||||
|
else => unreachable,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Only applying styling if color isn't black and styling isn't also black
|
||||||
|
if (!(new_color == 0x20000000 and styling_only == 0x20000000)) {
|
||||||
|
// Shift styling by 16 to the left to apply it to the new 32-bit color
|
||||||
|
new_color |= @as(u32, @intCast(styling_only)) << 16;
|
||||||
|
}
|
||||||
|
|
||||||
|
return try std.fmt.bufPrint(&buffer, "0x{X}", .{new_color});
|
||||||
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ pub const Animation = enum {
|
|||||||
none,
|
none,
|
||||||
doom,
|
doom,
|
||||||
matrix,
|
matrix,
|
||||||
|
colormix,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const DisplayServer = enum {
|
pub const DisplayServer = enum {
|
||||||
@@ -12,7 +13,19 @@ pub const DisplayServer = enum {
|
|||||||
};
|
};
|
||||||
|
|
||||||
pub const Input = enum {
|
pub const Input = enum {
|
||||||
|
info_line,
|
||||||
session,
|
session,
|
||||||
login,
|
login,
|
||||||
password,
|
password,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
pub const ViMode = enum {
|
||||||
|
normal,
|
||||||
|
insert,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const Bigclock = enum {
|
||||||
|
none,
|
||||||
|
en,
|
||||||
|
fa,
|
||||||
|
};
|
||||||
|
|||||||
140
src/interop.zig
140
src/interop.zig
@@ -9,111 +9,101 @@ pub const pam = @cImport({
|
|||||||
});
|
});
|
||||||
|
|
||||||
pub const utmp = @cImport({
|
pub const utmp = @cImport({
|
||||||
@cInclude("utmp.h");
|
@cInclude("utmpx.h");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Exists for X11 support only
|
||||||
pub const xcb = @cImport({
|
pub const xcb = @cImport({
|
||||||
@cInclude("xcb/xcb.h");
|
@cInclude("xcb/xcb.h");
|
||||||
});
|
});
|
||||||
|
|
||||||
pub const c_size = u64;
|
pub const unistd = @cImport({
|
||||||
pub const c_uid = u32;
|
@cInclude("unistd.h");
|
||||||
pub const c_gid = u32;
|
});
|
||||||
pub const c_time = c_long;
|
|
||||||
pub const tm = extern struct {
|
|
||||||
tm_sec: c_int,
|
|
||||||
tm_min: c_int,
|
|
||||||
tm_hour: c_int,
|
|
||||||
tm_mday: c_int,
|
|
||||||
tm_mon: c_int,
|
|
||||||
tm_year: c_int,
|
|
||||||
tm_wday: c_int,
|
|
||||||
tm_yday: c_int,
|
|
||||||
tm_isdst: c_int,
|
|
||||||
};
|
|
||||||
pub const passwd = extern struct {
|
|
||||||
pw_name: [*:0]u8,
|
|
||||||
pw_passwd: [*:0]u8,
|
|
||||||
|
|
||||||
pw_uid: c_uid,
|
pub const time = @cImport({
|
||||||
pw_gid: c_gid,
|
@cInclude("time.h");
|
||||||
pw_gecos: [*:0]u8,
|
});
|
||||||
pw_dir: [*:0]u8,
|
|
||||||
pw_shell: [*:0]u8,
|
|
||||||
};
|
|
||||||
|
|
||||||
pub const VT_ACTIVATE: c_int = 0x5606;
|
pub const system_time = @cImport({
|
||||||
pub const VT_WAITACTIVE: c_int = 0x5607;
|
@cInclude("sys/time.h");
|
||||||
|
});
|
||||||
|
|
||||||
pub const KDGETLED: c_int = 0x4B31;
|
pub const stdlib = @cImport({
|
||||||
pub const KDSETLED: c_int = 0x4B32;
|
@cInclude("stdlib.h");
|
||||||
pub const KDGKBLED: c_int = 0x4B64;
|
});
|
||||||
pub const KDSKBLED: c_int = 0x4B65;
|
|
||||||
|
|
||||||
pub const LED_NUM: c_int = 0x02;
|
pub const pwd = @cImport({
|
||||||
pub const LED_CAP: c_int = 0x04;
|
@cInclude("pwd.h");
|
||||||
|
// We include a FreeBSD-specific header here since login_cap.h references
|
||||||
|
// the passwd struct directly, so we can't import it separately'
|
||||||
|
if (builtin.os.tag == .freebsd) @cInclude("login_cap.h");
|
||||||
|
});
|
||||||
|
|
||||||
pub const K_NUMLOCK: c_int = 0x02;
|
pub const grp = @cImport({
|
||||||
pub const K_CAPSLOCK: c_int = 0x04;
|
@cInclude("grp.h");
|
||||||
|
});
|
||||||
|
|
||||||
pub extern "c" fn localtime(timer: *const c_time) *tm;
|
// BSD-specific headers
|
||||||
pub extern "c" fn strftime(str: [*:0]u8, maxsize: c_size, format: [*:0]const u8, timeptr: *const tm) c_size;
|
pub const kbio = @cImport({
|
||||||
pub extern "c" fn setenv(name: [*:0]const u8, value: [*:0]const u8, overwrite: c_int) c_int;
|
@cInclude("sys/kbio.h");
|
||||||
pub extern "c" fn putenv(name: [*:0]u8) c_int;
|
});
|
||||||
pub extern "c" fn getuid() c_uid;
|
|
||||||
pub extern "c" fn getpwnam(name: [*:0]const u8) ?*passwd;
|
|
||||||
pub extern "c" fn endpwent() void;
|
|
||||||
pub extern "c" fn setusershell() void;
|
|
||||||
pub extern "c" fn getusershell() [*:0]u8;
|
|
||||||
pub extern "c" fn endusershell() void;
|
|
||||||
pub extern "c" fn initgroups(user: [*:0]const u8, group: c_gid) c_int;
|
|
||||||
|
|
||||||
pub fn timeAsString(buf: [:0]u8, format: [:0]const u8) ![]u8 {
|
// Linux-specific headers
|
||||||
|
pub const kd = @cImport({
|
||||||
|
@cInclude("sys/kd.h");
|
||||||
|
});
|
||||||
|
|
||||||
|
pub const vt = @cImport({
|
||||||
|
@cInclude("sys/vt.h");
|
||||||
|
});
|
||||||
|
|
||||||
|
// Used for getting & setting the lock state
|
||||||
|
const LedState = if (builtin.os.tag.isBSD()) c_int else c_char;
|
||||||
|
const get_led_state = if (builtin.os.tag.isBSD()) kbio.KDGETLED else kd.KDGKBLED;
|
||||||
|
const set_led_state = if (builtin.os.tag.isBSD()) kbio.KDSETLED else kd.KDSKBLED;
|
||||||
|
const numlock_led = if (builtin.os.tag.isBSD()) kbio.LED_NUM else kd.K_NUMLOCK;
|
||||||
|
const capslock_led = if (builtin.os.tag.isBSD()) kbio.LED_CAP else kd.K_CAPSLOCK;
|
||||||
|
|
||||||
|
pub fn timeAsString(buf: [:0]u8, format: [:0]const u8) []u8 {
|
||||||
const timer = std.time.timestamp();
|
const timer = std.time.timestamp();
|
||||||
const tm_info = localtime(&timer);
|
const tm_info = time.localtime(&timer);
|
||||||
|
const len = time.strftime(buf, buf.len, format, tm_info);
|
||||||
const len = strftime(buf, buf.len, format, tm_info);
|
|
||||||
if (len < 0) return error.CannotGetFormattedTime;
|
|
||||||
|
|
||||||
return buf[0..len];
|
return buf[0..len];
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn getLockState(console_dev: [:0]const u8) !struct {
|
pub fn switchTty(console_dev: []const u8, tty: u8) !void {
|
||||||
|
const fd = try std.posix.open(console_dev, .{ .ACCMODE = .WRONLY }, 0);
|
||||||
|
defer std.posix.close(fd);
|
||||||
|
|
||||||
|
_ = std.c.ioctl(fd, vt.VT_ACTIVATE, tty);
|
||||||
|
_ = std.c.ioctl(fd, vt.VT_WAITACTIVE, tty);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn getLockState(console_dev: []const u8) !struct {
|
||||||
numlock: bool,
|
numlock: bool,
|
||||||
capslock: bool,
|
capslock: bool,
|
||||||
} {
|
} {
|
||||||
const fd = std.c.open(console_dev, .{ .ACCMODE = .RDONLY });
|
const fd = try std.posix.open(console_dev, .{ .ACCMODE = .RDONLY }, 0);
|
||||||
if (fd < 0) return error.CannotOpenConsoleDev;
|
defer std.posix.close(fd);
|
||||||
defer _ = std.c.close(fd);
|
|
||||||
|
|
||||||
var numlock = false;
|
var led: LedState = undefined;
|
||||||
var capslock = false;
|
_ = std.c.ioctl(fd, get_led_state, &led);
|
||||||
|
|
||||||
if (builtin.os.tag.isBSD()) {
|
|
||||||
var led: c_int = undefined;
|
|
||||||
_ = std.c.ioctl(fd, KDGETLED, &led);
|
|
||||||
numlock = (led & LED_NUM) != 0;
|
|
||||||
capslock = (led & LED_CAP) != 0;
|
|
||||||
} else {
|
|
||||||
var led: c_char = undefined;
|
|
||||||
_ = std.c.ioctl(fd, KDGKBLED, &led);
|
|
||||||
numlock = (led & K_NUMLOCK) != 0;
|
|
||||||
capslock = (led & K_CAPSLOCK) != 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return .{
|
return .{
|
||||||
.numlock = numlock,
|
.numlock = (led & numlock_led) != 0,
|
||||||
.capslock = capslock,
|
.capslock = (led & capslock_led) != 0,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn setNumlock(val: bool) !void {
|
pub fn setNumlock(val: bool) !void {
|
||||||
var led: c_char = undefined;
|
var led: LedState = undefined;
|
||||||
_ = std.c.ioctl(0, KDGKBLED, &led);
|
_ = std.c.ioctl(0, get_led_state, &led);
|
||||||
|
|
||||||
const numlock = (led & K_NUMLOCK) != 0;
|
const numlock = (led & numlock_led) != 0;
|
||||||
if (numlock != val) {
|
if (numlock != val) {
|
||||||
const status = std.c.ioctl(std.posix.STDIN_FILENO, KDSKBLED, led ^ K_NUMLOCK);
|
const status = std.c.ioctl(std.posix.STDIN_FILENO, set_led_state, led ^ numlock_led);
|
||||||
if (status != 0) return error.FailedToSetNumlock;
|
if (status != 0) return error.FailedToSetNumlock;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
656
src/main.zig
656
src/main.zig
File diff suppressed because it is too large
Load Diff
61
src/tui/Animation.zig
Normal file
61
src/tui/Animation.zig
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
const Animation = @This();
|
||||||
|
|
||||||
|
const VTable = struct {
|
||||||
|
deinit_fn: *const fn (ptr: *anyopaque) void,
|
||||||
|
realloc_fn: *const fn (ptr: *anyopaque) anyerror!void,
|
||||||
|
draw_fn: *const fn (ptr: *anyopaque) void,
|
||||||
|
};
|
||||||
|
|
||||||
|
pointer: *anyopaque,
|
||||||
|
vtable: VTable,
|
||||||
|
|
||||||
|
pub fn init(
|
||||||
|
pointer: anytype,
|
||||||
|
comptime deinit_fn: fn (ptr: @TypeOf(pointer)) void,
|
||||||
|
comptime realloc_fn: fn (ptr: @TypeOf(pointer)) anyerror!void,
|
||||||
|
comptime draw_fn: fn (ptr: @TypeOf(pointer)) void,
|
||||||
|
) Animation {
|
||||||
|
const Pointer = @TypeOf(pointer);
|
||||||
|
const Impl = struct {
|
||||||
|
pub fn deinitImpl(ptr: *anyopaque) void {
|
||||||
|
const impl: Pointer = @ptrCast(@alignCast(ptr));
|
||||||
|
return @call(.always_inline, deinit_fn, .{impl});
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn reallocImpl(ptr: *anyopaque) anyerror!void {
|
||||||
|
const impl: Pointer = @ptrCast(@alignCast(ptr));
|
||||||
|
return @call(.always_inline, realloc_fn, .{impl});
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn drawImpl(ptr: *anyopaque) void {
|
||||||
|
const impl: Pointer = @ptrCast(@alignCast(ptr));
|
||||||
|
return @call(.always_inline, draw_fn, .{impl});
|
||||||
|
}
|
||||||
|
|
||||||
|
const vtable = VTable{
|
||||||
|
.deinit_fn = deinitImpl,
|
||||||
|
.realloc_fn = reallocImpl,
|
||||||
|
.draw_fn = drawImpl,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
return .{
|
||||||
|
.pointer = pointer,
|
||||||
|
.vtable = Impl.vtable,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn deinit(self: *Animation) void {
|
||||||
|
const impl: @TypeOf(self.pointer) = @ptrCast(@alignCast(self.pointer));
|
||||||
|
return @call(.auto, self.vtable.deinit_fn, .{impl});
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn realloc(self: *Animation) anyerror!void {
|
||||||
|
const impl: @TypeOf(self.pointer) = @ptrCast(@alignCast(self.pointer));
|
||||||
|
return @call(.auto, self.vtable.realloc_fn, .{impl});
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn draw(self: *Animation) void {
|
||||||
|
const impl: @TypeOf(self.pointer) = @ptrCast(@alignCast(self.pointer));
|
||||||
|
return @call(.auto, self.vtable.draw_fn, .{impl});
|
||||||
|
}
|
||||||
23
src/tui/Cell.zig
Normal file
23
src/tui/Cell.zig
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
const interop = @import("../interop.zig");
|
||||||
|
|
||||||
|
const termbox = interop.termbox;
|
||||||
|
|
||||||
|
const Cell = @This();
|
||||||
|
|
||||||
|
ch: u32,
|
||||||
|
fg: u32,
|
||||||
|
bg: u32,
|
||||||
|
|
||||||
|
pub fn init(ch: u32, fg: u32, bg: u32) Cell {
|
||||||
|
return .{
|
||||||
|
.ch = ch,
|
||||||
|
.fg = fg,
|
||||||
|
.bg = bg,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn put(self: Cell, x: usize, y: usize) void {
|
||||||
|
if (self.ch == 0) return;
|
||||||
|
|
||||||
|
_ = termbox.tb_set_cell(@intCast(x), @intCast(y), self.ch, self.fg, self.bg);
|
||||||
|
}
|
||||||
@@ -1,22 +1,52 @@
|
|||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const builtin = @import("builtin");
|
const builtin = @import("builtin");
|
||||||
const interop = @import("../interop.zig");
|
const interop = @import("../interop.zig");
|
||||||
const utils = @import("utils.zig");
|
const Cell = @import("Cell.zig");
|
||||||
const Config = @import("../config/Config.zig");
|
|
||||||
|
|
||||||
const Random = std.rand.Random;
|
const Random = std.Random;
|
||||||
|
|
||||||
const termbox = interop.termbox;
|
const termbox = interop.termbox;
|
||||||
|
|
||||||
const TerminalBuffer = @This();
|
const TerminalBuffer = @This();
|
||||||
|
|
||||||
|
pub const InitOptions = struct {
|
||||||
|
fg: u32,
|
||||||
|
bg: u32,
|
||||||
|
border_fg: u32,
|
||||||
|
margin_box_h: u8,
|
||||||
|
margin_box_v: u8,
|
||||||
|
input_len: u8,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const Styling = struct {
|
||||||
|
pub const BOLD = termbox.TB_BOLD;
|
||||||
|
pub const UNDERLINE = termbox.TB_UNDERLINE;
|
||||||
|
pub const REVERSE = termbox.TB_REVERSE;
|
||||||
|
pub const ITALIC = termbox.TB_ITALIC;
|
||||||
|
pub const BLINK = termbox.TB_BLINK;
|
||||||
|
pub const HI_BLACK = termbox.TB_HI_BLACK;
|
||||||
|
pub const BRIGHT = termbox.TB_BRIGHT;
|
||||||
|
pub const DIM = termbox.TB_DIM;
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const Color = struct {
|
||||||
|
pub const DEFAULT = 0x00000000;
|
||||||
|
pub const BLACK = Styling.HI_BLACK;
|
||||||
|
pub const RED = 0x00FF0000;
|
||||||
|
pub const GREEN = 0x0000FF00;
|
||||||
|
pub const YELLOW = 0x00FFFF00;
|
||||||
|
pub const BLUE = 0x000000FF;
|
||||||
|
pub const MAGENTA = 0x00FF00FF;
|
||||||
|
pub const CYAN = 0x0000FFFF;
|
||||||
|
pub const WHITE = 0x00FFFFFF;
|
||||||
|
};
|
||||||
|
|
||||||
random: Random,
|
random: Random,
|
||||||
width: u64,
|
width: usize,
|
||||||
height: u64,
|
height: usize,
|
||||||
buffer: [*]termbox.tb_cell,
|
fg: u32,
|
||||||
fg: u8,
|
bg: u32,
|
||||||
bg: u8,
|
border_fg: u32,
|
||||||
border_fg: u8,
|
|
||||||
box_chars: struct {
|
box_chars: struct {
|
||||||
left_up: u32,
|
left_up: u32,
|
||||||
left_down: u32,
|
left_down: u32,
|
||||||
@@ -27,25 +57,23 @@ box_chars: struct {
|
|||||||
left: u32,
|
left: u32,
|
||||||
right: u32,
|
right: u32,
|
||||||
},
|
},
|
||||||
labels_max_length: u64,
|
labels_max_length: usize,
|
||||||
box_x: u64,
|
box_x: usize,
|
||||||
box_y: u64,
|
box_y: usize,
|
||||||
box_width: u64,
|
box_width: usize,
|
||||||
box_height: u64,
|
box_height: usize,
|
||||||
margin_box_v: u8,
|
margin_box_v: u8,
|
||||||
margin_box_h: u8,
|
margin_box_h: u8,
|
||||||
|
blank_cell: Cell,
|
||||||
|
|
||||||
pub fn init(config: Config, labels_max_length: u64) TerminalBuffer {
|
pub fn init(options: InitOptions, labels_max_length: usize, random: Random) TerminalBuffer {
|
||||||
var prng = std.rand.Isaac64.init(@intCast(std.time.timestamp()));
|
|
||||||
|
|
||||||
return .{
|
return .{
|
||||||
.random = prng.random(),
|
.random = random,
|
||||||
.width = @intCast(termbox.tb_width()),
|
.width = @intCast(termbox.tb_width()),
|
||||||
.height = @intCast(termbox.tb_height()),
|
.height = @intCast(termbox.tb_height()),
|
||||||
.buffer = termbox.tb_cell_buffer(),
|
.fg = options.fg,
|
||||||
.fg = config.fg,
|
.bg = options.bg,
|
||||||
.bg = config.bg,
|
.border_fg = options.border_fg,
|
||||||
.border_fg = config.border_fg,
|
|
||||||
.box_chars = if (builtin.os.tag == .linux or builtin.os.tag.isBSD()) .{
|
.box_chars = if (builtin.os.tag == .linux or builtin.os.tag.isBSD()) .{
|
||||||
.left_up = 0x250C,
|
.left_up = 0x250C,
|
||||||
.left_down = 0x2514,
|
.left_down = 0x2514,
|
||||||
@@ -68,35 +96,42 @@ pub fn init(config: Config, labels_max_length: u64) TerminalBuffer {
|
|||||||
.labels_max_length = labels_max_length,
|
.labels_max_length = labels_max_length,
|
||||||
.box_x = 0,
|
.box_x = 0,
|
||||||
.box_y = 0,
|
.box_y = 0,
|
||||||
.box_width = (2 * config.margin_box_h) + config.input_len + 1 + labels_max_length,
|
.box_width = (2 * options.margin_box_h) + options.input_len + 1 + labels_max_length,
|
||||||
.box_height = 7 + (2 * config.margin_box_v),
|
.box_height = 7 + (2 * options.margin_box_v),
|
||||||
.margin_box_v = config.margin_box_v,
|
.margin_box_v = options.margin_box_v,
|
||||||
.margin_box_h = config.margin_box_h,
|
.margin_box_h = options.margin_box_h,
|
||||||
|
.blank_cell = Cell.init(' ', options.fg, options.bg),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn cascade(self: TerminalBuffer) bool {
|
pub fn cascade(self: TerminalBuffer) bool {
|
||||||
var changes = false;
|
var changed = false;
|
||||||
|
|
||||||
var y = self.height - 2;
|
var y = self.height - 2;
|
||||||
|
|
||||||
while (y > 0) : (y -= 1) {
|
while (y > 0) : (y -= 1) {
|
||||||
for (0..self.width) |x| {
|
for (0..self.width) |x| {
|
||||||
const c: u8 = @truncate(self.buffer[(y - 1) * self.width + x].ch);
|
var cell: termbox.tb_cell = undefined;
|
||||||
if (std.ascii.isWhitespace(c)) continue;
|
var cell_under: termbox.tb_cell = undefined;
|
||||||
|
|
||||||
const c_under: u8 = @truncate(self.buffer[y * self.width + x].ch);
|
_ = termbox.tb_get_cell(@intCast(x), @intCast(y - 1), 1, &cell);
|
||||||
if (!std.ascii.isWhitespace(c_under)) continue;
|
_ = termbox.tb_get_cell(@intCast(x), @intCast(y), 1, &cell_under);
|
||||||
|
|
||||||
changes = true;
|
const char: u8 = @truncate(cell.ch);
|
||||||
|
if (std.ascii.isWhitespace(char)) continue;
|
||||||
|
|
||||||
|
const char_under: u8 = @truncate(cell_under.ch);
|
||||||
|
if (!std.ascii.isWhitespace(char_under)) continue;
|
||||||
|
|
||||||
|
changed = true;
|
||||||
|
|
||||||
if ((self.random.int(u16) % 10) > 7) continue;
|
if ((self.random.int(u16) % 10) > 7) continue;
|
||||||
|
|
||||||
self.buffer[y * self.width + x] = self.buffer[(y - 1) * self.width + x];
|
_ = termbox.tb_set_cell(@intCast(x), @intCast(y), cell.ch, cell.fg, cell.bg);
|
||||||
self.buffer[(y - 1) * self.width + x].ch = ' ';
|
_ = termbox.tb_set_cell(@intCast(x), @intCast(y - 1), ' ', cell_under.fg, cell_under.bg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return changes;
|
return changed;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn drawBoxCenter(self: *TerminalBuffer, show_borders: bool, blank_box: bool) void {
|
pub fn drawBoxCenter(self: *TerminalBuffer, show_borders: bool, blank_box: bool) void {
|
||||||
@@ -115,76 +150,92 @@ pub fn drawBoxCenter(self: *TerminalBuffer, show_borders: bool, blank_box: bool)
|
|||||||
_ = termbox.tb_set_cell(@intCast(x1 - 1), @intCast(y2), self.box_chars.left_down, self.border_fg, self.bg);
|
_ = termbox.tb_set_cell(@intCast(x1 - 1), @intCast(y2), self.box_chars.left_down, self.border_fg, self.bg);
|
||||||
_ = termbox.tb_set_cell(@intCast(x2), @intCast(y2), self.box_chars.right_down, self.border_fg, self.bg);
|
_ = termbox.tb_set_cell(@intCast(x2), @intCast(y2), self.box_chars.right_down, self.border_fg, self.bg);
|
||||||
|
|
||||||
var c1 = utils.initCell(self.box_chars.top, self.border_fg, self.bg);
|
var c1 = Cell.init(self.box_chars.top, self.border_fg, self.bg);
|
||||||
var c2 = utils.initCell(self.box_chars.bottom, self.border_fg, self.bg);
|
var c2 = Cell.init(self.box_chars.bottom, self.border_fg, self.bg);
|
||||||
|
|
||||||
for (0..self.box_width) |i| {
|
for (0..self.box_width) |i| {
|
||||||
_ = utils.putCell(@intCast(x1 + i), @intCast(y1 - 1), &c1);
|
c1.put(x1 + i, y1 - 1);
|
||||||
_ = utils.putCell(@intCast(x1 + i), @intCast(y2), &c2);
|
c2.put(x1 + i, y2);
|
||||||
}
|
}
|
||||||
|
|
||||||
c1.ch = self.box_chars.left;
|
c1.ch = self.box_chars.left;
|
||||||
c2.ch = self.box_chars.right;
|
c2.ch = self.box_chars.right;
|
||||||
|
|
||||||
for (0..self.box_height) |i| {
|
for (0..self.box_height) |i| {
|
||||||
_ = utils.putCell(@intCast(x1 - 1), @intCast(y1 + i), &c1);
|
c1.put(x1 - 1, y1 + i);
|
||||||
_ = utils.putCell(@intCast(x2), @intCast(y1 + i), &c2);
|
c2.put(x2, y1 + i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (blank_box) {
|
if (blank_box) {
|
||||||
const blank = utils.initCell(' ', self.fg, self.bg);
|
|
||||||
|
|
||||||
for (0..self.box_height) |y| {
|
for (0..self.box_height) |y| {
|
||||||
for (0..self.box_width) |x| {
|
for (0..self.box_width) |x| {
|
||||||
_ = utils.putCell(@intCast(x1 + x), @intCast(y1 + y), &blank);
|
self.blank_cell.put(x1 + x, y1 + y);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn calculateComponentCoordinates(self: TerminalBuffer) struct {
|
pub fn calculateComponentCoordinates(self: TerminalBuffer) struct {
|
||||||
x: u64,
|
start_x: usize,
|
||||||
y: u64,
|
x: usize,
|
||||||
visible_length: u64,
|
y: usize,
|
||||||
|
full_visible_length: usize,
|
||||||
|
visible_length: usize,
|
||||||
} {
|
} {
|
||||||
const x = self.box_x + self.margin_box_h + self.labels_max_length + 1;
|
const start_x = self.box_x + self.margin_box_h;
|
||||||
|
const x = start_x + self.labels_max_length + 1;
|
||||||
const y = self.box_y + self.margin_box_v;
|
const y = self.box_y + self.margin_box_v;
|
||||||
|
const full_visible_length = self.box_x + self.box_width - self.margin_box_h - start_x;
|
||||||
const visible_length = self.box_x + self.box_width - self.margin_box_h - x;
|
const visible_length = self.box_x + self.box_width - self.margin_box_h - x;
|
||||||
|
|
||||||
return .{
|
return .{
|
||||||
|
.start_x = start_x,
|
||||||
.x = x,
|
.x = x,
|
||||||
.y = y,
|
.y = y,
|
||||||
|
.full_visible_length = full_visible_length,
|
||||||
.visible_length = visible_length,
|
.visible_length = visible_length,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn drawLabel(self: TerminalBuffer, text: []const u8, x: u64, y: u64) void {
|
pub fn drawLabel(self: TerminalBuffer, text: []const u8, x: usize, y: usize) void {
|
||||||
|
drawColorLabel(text, x, y, self.fg, self.bg);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn drawColorLabel(text: []const u8, x: usize, y: usize, fg: u32, bg: u32) void {
|
||||||
const yc: c_int = @intCast(y);
|
const yc: c_int = @intCast(y);
|
||||||
const utf8view = std.unicode.Utf8View.init(text) catch return;
|
const utf8view = std.unicode.Utf8View.init(text) catch return;
|
||||||
var utf8 = utf8view.iterator();
|
var utf8 = utf8view.iterator();
|
||||||
|
|
||||||
var i = x;
|
var i: c_int = @intCast(x);
|
||||||
while (utf8.nextCodepoint()) |codepoint| : (i += 1) {
|
while (utf8.nextCodepoint()) |codepoint| : (i += termbox.tb_wcwidth(codepoint)) {
|
||||||
_ = termbox.tb_set_cell(@intCast(i), yc, codepoint, self.fg, self.bg);
|
_ = termbox.tb_set_cell(i, yc, codepoint, fg, bg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn drawConfinedLabel(self: TerminalBuffer, text: []const u8, x: u64, y: u64, max_length: u64) void {
|
pub fn drawConfinedLabel(self: TerminalBuffer, text: []const u8, x: usize, y: usize, max_length: usize) void {
|
||||||
const yc: c_int = @intCast(y);
|
const yc: c_int = @intCast(y);
|
||||||
const utf8view = std.unicode.Utf8View.init(text) catch return;
|
const utf8view = std.unicode.Utf8View.init(text) catch return;
|
||||||
var utf8 = utf8view.iterator();
|
var utf8 = utf8view.iterator();
|
||||||
|
|
||||||
var i: usize = 0;
|
var i: c_int = @intCast(x);
|
||||||
while (utf8.nextCodepoint()) |codepoint| : (i += 1) {
|
while (utf8.nextCodepoint()) |codepoint| : (i += termbox.tb_wcwidth(codepoint)) {
|
||||||
if (i >= max_length) break;
|
if (i >= max_length) break;
|
||||||
_ = termbox.tb_set_cell(@intCast(i + x), yc, codepoint, self.fg, self.bg);
|
_ = termbox.tb_set_cell(i, yc, codepoint, self.fg, self.bg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn drawCharMultiple(self: TerminalBuffer, char: u8, x: u64, y: u64, length: u64) void {
|
pub fn drawCharMultiple(self: TerminalBuffer, char: u32, x: usize, y: usize, length: usize) void {
|
||||||
const yc: c_int = @intCast(y);
|
const cell = Cell.init(char, self.fg, self.bg);
|
||||||
const cell = utils.initCell(char, self.fg, self.bg);
|
for (0..length) |xx| cell.put(x + xx, y);
|
||||||
|
}
|
||||||
for (0..length) |xx| _ = utils.putCell(@intCast(x + xx), yc, &cell);
|
|
||||||
|
// Every codepoint is assumed to have a width of 1.
|
||||||
|
// Since Ly is normally running in a TTY, this should be fine.
|
||||||
|
pub fn strWidth(str: []const u8) !u8 {
|
||||||
|
const utf8view = try std.unicode.Utf8View.init(str);
|
||||||
|
var utf8 = utf8view.iterator();
|
||||||
|
var i: c_int = 0;
|
||||||
|
while (utf8.nextCodepoint()) |codepoint| i += termbox.tb_wcwidth(codepoint);
|
||||||
|
return @intCast(i);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,223 +0,0 @@
|
|||||||
const std = @import("std");
|
|
||||||
const enums = @import("../../enums.zig");
|
|
||||||
const interop = @import("../../interop.zig");
|
|
||||||
const TerminalBuffer = @import("../TerminalBuffer.zig");
|
|
||||||
const Ini = @import("zigini").Ini;
|
|
||||||
const Lang = @import("../../config/Lang.zig");
|
|
||||||
|
|
||||||
const Allocator = std.mem.Allocator;
|
|
||||||
const EnvironmentList = std.ArrayList(Environment);
|
|
||||||
|
|
||||||
const DisplayServer = enums.DisplayServer;
|
|
||||||
|
|
||||||
const termbox = interop.termbox;
|
|
||||||
|
|
||||||
const Desktop = @This();
|
|
||||||
|
|
||||||
pub const Environment = struct {
|
|
||||||
entry_ini: ?Ini(Entry) = null,
|
|
||||||
name: [:0]const u8 = "",
|
|
||||||
xdg_session_desktop: [:0]const u8 = "",
|
|
||||||
xdg_desktop_names: ?[:0]const u8 = "",
|
|
||||||
cmd: []const u8 = "",
|
|
||||||
specifier: []const u8 = "",
|
|
||||||
display_server: DisplayServer = .wayland,
|
|
||||||
};
|
|
||||||
|
|
||||||
const DesktopEntry = struct {
|
|
||||||
Exec: []const u8 = "",
|
|
||||||
Name: [:0]const u8 = "",
|
|
||||||
DesktopNames: ?[]const u8 = null,
|
|
||||||
};
|
|
||||||
|
|
||||||
pub const Entry = struct { @"Desktop Entry": DesktopEntry = DesktopEntry{} };
|
|
||||||
|
|
||||||
allocator: Allocator,
|
|
||||||
buffer: *TerminalBuffer,
|
|
||||||
environments: EnvironmentList,
|
|
||||||
current: u64,
|
|
||||||
visible_length: u64,
|
|
||||||
x: u64,
|
|
||||||
y: u64,
|
|
||||||
lang: Lang,
|
|
||||||
|
|
||||||
pub fn init(allocator: Allocator, buffer: *TerminalBuffer, max_length: u64, lang: Lang) !Desktop {
|
|
||||||
return .{
|
|
||||||
.allocator = allocator,
|
|
||||||
.buffer = buffer,
|
|
||||||
.environments = try EnvironmentList.initCapacity(allocator, max_length),
|
|
||||||
.current = 0,
|
|
||||||
.visible_length = 0,
|
|
||||||
.x = 0,
|
|
||||||
.y = 0,
|
|
||||||
.lang = lang,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn deinit(self: Desktop) void {
|
|
||||||
for (self.environments.items) |*environment| {
|
|
||||||
if (environment.entry_ini) |*entry_ini| entry_ini.deinit();
|
|
||||||
if (environment.xdg_desktop_names) |desktop_name| self.allocator.free(desktop_name);
|
|
||||||
self.allocator.free(environment.xdg_session_desktop);
|
|
||||||
}
|
|
||||||
|
|
||||||
self.environments.deinit();
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn position(self: *Desktop, x: u64, y: u64, visible_length: u64) void {
|
|
||||||
self.x = x;
|
|
||||||
self.y = y;
|
|
||||||
self.visible_length = visible_length;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn addEnvironment(self: *Desktop, entry: DesktopEntry, xdg_session_desktop: []const u8, display_server: DisplayServer) !void {
|
|
||||||
var xdg_desktop_names: ?[:0]const u8 = null;
|
|
||||||
if (entry.DesktopNames) |desktop_names| {
|
|
||||||
const desktop_names_z = try self.allocator.dupeZ(u8, desktop_names);
|
|
||||||
for (desktop_names_z) |*c| {
|
|
||||||
if (c.* == ';') c.* = ':';
|
|
||||||
}
|
|
||||||
xdg_desktop_names = desktop_names_z;
|
|
||||||
}
|
|
||||||
|
|
||||||
errdefer {
|
|
||||||
if (xdg_desktop_names) |desktop_names| self.allocator.free(desktop_names);
|
|
||||||
}
|
|
||||||
|
|
||||||
const session_desktop = try self.allocator.dupeZ(u8, xdg_session_desktop);
|
|
||||||
errdefer self.allocator.free(session_desktop);
|
|
||||||
|
|
||||||
try self.environments.append(.{
|
|
||||||
.entry_ini = null,
|
|
||||||
.name = entry.Name,
|
|
||||||
.xdg_session_desktop = session_desktop,
|
|
||||||
.xdg_desktop_names = xdg_desktop_names,
|
|
||||||
.cmd = entry.Exec,
|
|
||||||
.specifier = switch (display_server) {
|
|
||||||
.wayland => self.lang.wayland,
|
|
||||||
.x11 => self.lang.x11,
|
|
||||||
else => self.lang.other,
|
|
||||||
},
|
|
||||||
.display_server = display_server,
|
|
||||||
});
|
|
||||||
|
|
||||||
self.current = self.environments.items.len - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn addEnvironmentWithIni(self: *Desktop, entry_ini: Ini(Entry), xdg_session_desktop: []const u8, display_server: DisplayServer) !void {
|
|
||||||
const entry = entry_ini.data.@"Desktop Entry";
|
|
||||||
var xdg_desktop_names: ?[:0]const u8 = null;
|
|
||||||
if (entry.DesktopNames) |desktop_names| {
|
|
||||||
const desktop_names_z = try self.allocator.dupeZ(u8, desktop_names);
|
|
||||||
for (desktop_names_z) |*c| {
|
|
||||||
if (c.* == ';') c.* = ':';
|
|
||||||
}
|
|
||||||
xdg_desktop_names = desktop_names_z;
|
|
||||||
}
|
|
||||||
|
|
||||||
errdefer {
|
|
||||||
if (xdg_desktop_names) |desktop_names| self.allocator.free(desktop_names);
|
|
||||||
}
|
|
||||||
|
|
||||||
const session_desktop = try self.allocator.dupeZ(u8, xdg_session_desktop);
|
|
||||||
errdefer self.allocator.free(session_desktop);
|
|
||||||
|
|
||||||
try self.environments.append(.{
|
|
||||||
.entry_ini = entry_ini,
|
|
||||||
.name = entry.Name,
|
|
||||||
.xdg_session_desktop = session_desktop,
|
|
||||||
.xdg_desktop_names = xdg_desktop_names,
|
|
||||||
.cmd = entry.Exec,
|
|
||||||
.specifier = switch (display_server) {
|
|
||||||
.wayland => self.lang.wayland,
|
|
||||||
.x11 => self.lang.x11,
|
|
||||||
else => self.lang.other,
|
|
||||||
},
|
|
||||||
.display_server = display_server,
|
|
||||||
});
|
|
||||||
|
|
||||||
self.current = self.environments.items.len - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn crawl(self: *Desktop, path: []const u8, display_server: DisplayServer) !void {
|
|
||||||
var iterable_directory = std.fs.openDirAbsolute(path, .{ .iterate = true }) catch return;
|
|
||||||
defer iterable_directory.close();
|
|
||||||
|
|
||||||
var iterator = iterable_directory.iterate();
|
|
||||||
while (try iterator.next()) |item| {
|
|
||||||
if (!std.mem.eql(u8, std.fs.path.extension(item.name), ".desktop")) continue;
|
|
||||||
|
|
||||||
const entry_path = try std.fmt.allocPrint(self.allocator, "{s}/{s}", .{ path, item.name });
|
|
||||||
defer self.allocator.free(entry_path);
|
|
||||||
var entry_ini = Ini(Entry).init(self.allocator);
|
|
||||||
_ = try entry_ini.readFileToStruct(entry_path);
|
|
||||||
errdefer entry_ini.deinit();
|
|
||||||
|
|
||||||
var xdg_session_desktop: []const u8 = undefined;
|
|
||||||
const maybe_desktop_names = entry_ini.data.@"Desktop Entry".DesktopNames;
|
|
||||||
if (maybe_desktop_names) |desktop_names| {
|
|
||||||
xdg_session_desktop = std.mem.sliceTo(desktop_names, ';');
|
|
||||||
} else {
|
|
||||||
// if DesktopNames is empty, we'll take the name of the session file
|
|
||||||
xdg_session_desktop = std.fs.path.stem(item.name);
|
|
||||||
}
|
|
||||||
|
|
||||||
try self.addEnvironmentWithIni(entry_ini, xdg_session_desktop, display_server);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn handle(self: *Desktop, maybe_event: ?*termbox.tb_event, insert_mode: bool) void {
|
|
||||||
if (maybe_event) |event| blk: {
|
|
||||||
if (event.type != termbox.TB_EVENT_KEY) break :blk;
|
|
||||||
|
|
||||||
switch (event.key) {
|
|
||||||
termbox.TB_KEY_ARROW_LEFT, termbox.TB_KEY_CTRL_H => self.goLeft(),
|
|
||||||
termbox.TB_KEY_ARROW_RIGHT, termbox.TB_KEY_CTRL_L => self.goRight(),
|
|
||||||
else => {
|
|
||||||
if (!insert_mode) {
|
|
||||||
switch (event.ch) {
|
|
||||||
'h' => self.goLeft(),
|
|
||||||
'l' => self.goRight(),
|
|
||||||
else => {},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_ = termbox.tb_set_cursor(@intCast(self.x + 2), @intCast(self.y));
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn draw(self: Desktop) void {
|
|
||||||
const environment = self.environments.items[self.current];
|
|
||||||
|
|
||||||
const length = @min(environment.name.len, self.visible_length - 3);
|
|
||||||
if (length == 0) return;
|
|
||||||
|
|
||||||
const x = self.buffer.box_x + self.buffer.margin_box_h;
|
|
||||||
const y = self.buffer.box_y + self.buffer.margin_box_v + 2;
|
|
||||||
self.buffer.drawLabel(environment.specifier, x, y);
|
|
||||||
|
|
||||||
_ = termbox.tb_set_cell(@intCast(self.x), @intCast(self.y), '<', self.buffer.fg, self.buffer.bg);
|
|
||||||
_ = termbox.tb_set_cell(@intCast(self.x + self.visible_length - 1), @intCast(self.y), '>', self.buffer.fg, self.buffer.bg);
|
|
||||||
|
|
||||||
self.buffer.drawLabel(environment.name, self.x + 2, self.y);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn goLeft(self: *Desktop) void {
|
|
||||||
if (self.current == 0) {
|
|
||||||
self.current = self.environments.items.len - 1;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
self.current -= 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn goRight(self: *Desktop) void {
|
|
||||||
if (self.current == self.environments.items.len - 1) {
|
|
||||||
self.current = 0;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
self.current += 1;
|
|
||||||
}
|
|
||||||
@@ -1,28 +1,45 @@
|
|||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const utils = @import("../utils.zig");
|
|
||||||
const TerminalBuffer = @import("../TerminalBuffer.zig");
|
const TerminalBuffer = @import("../TerminalBuffer.zig");
|
||||||
|
const generic = @import("generic.zig");
|
||||||
|
|
||||||
|
const Allocator = std.mem.Allocator;
|
||||||
|
|
||||||
|
const MessageLabel = generic.CyclableLabel(Message);
|
||||||
|
|
||||||
const InfoLine = @This();
|
const InfoLine = @This();
|
||||||
|
|
||||||
text: []const u8 = "",
|
const Message = struct {
|
||||||
width: u8 = 0,
|
width: u8,
|
||||||
|
text: []const u8,
|
||||||
|
bg: u32,
|
||||||
|
fg: u32,
|
||||||
|
};
|
||||||
|
|
||||||
pub fn setText(self: *InfoLine, text: []const u8) !void {
|
label: MessageLabel,
|
||||||
self.width = if (text.len > 0) try utils.strWidth(text) else 0;
|
|
||||||
self.text = text;
|
pub fn init(allocator: Allocator, buffer: *TerminalBuffer) InfoLine {
|
||||||
|
return .{
|
||||||
|
.label = MessageLabel.init(allocator, buffer, drawItem),
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn draw(self: InfoLine, buffer: TerminalBuffer) void {
|
pub fn deinit(self: *InfoLine) void {
|
||||||
if (self.width > 0 and buffer.box_width > self.width) {
|
self.label.deinit();
|
||||||
const label_y = buffer.box_y + buffer.margin_box_v;
|
|
||||||
const x = buffer.box_x + ((buffer.box_width - self.width) / 2);
|
|
||||||
|
|
||||||
buffer.drawLabel(self.text, x, label_y);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn clearRendered(allocator: std.mem.Allocator, buffer: TerminalBuffer) !void {
|
pub fn addMessage(self: *InfoLine, text: []const u8, bg: u32, fg: u32) !void {
|
||||||
// draw over the area
|
if (text.len == 0) return;
|
||||||
|
|
||||||
|
try self.label.addItem(.{
|
||||||
|
.width = try TerminalBuffer.strWidth(text),
|
||||||
|
.text = text,
|
||||||
|
.bg = bg,
|
||||||
|
.fg = fg,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn clearRendered(allocator: Allocator, buffer: TerminalBuffer) !void {
|
||||||
|
// Draw over the area
|
||||||
const y = buffer.box_y + buffer.margin_box_v;
|
const y = buffer.box_y + buffer.margin_box_v;
|
||||||
const spaces = try allocator.alloc(u8, buffer.box_width);
|
const spaces = try allocator.alloc(u8, buffer.box_width);
|
||||||
defer allocator.free(spaces);
|
defer allocator.free(spaces);
|
||||||
@@ -31,3 +48,13 @@ pub fn clearRendered(allocator: std.mem.Allocator, buffer: TerminalBuffer) !void
|
|||||||
|
|
||||||
buffer.drawLabel(spaces, buffer.box_x, y);
|
buffer.drawLabel(spaces, buffer.box_x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn drawItem(label: *MessageLabel, message: Message, _: usize, _: usize) bool {
|
||||||
|
if (message.width == 0 or label.buffer.box_width <= message.width) return false;
|
||||||
|
|
||||||
|
const x = label.buffer.box_x + ((label.buffer.box_width - message.width) / 2);
|
||||||
|
label.first_char_x = x + message.width;
|
||||||
|
|
||||||
|
TerminalBuffer.drawColorLabel(message.text, x, label.y, message.fg, message.bg);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|||||||
46
src/tui/components/Session.zig
Normal file
46
src/tui/components/Session.zig
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
const std = @import("std");
|
||||||
|
const TerminalBuffer = @import("../TerminalBuffer.zig");
|
||||||
|
const enums = @import("../../enums.zig");
|
||||||
|
const ini = @import("zigini");
|
||||||
|
const Environment = @import("../../Environment.zig");
|
||||||
|
const generic = @import("generic.zig");
|
||||||
|
|
||||||
|
const Allocator = std.mem.Allocator;
|
||||||
|
const DisplayServer = enums.DisplayServer;
|
||||||
|
const Ini = ini.Ini;
|
||||||
|
const EnvironmentLabel = generic.CyclableLabel(Environment);
|
||||||
|
|
||||||
|
const Session = @This();
|
||||||
|
|
||||||
|
label: EnvironmentLabel,
|
||||||
|
|
||||||
|
pub fn init(allocator: Allocator, buffer: *TerminalBuffer) Session {
|
||||||
|
return .{
|
||||||
|
.label = EnvironmentLabel.init(allocator, buffer, drawItem),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn deinit(self: *Session) void {
|
||||||
|
for (self.label.list.items) |*environment| {
|
||||||
|
if (environment.entry_ini) |*entry_ini| entry_ini.deinit();
|
||||||
|
if (environment.xdg_session_desktop) |session_desktop| self.label.allocator.free(session_desktop);
|
||||||
|
}
|
||||||
|
|
||||||
|
self.label.deinit();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn addEnvironment(self: *Session, environment: Environment) !void {
|
||||||
|
try self.label.addItem(environment);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn drawItem(label: *EnvironmentLabel, environment: Environment, x: usize, y: usize) bool {
|
||||||
|
const length = @min(environment.name.len, label.visible_length - 3);
|
||||||
|
if (length == 0) return false;
|
||||||
|
|
||||||
|
const nx = if (label.text_in_center) (label.x + (label.visible_length - environment.name.len) / 2) else (label.x + 2);
|
||||||
|
label.first_char_x = nx + environment.name.len;
|
||||||
|
|
||||||
|
label.buffer.drawLabel(environment.specifier, x, y);
|
||||||
|
label.buffer.drawLabel(environment.name, nx, label.y);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
@@ -1,10 +1,9 @@
|
|||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const interop = @import("../../interop.zig");
|
const interop = @import("../../interop.zig");
|
||||||
const TerminalBuffer = @import("../TerminalBuffer.zig");
|
const TerminalBuffer = @import("../TerminalBuffer.zig");
|
||||||
const utils = @import("../utils.zig");
|
|
||||||
|
|
||||||
const Allocator = std.mem.Allocator;
|
const Allocator = std.mem.Allocator;
|
||||||
const DynamicString = std.ArrayList(u8);
|
const DynamicString = std.ArrayListUnmanaged(u8);
|
||||||
|
|
||||||
const termbox = interop.termbox;
|
const termbox = interop.termbox;
|
||||||
|
|
||||||
@@ -13,15 +12,17 @@ const Text = @This();
|
|||||||
allocator: Allocator,
|
allocator: Allocator,
|
||||||
buffer: *TerminalBuffer,
|
buffer: *TerminalBuffer,
|
||||||
text: DynamicString,
|
text: DynamicString,
|
||||||
end: u64,
|
end: usize,
|
||||||
cursor: u64,
|
cursor: usize,
|
||||||
visible_start: u64,
|
visible_start: usize,
|
||||||
visible_length: u64,
|
visible_length: usize,
|
||||||
x: u64,
|
x: usize,
|
||||||
y: u64,
|
y: usize,
|
||||||
|
masked: bool,
|
||||||
|
maybe_mask: ?u32,
|
||||||
|
|
||||||
pub fn init(allocator: Allocator, buffer: *TerminalBuffer, max_length: u64) !Text {
|
pub fn init(allocator: Allocator, buffer: *TerminalBuffer, masked: bool, maybe_mask: ?u32) Text {
|
||||||
const text = try DynamicString.initCapacity(allocator, max_length);
|
const text: DynamicString = .empty;
|
||||||
|
|
||||||
return .{
|
return .{
|
||||||
.allocator = allocator,
|
.allocator = allocator,
|
||||||
@@ -33,14 +34,16 @@ pub fn init(allocator: Allocator, buffer: *TerminalBuffer, max_length: u64) !Tex
|
|||||||
.visible_length = 0,
|
.visible_length = 0,
|
||||||
.x = 0,
|
.x = 0,
|
||||||
.y = 0,
|
.y = 0,
|
||||||
|
.masked = masked,
|
||||||
|
.maybe_mask = maybe_mask,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn deinit(self: Text) void {
|
pub fn deinit(self: *Text) void {
|
||||||
self.text.deinit();
|
self.text.deinit(self.allocator);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn position(self: *Text, x: u64, y: u64, visible_length: u64) void {
|
pub fn position(self: *Text, x: usize, y: usize, visible_length: usize) void {
|
||||||
self.x = x;
|
self.x = x;
|
||||||
self.y = y;
|
self.y = y;
|
||||||
self.visible_length = visible_length;
|
self.visible_length = visible_length;
|
||||||
@@ -78,10 +81,25 @@ pub fn handle(self: *Text, maybe_event: ?*termbox.tb_event, insert_mode: bool) !
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (self.masked and self.maybe_mask == null) {
|
||||||
|
_ = termbox.tb_set_cursor(@intCast(self.x), @intCast(self.y));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
_ = termbox.tb_set_cursor(@intCast(self.x + (self.cursor - self.visible_start)), @intCast(self.y));
|
_ = termbox.tb_set_cursor(@intCast(self.x + (self.cursor - self.visible_start)), @intCast(self.y));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn draw(self: Text) void {
|
pub fn draw(self: Text) void {
|
||||||
|
if (self.masked) {
|
||||||
|
if (self.maybe_mask) |mask| {
|
||||||
|
const length = @min(self.text.items.len, self.visible_length - 1);
|
||||||
|
if (length == 0) return;
|
||||||
|
|
||||||
|
self.buffer.drawCharMultiple(mask, self.x, self.y, length);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const length = @min(self.text.items.len, self.visible_length);
|
const length = @min(self.text.items.len, self.visible_length);
|
||||||
if (length == 0) return;
|
if (length == 0) return;
|
||||||
|
|
||||||
@@ -96,13 +114,6 @@ pub fn draw(self: Text) void {
|
|||||||
self.buffer.drawLabel(visible_slice, self.x, self.y);
|
self.buffer.drawLabel(visible_slice, self.x, self.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn drawMasked(self: Text, mask: u8) void {
|
|
||||||
const length = @min(self.text.items.len, self.visible_length - 1);
|
|
||||||
if (length == 0) return;
|
|
||||||
|
|
||||||
self.buffer.drawCharMultiple(mask, self.x, self.y, length);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn clear(self: *Text) void {
|
pub fn clear(self: *Text) void {
|
||||||
self.text.clearRetainingCapacity();
|
self.text.clearRetainingCapacity();
|
||||||
self.end = 0;
|
self.end = 0;
|
||||||
@@ -142,7 +153,7 @@ fn backspace(self: *Text) void {
|
|||||||
fn write(self: *Text, char: u8) !void {
|
fn write(self: *Text, char: u8) !void {
|
||||||
if (char == 0) return;
|
if (char == 0) return;
|
||||||
|
|
||||||
try self.text.insert(self.cursor, char);
|
try self.text.insert(self.allocator, self.cursor, char);
|
||||||
|
|
||||||
self.end += 1;
|
self.end += 1;
|
||||||
self.goRight();
|
self.goRight();
|
||||||
|
|||||||
114
src/tui/components/generic.zig
Normal file
114
src/tui/components/generic.zig
Normal file
@@ -0,0 +1,114 @@
|
|||||||
|
const std = @import("std");
|
||||||
|
const interop = @import("../../interop.zig");
|
||||||
|
const TerminalBuffer = @import("../TerminalBuffer.zig");
|
||||||
|
|
||||||
|
pub fn CyclableLabel(comptime ItemType: type) type {
|
||||||
|
return struct {
|
||||||
|
const Allocator = std.mem.Allocator;
|
||||||
|
const ItemList = std.ArrayListUnmanaged(ItemType);
|
||||||
|
const DrawItemFn = *const fn (*Self, ItemType, usize, usize) bool;
|
||||||
|
|
||||||
|
const termbox = interop.termbox;
|
||||||
|
|
||||||
|
const Self = @This();
|
||||||
|
|
||||||
|
allocator: Allocator,
|
||||||
|
buffer: *TerminalBuffer,
|
||||||
|
list: ItemList,
|
||||||
|
current: usize,
|
||||||
|
visible_length: usize,
|
||||||
|
x: usize,
|
||||||
|
y: usize,
|
||||||
|
first_char_x: usize,
|
||||||
|
text_in_center: bool,
|
||||||
|
draw_item_fn: DrawItemFn,
|
||||||
|
|
||||||
|
pub fn init(allocator: Allocator, buffer: *TerminalBuffer, draw_item_fn: DrawItemFn) Self {
|
||||||
|
return .{
|
||||||
|
.allocator = allocator,
|
||||||
|
.buffer = buffer,
|
||||||
|
.list = .empty,
|
||||||
|
.current = 0,
|
||||||
|
.visible_length = 0,
|
||||||
|
.x = 0,
|
||||||
|
.y = 0,
|
||||||
|
.first_char_x = 0,
|
||||||
|
.text_in_center = false,
|
||||||
|
.draw_item_fn = draw_item_fn,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn deinit(self: *Self) void {
|
||||||
|
self.list.deinit(self.allocator);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn position(self: *Self, x: usize, y: usize, visible_length: usize, text_in_center: ?bool) void {
|
||||||
|
self.x = x;
|
||||||
|
self.y = y;
|
||||||
|
self.visible_length = visible_length;
|
||||||
|
self.first_char_x = x + 2;
|
||||||
|
if (text_in_center) |value| {
|
||||||
|
self.text_in_center = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn addItem(self: *Self, item: ItemType) !void {
|
||||||
|
try self.list.append(self.allocator, item);
|
||||||
|
self.current = self.list.items.len - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn handle(self: *Self, maybe_event: ?*termbox.tb_event, insert_mode: bool) void {
|
||||||
|
if (maybe_event) |event| blk: {
|
||||||
|
if (event.type != termbox.TB_EVENT_KEY) break :blk;
|
||||||
|
|
||||||
|
switch (event.key) {
|
||||||
|
termbox.TB_KEY_ARROW_LEFT, termbox.TB_KEY_CTRL_H => self.goLeft(),
|
||||||
|
termbox.TB_KEY_ARROW_RIGHT, termbox.TB_KEY_CTRL_L => self.goRight(),
|
||||||
|
else => {
|
||||||
|
if (!insert_mode) {
|
||||||
|
switch (event.ch) {
|
||||||
|
'h' => self.goLeft(),
|
||||||
|
'l' => self.goRight(),
|
||||||
|
else => {},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_ = termbox.tb_set_cursor(@intCast(self.first_char_x), @intCast(self.y));
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn draw(self: *Self) void {
|
||||||
|
if (self.list.items.len == 0) return;
|
||||||
|
|
||||||
|
const current_item = self.list.items[self.current];
|
||||||
|
const x = self.buffer.box_x + self.buffer.margin_box_h;
|
||||||
|
const y = self.buffer.box_y + self.buffer.margin_box_v + 2;
|
||||||
|
|
||||||
|
const continue_drawing = @call(.auto, self.draw_item_fn, .{ self, current_item, x, y });
|
||||||
|
if (!continue_drawing) return;
|
||||||
|
|
||||||
|
_ = termbox.tb_set_cell(@intCast(self.x), @intCast(self.y), '<', self.buffer.fg, self.buffer.bg);
|
||||||
|
_ = termbox.tb_set_cell(@intCast(self.x + self.visible_length - 1), @intCast(self.y), '>', self.buffer.fg, self.buffer.bg);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn goLeft(self: *Self) void {
|
||||||
|
if (self.current == 0) {
|
||||||
|
self.current = self.list.items.len - 1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.current -= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn goRight(self: *Self) void {
|
||||||
|
if (self.current == self.list.items.len - 1) {
|
||||||
|
self.current = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.current += 1;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
const std = @import("std");
|
|
||||||
const interop = @import("../interop.zig");
|
|
||||||
|
|
||||||
const termbox = interop.termbox;
|
|
||||||
|
|
||||||
pub fn initCell(ch: u32, fg: u16, bg: u16) termbox.tb_cell {
|
|
||||||
return .{
|
|
||||||
.ch = ch,
|
|
||||||
.fg = fg,
|
|
||||||
.bg = bg,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn putCell(x: i32, y: i32, cell: *const termbox.tb_cell) c_int {
|
|
||||||
return termbox.tb_set_cell(x, y, cell.ch, cell.fg, cell.bg);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Every codepoint is assumed to have a width of 1.
|
|
||||||
// Since ly should be running in a tty, this should be fine.
|
|
||||||
pub fn strWidth(str: []const u8) !u8 {
|
|
||||||
const utf8view = try std.unicode.Utf8View.init(str);
|
|
||||||
var utf8 = utf8view.iterator();
|
|
||||||
var i: u8 = 0;
|
|
||||||
while (utf8.nextCodepoint()) |_| i += 1;
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user