Compare commits

..

10 commits

5 changed files with 214 additions and 22 deletions

100
build.zig
View file

@ -1,9 +1,92 @@
const std = @import("std");
pub fn build(b: *std.Build) void {
const release = b.option(bool, "package_release", "Build all release targets") orelse false;
const strip = b.option(bool, "strip", "Disable debug information (default: no)");
const pie = b.option(bool, "pie", "Produce an executable with position independent code (default: none)");
const run_step = b.step("run", "Run the app");
return (if (release) &build_release else &build_development)(
b,
run_step,
strip,
pie,
);
}
fn build_development(
b: *std.Build,
run_step: *std.Build.Step,
strip: ?bool,
pie: ?bool,
) void {
const target = b.standardTargetOptions(.{});
const optimize = b.standardOptimizeOption(.{});
return build_exe(
b,
run_step,
target,
optimize,
.{},
strip orelse false,
pie,
);
}
fn build_release(
b: *std.Build,
run_step: *std.Build.Step,
strip: ?bool,
pie: ?bool,
) void {
const targets: []const std.Target.Query = &.{
.{ .cpu_arch = .x86_64, .os_tag = .linux, .abi = .musl },
.{ .cpu_arch = .aarch64, .os_tag = .linux, .abi = .musl },
.{ .cpu_arch = .x86_64, .os_tag = .macos },
.{ .cpu_arch = .aarch64, .os_tag = .macos },
.{ .cpu_arch = .x86_64, .os_tag = .windows },
.{ .cpu_arch = .aarch64, .os_tag = .windows },
};
const optimize = .ReleaseFast;
var version = std.ArrayList(u8).init(b.allocator);
defer version.deinit();
gen_version(b, version.writer()) catch unreachable;
const write_file_step = b.addWriteFiles();
const version_file = write_file_step.add("version", version.items);
b.getInstallStep().dependOn(&b.addInstallFile(version_file, "version").step);
for (targets) |t| {
const target = b.resolveTargetQuery(t);
var triple = std.mem.splitScalar(u8, t.zigTriple(b.allocator) catch unreachable, '-');
const arch = triple.next() orelse unreachable;
const os = triple.next() orelse unreachable;
const target_path = std.mem.join(b.allocator, "-", &[_][]const u8{ os, arch }) catch unreachable;
build_exe(
b,
run_step,
target,
optimize,
.{ .dest_dir = .{ .override = .{ .custom = target_path } } },
strip orelse true,
pie,
);
}
}
pub fn build_exe(
b: *std.Build,
run_step: *std.Build.Step,
target: std.Build.ResolvedTarget,
optimize: std.builtin.OptimizeMode,
exe_install_options: std.Build.Step.InstallArtifact.Options,
strip: bool,
pie: ?bool,
) void {
const clap_dep = b.dependency("clap", .{ .target = target, .optimize = optimize });
const ansi_term_dep = b.dependency("ansi-term", .{ .target = target, .optimize = optimize });
const themes_dep = b.dependency("themes", .{});
@ -15,18 +98,31 @@ pub fn build(b: *std.Build) void {
.root_source_file = b.path("src/main.zig"),
.target = target,
.optimize = optimize,
.strip = strip,
});
if (pie) |value| exe.pie = value;
exe.root_module.addImport("syntax", syntax_dep.module("syntax"));
exe.root_module.addImport("theme", themes_dep.module("theme"));
exe.root_module.addImport("themes", themes_dep.module("themes"));
exe.root_module.addImport("clap", clap_dep.module("clap"));
exe.root_module.addImport("ansi-term", ansi_term_dep.module("ansi-term"));
exe.root_module.addImport("cbor", b.createModule(.{ .root_source_file = thespian_dep.path("src/cbor.zig") }));
b.installArtifact(exe);
const exe_install = b.addInstallArtifact(exe, exe_install_options);
b.getInstallStep().dependOn(&exe_install.step);
const run_cmd = b.addRunArtifact(exe);
run_cmd.step.dependOn(b.getInstallStep());
if (b.args) |args| run_cmd.addArgs(args);
const run_step = b.step("run", "Run the app");
run_step.dependOn(&run_cmd.step);
}
fn gen_version(b: *std.Build, writer: anytype) !void {
var code: u8 = 0;
const describe = try b.runAllowFail(&[_][]const u8{ "git", "describe", "--always", "--tags" }, &code, .Ignore);
const diff_ = try b.runAllowFail(&[_][]const u8{ "git", "diff", "--stat", "--patch", "HEAD" }, &code, .Ignore);
const diff = std.mem.trimRight(u8, diff_, "\r\n ");
const version = std.mem.trimRight(u8, describe, "\r\n ");
try writer.print("{s}{s}", .{ version, if (diff.len > 0) "-dirty" else "" });
}

View file

