Compare commits
10 commits
283bfa5407
...
a6358d5156
Author | SHA1 | Date | |
---|---|---|---|
a6358d5156 | |||
ef0088a923 | |||
50d5b969a9 | |||
a3fc96418f | |||
a84f213848 | |||
641528ac84 | |||
ec79f693a5 | |||
e3cef17b63 | |||
9e96cbb4c3 | |||
fc512c0689 |
5 changed files with 214 additions and 22 deletions
100
build.zig
100
build.zig
|
@ -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 "" });
|
||||
}
|
||||
|
|
|
@ -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
45
scripts/make_release
Executable 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
|
|
@ -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 => {},
|
||||
|
|
50
src/main.zig
50
src/main.zig
|
@ -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]);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue