Changes
12 changed files (+599/-1)
-
-
@@ -22,3 +22,8 @@ [*.nix]# Nix can't handle tab character inside string interpolation. indent_style = space indent_size = 2 [*.{zig,zon}] # Zig can't handle tab character. indent_style = space indent_size = 4
-
-
.gitignore (new)
-
@@ -0,0 +1,14 @@# Copyright 2025 Shota FUJI # # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at https://mozilla.org/MPL/2.0/. # # SPDX-License-Identifier: MPL-2.0 # Zig build system writes cache and build output to these directories. .zig-cache zig-out # Nix writes build output to this too generic named directory. result
-
-
build.zig (new)
-
@@ -0,0 +1,88 @@// Copyright 2025 Shota FUJI // // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at https://mozilla.org/MPL/2.0/. // // SPDX-License-Identifier: MPL-2.0 const std = @import("std"); const CompileVala = @import("./build/CompileVala.zig"); const manifest = @import("./build.zig.zon"); const app_name = "jp.pocka.timetracker"; pub fn build(b: *std.Build) !void { const target = b.standardTargetOptions(.{}); const optimize = b.standardOptimizeOption(.{}); const version = b.option( []const u8, "version", "Application version. Defaults to `version` field in \"build.zig.zon\".", ) orelse manifest.version; const app_id = b.option( []const u8, "app-id", b.fmt("Application ID. Defaults to \"{s}\"", .{app_name}), ) orelse app_name; // System libraries to link. const system_libraries = [_][]const u8{ "glib-2.0", "gtk4", "libadwaita-1", }; const vala_main = vala_main: { var compile = try CompileVala.init(b, .{ .src = b.path("src"), .includeTestFiles = false, }); for (system_libraries) |lib| { compile.addPackage(lib); } compile.addPackage("posix"); compile.addPackage("Config"); compile.addVapi(b.path("src/Config.vapi")); const step = b.step("valac", "Compile C source code from Vala files for debugging purpose"); step.dependOn(compile.step); break :vala_main compile; }; const exe = exe: { const exe = b.addExecutable(.{ .name = app_name, .root_module = b.createModule(.{ .link_libc = true, .target = target, .optimize = optimize, }), }); exe.root_module.addCMacro("APP_VERSION", b.fmt("\"{s}\"", .{version})); exe.root_module.addCMacro("APP_ID", b.fmt("\"{s}\"", .{app_id})); for (system_libraries) |lib| { exe.linkSystemLibrary(lib); } for (vala_main.compiled_c_files) |file| { exe.addCSourceFile(.{ .file = file }); } break :exe exe; }; // Default install step { b.installArtifact(exe); } }
-
-
build.zig.zon (new)
-
@@ -0,0 +1,21 @@// Copyright 2025 Shota FUJI // // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at https://mozilla.org/MPL/2.0/. // // SPDX-License-Identifier: MPL-2.0 .{ .name = .timetracker, .version = "0.0.0-dev", .fingerprint = 0xca682daa20529a8, .minimum_zig_version = "0.15.0", .dependencies = .{}, .paths = .{ "build/", "build.zig", "build.zig.zon", "src/", }, }
-
-
build/CompileVala.zig (new)
-
@@ -0,0 +1,131 @@// Copyright 2025 Shota FUJI // // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at https://mozilla.org/MPL/2.0/. // // SPDX-License-Identifier: MPL-2.0 const CompileVala = @This(); const std = @import("std"); step: *std.Build.Step, compiled_c_directory: std.Build.LazyPath, compiled_c_files: []std.Build.LazyPath, valac: *std.Build.Step.Run, pub const Options = struct { /// This must be an existing path. src: std.Build.LazyPath, includeTestFiles: bool = false, suppressDeprecationWarning: bool = false, }; pub fn init(b: *std.Build, opts: Options) !CompileVala { const valac = b.addSystemCommand(&.{"valac"}); // Vala source codes to compile. const vala_sources: [][]const u8 = vala_sources: { var list: std.ArrayList([]const u8) = .empty; var dir = try opts.src.getPath3(b, &valac.step).openDir("", .{ .iterate = true }); defer dir.close(); var walker = try dir.walk(b.allocator); defer walker.deinit(); while (try walker.next()) |entry| { const ext = std.fs.path.extension(entry.basename); if (std.mem.eql(u8, ".vala", ext)) { if (!opts.includeTestFiles and std.mem.endsWith(u8, entry.basename, ".test.vala")) { continue; } try list.append(b.allocator, b.dupe(entry.path)); } } break :vala_sources try list.toOwnedSlice(b.allocator); }; // Tell Vala compiler to emit C rather than compile using system C compiler. valac.addArg("--ccode"); if (opts.suppressDeprecationWarning) { valac.addArg("--enable-deprecated"); } // Tell Vala to emit C source files under the output directory. // The directory usually is Zig cache directory (like ".zig-cache/o/xxx"). // For example, when there is "src/Foo.vala", this step produces // ".zig-cache/o/hash-or-something-idk/vala/Foo.c" valac.addArg("--directory"); const dir = valac.addOutputDirectoryArg("vala"); // Let valac emit C source code without prefixing using directory. valac.addArg("--basedir"); valac.addDirectoryArg(opts.src); // Vala compiler takes a list of Vala source files, then process them all. for (vala_sources) |src| { valac.addFileArg(try opts.src.join(b.allocator, src)); } const t = b.addInstallDirectory(.{ .source_dir = dir, .install_dir = .{ .custom = "src" }, .install_subdir = "", }); const compiled_c_files = try b.allocator.alloc(std.Build.LazyPath, vala_sources.len); for (vala_sources, 0..) |src, i| { // Looks fragile but it works. Even if it produced incorrect paths, // filesystem and Zig compiler will tell us a file is missing. const rel_path = b.fmt("{s}.c", .{src[0..(src.len - 5)]}); // src = "src/Foo.vala" // rel_path = "Foo.c" // file = "(step cache directory)/vala/Foo.c" compiled_c_files[i] = try dir.join(b.allocator, rel_path); } return .{ .step = &t.step, .compiled_c_directory = dir, .compiled_c_files = compiled_c_files, .valac = valac, }; } pub fn addPackage(self: *CompileVala, pkg: []const u8) void { self.valac.addArg("--pkg"); self.valac.addArg(pkg); } pub fn addPackages(self: *CompileVala, pkgs: []const []const u8) void { for (pkgs) |pkg| { self.addPackage(pkg); } } pub fn addVapi(self: *CompileVala, file: std.Build.LazyPath) void { self.valac.addArg("--vapidir"); self.valac.addDirectoryArg(file.dirname()); self.valac.addFileInput(file); } pub fn addGResourceXML(self: *CompileVala, path: std.Build.LazyPath) void { self.valac.addArg("--gresources"); self.valac.addFileArg(path); } pub fn getCompiledCDirectory(self: CompileVala) std.Build.LazyPath { return self.compiled_c_directory; } pub fn getCompiledCFiles(self: CompileVala) []std.Build.LazyPath { return self.compiled_c_files; }
-
-
default.nix (new)
-
@@ -0,0 +1,80 @@# Copyright 2025 Shota FUJI # # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at https://mozilla.org/MPL/2.0/. # # SPDX-License-Identifier: MPL-2.0 { lib, stdenvNoCC, zig, vala, pkg-config, wrapGAppsHook4, glib, gtk4, libadwaita, }: stdenvNoCC.mkDerivation { pname = "timetracker"; version = "0.0.0-dev"; src = with lib.filset; toSource { root = ./.; fileset = unions [ ./src ./build ./build.zig ./build.zig.zon ]; }; meta = { mainProgram = "jp.pocka.timetracker"; }; nativeBuildInputs = [ zig.hook # > Zig is a general-purpose programming language and toolchain for maintaining # > robust, optimal and reusable software. # https://ziglang.org/ zig # > pkg-config is a helper tool used when compiling applications and libraries. # https://www.freedesktop.org/wiki/Software/pkg-config/ pkg-config # > Vala is a programming language using modern high level abstractions without # > imposing additional runtime requirements and without using a different ABI # > compared to applications and libraries written in C. # https://vala.dev/ vala # This helper takes care of GLib/GTK's messy runtime things. # https://nixos.org/manual/nixpkgs/stable/#sec-language-gnome wrapGAppsHook4 ]; buildInputs = [ # > C library of programming buildings blocks # https://gitlab.gnome.org/GNOME/glib glib # > The GTK toolkit # https://docs.gtk.org/gtk4/ gtk4 # Provides styles and widgets following GNOME Human Interface Guideline. # (https://developer.gnome.org/hig/index.html) # > Building blocks for modern GNOME applications # https://gnome.pages.gitlab.gnome.org/libadwaita/ # https://gnome.pages.gitlab.gnome.org/libadwaita/doc/1-latest/ # https://valadoc.org/libadwaita-1/index.htm libadwaita ]; }
-
-
-
@@ -18,6 +18,19 @@ "exec": {"cwd": "${configDir}", "commands": [ { "exts": ["zig"], "command": "zig fmt --stdin", }, { "exts": ["zon"], "command": "zig fmt --zon --stdin", }, { "exts": ["vala"], "command": "uncrustify -c uncrustify.cfg -l VALA", "cacheKeyFiles": ["uncrustify.cfg"], }, { "exts": ["nix"], "command": "nixfmt --strict --width={{line_width}} --indent={{indent_width}}", },
-
-
-
@@ -33,12 +33,28 @@ pkgs = nixpkgs.legacyPackages.${system};} ); in { rec { packages = forEachSystems ( { pkgs, ... }: { default = pkgs.callPackage ./default.nix { }; } ); devShells = forEachSystems ( { pkgs, system }: { default = pkgs.mkShell { buildInputs = [ (pkgs.lib.lists.remove pkgs.zig.hook packages.${system}.default.nativeBuildInputs) packages.${system}.default.buildInputs ]; packages = with pkgs; [ # > Zig LSP implementation + Zig Language Server # https://github.com/zigtools/zls zls # > Tool for compliance with the REUSE Initiative recommendations # https://github.com/fsfe/reuse-tool # https://reuse.software/
-
@@ -47,6 +63,10 @@# > Code formatting platform written in Rust # https://dprint.dev/ dprint # > Source Code Beautifier for C, C++, C#, ObjectiveC, D, Java, Pawn and VALA # https://uncrustify.sourceforge.net/ uncrustify # > Official formatter for Nix code # https://github.com/NixOS/nixfmt
-
-
src/Application.vala (new)
-
@@ -0,0 +1,23 @@// Copyright 2025 Shota FUJI // // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at https://mozilla.org/MPL/2.0/. // // SPDX-License-Identifier: MPL-2.0 namespace TimeTracker { public class Application : Adw.Application { public Application() { Object(application_id: Config.APP_ID); } protected override void activate() { var window = new Gtk.ApplicationWindow(this) { title = "Sample" }; window.present(); } } }
-
-
src/Config.vapi (new)
-
@@ -0,0 +1,15 @@// Copyright 2025 Shota FUJI // // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at https://mozilla.org/MPL/2.0/. // // SPDX-License-Identifier: MPL-2.0 namespace Config { [CCode (cname = "APP_ID")] public const string APP_ID; [CCode (cname = "APP_VERSION")] public const string APP_VERSION; }
-
-
src/main.vala (new)
-
@@ -0,0 +1,13 @@// Copyright 2025 Shota FUJI // // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at https://mozilla.org/MPL/2.0/. // // SPDX-License-Identifier: MPL-2.0 static int main(string[] args) { var app = new TimeTracker.Application(); return app.run(args); }
-
-
uncrustify.cfg (new)
-
@@ -0,0 +1,175 @@# Configurations for Uncrustify, code formatter tool. # This file is based on: # https://codeberg.org/pocka/plac-for-gtk4/src/tag/v0.2.0/uncrustify.cfg # # Copyright 2025 Shota FUJI # # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at https://mozilla.org/MPL/2.0/. # # SPDX-License-Identifier: MPL-2.0 # The type of line endings. newlines = lf # The size of tabs in the output (only used if align_with_tabs=true). output_tab_size = 8 # Add or remove the UTF-8 BOM (recommend 'remove'). utf8_bom = remove # If the file contains bytes with values between 128 and 255, but is not # UTF-8, then output as UTF-8. utf8_byte = true # Force the output encoding to UTF-8. utf8_force = true # Add or remove space around non-assignment symbolic operators ('+', '/', '%', # '<<', and so forth). sp_arith = add # Add or remove space around assignment operator '=', '+=', etc. sp_assign = add # Add or remove space around assignment operator '=' in a prototype. # # If set to ignore, use sp_assign. sp_assign_default = add # Add or remove space before assignment operator '=', '+=', etc. # # Overrides sp_assign. sp_before_assign = add # Add or remove space after assignment operator '=', '+=', etc. # # Overrides sp_assign. sp_after_assign = add # Add or remove space around boolean operators '&&' and '||'. sp_bool = add # Add or remove space around compare operator '<', '>', '==', etc. sp_compare = add # Add or remove space inside '(' and ')'. sp_inside_paren = remove # Add or remove space inside function '(' and ')'. sp_inside_fparen = remove # Add or remove space between nested parentheses, i.e. '((' vs. ') )'. sp_paren_paren = remove # Add or remove space between back-to-back parentheses, i.e. ')(' vs. ') ('. sp_cparen_oparen = remove # Add or remove space between ')' and '{'. sp_paren_brace = add # Add or remove space between nested braces, i.e. '{{' vs. '{ {'. sp_brace_brace = remove # Add or remove space between '>' and '(' as found in 'new List<byte>(foo);'. sp_angle_paren = remove # Add or remove space between '>' and '()' as found in 'new List<byte>();'. sp_angle_paren_empty = remove # Add or remove space between '>' and a word as in 'List<byte> m;' or # 'template <typename T> static ...'. sp_angle_word = remove # Add or remove space before '(' of control statements ('if', 'for', 'switch', # 'while', etc.). sp_before_sparen = add # Add or remove space inside '(' and ')' of control statements other than # 'for'. sp_inside_sparen = remove # Add or remove space between ')' and '{' of control statements. sp_sparen_brace = add # Add or remove space after ',', i.e. 'a,b' vs. 'a, b'. sp_after_comma = add # Add or remove space between '>' and a word as in 'List<byte> m;' or # 'template <typename T> static ...'. sp_angle_word = add # (C#, Vala) Add or remove space between ',' and ']' in multidimensional array type # like 'int[,,]'. sp_after_mdatype_commas = remove # (C#, Vala) Add or remove space between '[' and ',' in multidimensional array type # like 'int[,,]'. sp_before_mdatype_commas = remove # (C#, Vala) Add or remove space between ',' in multidimensional array type # like 'int[,,]'. sp_between_mdatype_commas = remove # Add or remove space between a type and ':'. sp_type_colon = add # Add or remove space inside struct/union '{' and '}'. sp_inside_braces_struct = add # Add or remove space inside '{' and '}'. sp_inside_braces = add # Add or remove space inside '{}'. # if empty. sp_inside_braces_empty = remove # Add or remove space between type and open brace of an unnamed temporary # direct-list-initialization. sp_type_brace_init_lst = add # Add or remove space between function name and '(' on function declaration. sp_func_proto_paren = remove # Add or remove space between function name and '(' with a typedef specifier. sp_func_type_paren = remove # Add or remove space between alias name and '(' of a non-pointer function type typedef. sp_func_def_paren = remove # Add or remove space between ')' and '{' of a function call in object # initialization. # # Overrides sp_fparen_brace. sp_fparen_brace_initializer = add # Add or remove space between function name and '(' on function calls. sp_func_call_paren = remove # Add or remove space between a constructor/destructor and the open # parenthesis. sp_func_class_paren = remove # Add or remove space between 'else' and '{' if on the same line. sp_else_brace = force # Add or remove space between '}' and 'else' if on the same line. sp_brace_else = force # Whether the 'class' body is indented. indent_class = true # Whether to indent the body of a 'namespace'. indent_namespace = true # How to indent a close parenthesis after a newline. # # 0: Indent to body level (default) # 1: Align under the open parenthesis # 2: Indent to the brace level # -1: Preserve original indentation indent_paren_close = 2 # Whether to remove blank lines before '}'. eat_blanks_before_close_brace = true
-