diff --git a/build.zig b/build.zig index 59f7c74..12ecb4e 100644 --- a/build.zig +++ b/build.zig @@ -83,6 +83,7 @@ pub fn build(b: *std.Build) void { .target = target, .optimize = dependency_optimize, }); + const syntax_mod = syntax_dep.module("syntax"); const thespian_dep = b.dependency("thespian", .{ .target = target, @@ -158,7 +159,7 @@ pub fn build(b: *std.Build) void { .{ .name = "thespian", .module = thespian_mod }, .{ .name = "Buffer", .module = Buffer_mod }, .{ .name = "tracy", .module = tracy_mod }, - .{ .name = "syntax", .module = syntax_dep.module("syntax") }, + .{ .name = "syntax", .module = syntax_mod }, .{ .name = "dizzy", .module = dizzy_dep.module("dizzy") }, .{ .name = "fuzzig", .module = fuzzig_dep.module("fuzzig") }, }, @@ -191,7 +192,7 @@ pub fn build(b: *std.Build) void { .{ .name = "log", .module = log_mod }, .{ .name = "location_history", .module = location_history_mod }, .{ .name = "project_manager", .module = project_manager_mod }, - .{ .name = "syntax", .module = syntax_dep.module("syntax") }, + .{ .name = "syntax", .module = syntax_mod }, .{ .name = "text_manip", .module = text_manip_mod }, .{ .name = "Buffer", .module = Buffer_mod }, .{ .name = "ripgrep", .module = ripgrep_mod }, @@ -225,6 +226,7 @@ pub fn build(b: *std.Build) void { exe.root_module.addImport("log", log_mod); exe.root_module.addImport("tracy", tracy_mod); exe.root_module.addImport("renderer", renderer_mod); + exe.root_module.addImport("syntax", syntax_mod); exe.root_module.addImport("version_info", b.createModule(.{ .root_source_file = version_info_file })); b.installArtifact(exe); @@ -255,6 +257,7 @@ pub fn build(b: *std.Build) void { check_exe.root_module.addImport("log", log_mod); check_exe.root_module.addImport("tracy", tracy_mod); check_exe.root_module.addImport("renderer", renderer_mod); + check_exe.root_module.addImport("syntax", syntax_mod); check_exe.root_module.addImport("version_info", b.createModule(.{ .root_source_file = version_info_file })); const check = b.step("check", "Check the app"); check.dependOn(&check_exe.step); diff --git a/src/list_languages.zig b/src/list_languages.zig new file mode 100644 index 0000000..4ee50a2 --- /dev/null +++ b/src/list_languages.zig @@ -0,0 +1,65 @@ +const syntax = @import("syntax"); + +pub fn list(writer: anytype) !void { + var max_language_len: usize = 0; + var max_langserver_len: usize = 0; + var max_formatter_len: usize = 0; + var max_extensions_len: usize = 0; + + for (syntax.FileType.file_types) |file_type| { + max_language_len = @max(max_language_len, file_type.name.len); + max_langserver_len = @max(max_langserver_len, args_string_length(file_type.language_server)); + max_formatter_len = @max(max_formatter_len, args_string_length(file_type.formatter)); + max_extensions_len = @max(max_extensions_len, args_string_length(file_type.extensions)); + } + + try write_string(writer, "Language", max_language_len + 1); + try write_string(writer, "Extensions", max_extensions_len + 1); + try write_string(writer, "Language Server", max_langserver_len + 1); + try write_string(writer, "Formatter", max_formatter_len); + try writer.writeAll("\n"); + + for (syntax.FileType.file_types) |file_type| { + try write_string(writer, file_type.name, max_language_len + 1); + try write_segmented(writer, file_type.extensions, ",", max_extensions_len + 1); + try write_segmented(writer, file_type.language_server, " ", max_langserver_len + 1); + try write_segmented(writer, file_type.formatter, " ", max_formatter_len); + try writer.writeAll("\n"); + } +} + +fn args_string_length(args_: ?[]const []const u8) usize { + const args = args_ orelse return 0; + var len: usize = 0; + var first: bool = true; + for (args) |arg| { + if (first) first = false else len += 1; + len += arg.len; + } + return len; +} + +fn write_string(writer: anytype, string: []const u8, pad: usize) !void { + try writer.writeAll(string); + try write_padding(writer, string.len, pad); +} + +fn write_segmented(writer: anytype, args_: ?[]const []const u8, sep: []const u8, pad: usize) !void { + const args = args_ orelse return; + var len: usize = 0; + var first: bool = true; + for (args) |arg| { + if (first) first = false else { + len += 1; + try writer.writeAll(sep); + } + len += arg.len; + try writer.writeAll(arg); + } + try write_padding(writer, len, pad); +} + +fn write_padding(writer: anytype, len: usize, pad_len: usize) !void { + for (0..pad_len - len) |_| try writer.writeAll(" "); +} + diff --git a/src/main.zig b/src/main.zig index 80a6061..fb45ae3 100644 --- a/src/main.zig +++ b/src/main.zig @@ -4,6 +4,8 @@ const thespian = @import("thespian"); const clap = @import("clap"); const builtin = @import("builtin"); +const list_languages = @import("list_languages.zig"); + const c = @cImport({ @cInclude("locale.h"); }); @@ -38,6 +40,7 @@ pub fn main() anyerror!void { \\--show-input Open the input view on start. \\--show-log Open the log view on start. \\-l, --language Force the language of the file to be opened. + \\--list-languages Show available languages. \\-v, --version Show build version and exit. \\... File or directory to open. \\ Add + to the command line or append @@ -77,6 +80,9 @@ pub fn main() anyerror!void { if (res.args.version != 0) return std.io.getStdOut().writeAll(@embedFile("version_info")); + if (res.args.@"list-languages" != 0) + return list_languages.list(std.io.getStdOut().writer()); + if (builtin.os.tag != .windows) if (std.posix.getenv("JITDEBUG")) |_| thespian.install_debugger();