@ -1,18 +1,18 @@
.{
.name = "zat",
.version = "0.0.1",
.version = "1.0.0",
.dependencies = .{
.clap = .{
.url = "https://github.com/Hejsil/zig-clap/archive/c0193e9247335a6c1688b946325060289405de2a.tar.gz",
.hash = "12207ee987ce045596cb992cfb15b0d6d9456e50d4721c3061c69dabc2962053644d",
},
.themes = .{
.url = "https://github.com/neurocyte/flow-themes/releases/download/master-08c07e21c47abe41ebd16ee260438da5b4c2039e/flow-themes.tar.gz",
.hash = "12202be270e675e3b61d96845baad143494539b167bcb8b1ef32659bf146dd85d3e1",
.url = "https://github.com/neurocyte/flow-themes/releases/download/master-618a7801d3383049adfe18cc09f5f5086c66995f/flow-themes.tar.gz",
.hash = "1220019ed92f48fb94d4ae82bba17b11d0ba06f17ed31cd66613b3c048b1d2382095",
},
.syntax = .{
.url = "https://github.com/neurocyte/flow-syntax/archive/dcfa5cdf3f1f48411dc3c7ab8be26b7561673850.tar.gz",
.hash = "1220ea88bb77cba3cf85caeb8002823218503c601f9907ccffbd41329c632596ebc3",
.url = "https://github.com/neurocyte/flow-syntax/archive/28bc77f4615488aaa269c25fc862864f4b3a7460.tar.gz",
.hash = "1220abddc10ca8f8b6b5477f8c007948c168504b9dd3516899fe37251890eeabf4ab",
},
.thespian = .{
.url = "https://github.com/neurocyte/thespian/archive/d7dd27116398b17c8ab68327c384885f161d0cc1.tar.gz",

45
scripts/make_release Executable file
View file

@ -0,0 +1,45 @@
#!/bin/bash
set -e
BASEDIR="$(cd "$(dirname "$0")/.." && pwd)"
APPNAME="$(basename "$BASEDIR")"
cd "$BASEDIR"
if [ -e "release" ]; then
echo directory \"release\" already exists
exit 1
fi
echo building...
./zig build -Dpackage_release --prefix release/build
cd release/build
VERSION=$(/bin/cat version)
TARGETS=$(/bin/ls)
for target in $TARGETS; do
if [ -d "$target" ]; then
cd "$target"
echo packing "$target"...
tar -czf "../../${APPNAME}-${VERSION}-${target}.tar.gz" -- *
cd ..
fi
done
cd ..
rm -r build
TARFILES=$(/bin/ls)
for tarfile in $TARFILES; do
echo signing "$tarfile"...
gpg --local-user 4E6CF7234FFC4E14531074F98EB1E1BB660E3FB9 --detach-sig "$tarfile"
done
echo "done making release $VERSION"
echo
/bin/ls -lah

View file

@ -1,5 +1,6 @@
const std = @import("std");
const cbor = @import("cbor");
const builtin = @import("builtin");
const application_name = "flow";
@ -48,18 +49,36 @@ pub fn get_config_dir() ![]const u8 {
}
fn get_app_config_dir(appname: []const u8) ![]const u8 {
const a = std.heap.c_allocator;
const local = struct {
var config_dir_buffer: [std.posix.PATH_MAX]u8 = undefined;
var config_dir: ?[]const u8 = null;
};
const config_dir = if (local.config_dir) |dir|
dir
else if (std.posix.getenv("XDG_CONFIG_HOME")) |xdg|
try std.fmt.bufPrint(&local.config_dir_buffer, "{s}/{s}", .{ xdg, appname })
else if (std.posix.getenv("HOME")) |home|
try std.fmt.bufPrint(&local.config_dir_buffer, "{s}/.config/{s}", .{ home, appname })
else
return error.AppConfigDirUnavailable;
else if (std.process.getEnvVarOwned(a, "XDG_CONFIG_HOME") catch null) |xdg| ret: {
defer a.free(xdg);
break :ret try std.fmt.bufPrint(&local.config_dir_buffer, "{s}/{s}", .{ xdg, appname });
} else if (std.process.getEnvVarOwned(a, "HOME") catch null) |home| ret: {
defer a.free(home);
const dir = try std.fmt.bufPrint(&local.config_dir_buffer, "{s}/.config", .{home});
std.fs.makeDirAbsolute(dir) catch |e| switch (e) {
error.PathAlreadyExists => {},
else => return e,
};
break :ret try std.fmt.bufPrint(&local.config_dir_buffer, "{s}/.config/{s}", .{ home, appname });
} else if (builtin.os.tag == .windows) ret: {
if (std.process.getEnvVarOwned(a, "APPDATA") catch null) |appdata| {
defer a.free(appdata);
const dir = try std.fmt.bufPrint(&local.config_dir_buffer, "{s}/{s}", .{ appdata, appname });
std.fs.makeDirAbsolute(dir) catch |e| switch (e) {
error.PathAlreadyExists => {},
else => return e,
};
break :ret dir;
} else return error.AppConfigDirUnavailable;
} else return error.AppConfigDirUnavailable;
local.config_dir = config_dir;
std.fs.makeDirAbsolute(config_dir) catch |e| switch (e) {
error.PathAlreadyExists => {},

View file

@ -20,6 +20,7 @@ pub fn main() !void {
\\-t, --theme <name> Select theme to use.
\\-d, --default <name> Set the language to use if guessing failed (default: conf).
\\-s, --show-language Show detected language in output.
\\-C, --color Always produce color output, even if stdout is not a tty.
\\--html Output HTML instead of ansi escape codes.
\\--list-themes Show available themes.
\\--list-languages Show available language parsers.
@ -53,8 +54,9 @@ pub fn main() !void {
};
defer res.deinit();
const stdout_file = std.io.getStdOut().writer();
var bw = std.io.bufferedWriter(stdout_file);
const stdout_file = std.io.getStdOut();
const stdout_writer = stdout_file.writer();
var bw = std.io.bufferedWriter(stdout_writer);
const writer = bw.writer();
defer bw.flush() catch {};
@ -67,6 +69,9 @@ pub fn main() !void {
if (res.args.@"list-languages" != 0)
return list_langs(writer);
if (res.args.color == 0 and !stdout_file.supportsAnsiEscapeCodes())
return plain_cat(res.positionals);
var conf_buf: ?[]const u8 = null;
const conf = config_loader.read_config(a, &conf_buf);
const theme_name = if (res.args.theme) |theme| theme else conf.theme;
@ -103,7 +108,10 @@ pub fn main() !void {
if (res.positionals.len > 0) {
for (res.positionals) |arg| {
const file = try std.fs.cwd().openFile(arg, .{ .mode = .read_only });
const file = if (std.mem.eql(u8, arg, "-"))
std.io.getStdIn()
else
try std.fs.cwd().openFile(arg, .{ .mode = .read_only });
defer file.close();
const content = try file.readToEndAlloc(a, std.math.maxInt(u32));
defer a.free(content);
@ -392,8 +400,8 @@ fn list_themes(writer: Writer) !void {
fn set_ansi_style(writer: Writer, style: Theme.Style) Writer.Error!void {
const ansi_style = .{
.foreground = if (style.fg) |color| to_rgb_color(color) else .Default,
.background = if (style.bg) |color| to_rgb_color(color) else .Default,
.foreground = if (style.fg) |color| to_rgb_color(color.color) else .Default,
.background = if (style.bg) |color| to_rgb_color(color.color) else .Default,
.font_style = switch (style.fs orelse .normal) {
.normal => term.style.FontStyle{},
.bold => term.style.FontStyle.bold,
@ -409,8 +417,8 @@ fn set_ansi_style(writer: Writer, style: Theme.Style) Writer.Error!void {
const unset_ansi_style = set_ansi_style;
fn write_html_preamble(writer: Writer, style: Theme.Style) !void {
const color = if (style.fg) |color| color else 0;
const background = if (style.bg) |background| background else 0xFFFFFF;
const color = if (style.fg) |color| color.color else 0;
const background = if (style.bg) |background| background.color else 0xFFFFFF;
try writer.writeAll("<div style=\"color:");
try write_hex_color(writer, color);
try writer.writeAll(";background-color:");
@ -423,7 +431,7 @@ fn write_html_postamble(writer: Writer) !void {
}
fn set_html_style(writer: Writer, style: Theme.Style) !void {
const color = if (style.fg) |color| color else 0;
const color = if (style.fg) |color| color.color else 0;
try writer.writeAll("<span style=\"color:");
try write_hex_color(writer, color);
switch (style.fs orelse .normal) {
@ -466,7 +474,7 @@ fn render_file_type(writer: Writer, file_type: *const syntax.FileType, theme: *c
try set_ansi_style(writer, reversed);
try writer.writeAll("");
try set_ansi_style(writer, .{
.fg = if (file_type.color == 0xFFFFFF or file_type.color == 0x000000) style.fg else file_type.color,
.fg = if (file_type.color == 0xFFFFFF or file_type.color == 0x000000) style.fg else .{ .color = file_type.color },
.bg = style.bg,
});
try writer.writeAll(file_type.icon);
@ -478,3 +486,27 @@ fn render_file_type(writer: Writer, file_type: *const syntax.FileType, theme: *c
try set_ansi_style(writer, plain);
try writer.writeAll("\n");
}
fn plain_cat(files: []const []const u8) !void {
const stdout = std.io.getStdOut();
if (files.len == 0) {
try plain_cat_file(stdout, "-");
} else {
for (files) |file| try plain_cat_file(stdout, file);
}
}
fn plain_cat_file(out_file: std.fs.File, in_file_name: []const u8) !void {
var in_file = if (std.mem.eql(u8, in_file_name, "-"))
std.io.getStdIn()
else
try std.fs.cwd().openFile(in_file_name, .{});
defer in_file.close();
var buf: [std.mem.page_size]u8 = undefined;
while (true) {
const bytes_read = try in_file.read(&buf);
if (bytes_read == 0) return;
try out_file.writeAll(buf[0..bytes_read]);
}
}