Compare commits

...

6 commits

Author SHA1 Message Date
435a3edb9a
Merge branch 'master' into zig-0.15 2025-08-23 17:47:34 +02:00
Daggerfall-is-the-best-TES-game
7a705a4eb4
change python default lsp to ruff
ruff is much faster than pylsp so it would be a good fit for flow

closes neurocyte/flow-syntax#13
2025-08-23 17:35:29 +02:00
5dfa156fd6
build: update flow-syntax to drop lsp configuration fields 2025-08-23 17:35:23 +02:00
cc3ac7e58d
refactor: move default language_server and formatter config to file_type_lsp.zig
From flow-syntax commit 410d19e633f237cd1602175450bd7d3bb03a1898.
2025-08-23 17:28:32 +02:00
dad954da1a
fix: don't falsely claim to support LSP pull diagnostics
closes #285
2025-08-22 22:24:32 +02:00
5286975257
fix: move internal clipboard from buffer local to session wide
closes #287
2025-08-22 22:18:57 +02:00
7 changed files with 290 additions and 24 deletions

View file

@ -6,8 +6,8 @@
.dependencies = .{
.syntax = .{
.url = "git+https://github.com/neurocyte/flow-syntax?ref=master#2c28091fe5ccfe66b304da0532b46f98fa1c28d3",
.hash = "flow_syntax-0.1.0-X8jOockOAQBBkI-6qpOw17CjdlrQeRhiFJFszv9U_THm",
.url = "git+https://github.com/neurocyte/flow-syntax?ref=master#ed50776aaeadc0ebee99ed8c5dfb79669a855e63",
.hash = "flow_syntax-0.1.0-X8jOobQCAQDn-J1dyBRKmsSnUt0h_x6YqHxeEq44Ib6t",
},
.flags = .{
.url = "git+https://github.com/neurocyte/flags?ref=main#984b27948da3e4e40a253f76c85b51ec1a9ada11",

View file

@ -1872,10 +1872,6 @@ fn send_lsp_init_request(self: *Self, lsp: *const LSP, project_path: []const u8,
},
},
},
.diagnostic = .{
.dynamicRegistration = true,
.relatedDocumentSupport = false,
},
},
.window = .{
.showMessage = .{

View file

@ -23,6 +23,7 @@ pub const default = struct {
pub const folder_icon = "";
fn from_file_type(file_type: syntax.FileType) @This() {
const lsp_defaults: LspDefaults = static_file_type_lsp_defaults.get(file_type.name) orelse .{};
return .{
.name = file_type.name,
.color = file_type.color,
@ -33,8 +34,8 @@ fn from_file_type(file_type: syntax.FileType) @This() {
.first_line_matches_content = if (file_type.first_line_matches) |flm| flm.content else null,
.parser = file_type.name,
.comment = file_type.comment,
.formatter = file_type.formatter,
.language_server = file_type.language_server,
.formatter = lsp_defaults.formatter,
.language_server = lsp_defaults.language_server,
};
}
@ -199,6 +200,46 @@ pub fn create_syntax_guess_file_type(
return create_syntax(file_type, allocator, query_cache);
}
const static_file_type_lsp_defaults_list = load_file_type_lsp_defaults(@import("file_type_lsp.zig"));
const static_file_type_lsp_defaults = std.StaticStringMap(LspDefaults).initComptime(static_file_type_lsp_defaults_list);
const LspDefaults = struct {
formatter: ?[]const []const u8 = null,
language_server: ?[]const []const u8 = null,
};
const ListEntry = struct { []const u8, LspDefaults };
fn load_file_type_lsp_defaults(comptime Namespace: type) []const ListEntry {
comptime switch (@typeInfo(Namespace)) {
.@"struct" => |info| {
var count = 0;
for (info.decls) |_| count += 1;
var construct_types: [count]ListEntry = undefined;
var i = 0;
for (info.decls) |decl| {
const lang = decl.name;
const args = @field(Namespace, lang);
construct_types[i] = .{ lang, .{
.formatter = if (@hasField(@TypeOf(args), "formatter")) vec(args.formatter) else null,
.language_server = if (@hasField(@TypeOf(args), "language_server")) vec(args.language_server) else null,
} };
i += 1;
}
const types = construct_types;
return &types;
},
else => @compileError("expected tuple or struct type"),
};
}
fn vec(comptime args: anytype) []const []const u8 {
var cmd: []const []const u8 = &[_][]const u8{};
inline for (args) |arg| {
cmd = cmd ++ [_][]const u8{arg};
}
return cmd;
}
const syntax = @import("syntax");
const std = @import("std");
const root = @import("root");

224
src/file_type_lsp.zig Normal file
View file

@ -0,0 +1,224 @@
pub const agda = .{};
pub const astro = .{
.language_server = .{ "astro-ls", "--stdio" },
};
pub const bash = .{
.language_server = .{ "bash-language-server", "start" },
.formatter = .{ "shfmt", "--indent", "4" },
};
pub const c = .{
.language_server = .{"clangd"},
.formatter = .{"clang-format"},
};
pub const @"c-sharp" = .{
.language_server = .{ "OmniSharp", "-lsp" },
.formatter = .{ "csharpier", "format" },
};
pub const conf = .{};
pub const cmake = .{
.language_server = .{"cmake-language-server"},
.formatter = .{"cmake-format"},
};
pub const cpp = .{
.language_server = .{"clangd"},
.formatter = .{"clang-format"},
};
pub const css = .{
.language_server = .{ "vscode-css-language-server", "--stdio" },
};
pub const diff = .{};
pub const dockerfile = .{};
pub const dtd = .{};
pub const elixir = .{
.language_server = .{"elixir-ls"},
.formatter = .{ "mix", "format", "-" },
};
pub const fish = .{};
pub const @"git-rebase" = .{};
pub const gitcommit = .{};
pub const gleam = .{
.language_server = .{ "gleam", "lsp" },
.formatter = .{ "gleam", "format", "--stdin" },
};
pub const go = .{
.language_server = .{"gopls"},
.formatter = .{"gofmt"},
};
pub const hare = .{};
pub const haskell = .{
.language_server = .{ "haskell-language-server-wrapper", "lsp" },
};
pub const html = .{
.language_server = .{ "superhtml", "lsp" }, // https://github.com/kristoff-it/super-html.git
.formatter = .{ "superhtml", "fmt", "--stdin" },
};
pub const superhtml = .{
.language_server = .{ "superhtml", "lsp" },
.formatter = .{ "superhtml", "fmt", "--stdin-super" },
};
pub const hurl = .{};
pub const java = .{};
pub const javascript = .{
.language_server = .{ "typescript-language-server", "--stdio" },
.formatter = .{ "prettier", "--parser", "typescript" },
};
pub const json = .{
.language_server = .{ "vscode-json-language-server", "--stdio" },
.formatter = .{ "prettier", "--parser", "json" },
};
pub const julia = .{
.language_server = .{ "julia", "-e", "using LanguageServer; runserver()" },
.formatter = .{ "julia", "-e", "using JuliaFormatter; print(format_text(read(stdin, String)))" },
};
pub const kdl = .{};
pub const lua = .{
.language_server = .{"lua-lsp"},
};
pub const mail = .{};
pub const make = .{};
pub const markdown = .{
.language_server = .{ "marksman", "server" },
.formatter = .{ "prettier", "--parser", "markdown" },
};
pub const @"markdown-inline" = .{};
pub const nasm = .{};
pub const nim = .{
.language_server = .{"nimlangserver"},
};
pub const nimble = .{};
pub const ninja = .{};
pub const nix = .{
.language_server = .{"nixd"},
.formatter = .{"alejandra"},
};
pub const nu = .{
.language_server = .{ "nu", "--lsp" },
};
pub const ocaml = .{
.language_server = .{ "ocamllsp", "--fallback-read-dot-merlin" },
.formatter = .{ "ocamlformat", "--profile=ocamlformat", "-" },
};
pub const odin = .{
.language_server = .{"ols"},
.formatter = .{ "odinfmt", "-stdin" },
};
pub const openscad = .{
.language_server = .{"openscad-lsp"},
};
pub const org = .{};
pub const php = .{
.language_server = .{ "intelephense", "--stdio" },
};
pub const powershell = .{};
pub const proto = .{};
pub const purescript = .{};
pub const python = .{
.language_server = .{ "ruff", "server" },
.formatter = .{ "ruff", "format", "-" },
};
pub const regex = .{};
pub const rpmspec = .{};
pub const ruby = .{
.language_server = .{"ruby-lsp"},
};
pub const rust = .{
.language_server = .{"rust-analyzer"},
.formatter = .{"rustfmt"},
};
pub const scheme = .{};
pub const sql = .{};
pub const @"ssh-config" = .{};
pub const swift = .{
.language_server = .{"sourcekit-lsp"},
.formatter = .{"swift-format"},
};
pub const verilog = .{
.language_server = .{"verible-verilog-ls"},
.formatter = .{ "verible-verilog-format", "-" },
};
pub const toml = .{};
pub const typescript = .{
.language_server = .{ "typescript-language-server", "--stdio" },
.formatter = .{ "prettier", "--parser", "typescript" },
};
pub const typst = .{
.language_server = .{"tinymist"},
};
pub const uxntal = .{};
pub const vim = .{};
pub const xml = .{
.formatter = .{ "xmllint", "--format", "-" },
};
pub const yaml = .{};
pub const zig = .{
.language_server = .{"zls"},
.formatter = .{ "zig", "fmt", "--stdin" },
};
pub const ziggy = .{};
pub const @"ziggy-schema" = .{};

View file

@ -280,7 +280,6 @@ pub const Editor = struct {
cursels_saved: CurSel.List = .empty,
selection_mode: SelectMode = .char,
selection_drag_initial: ?Selection = null,
clipboard: ?[]const u8 = null,
target_column: ?Cursor = null,
filter_: ?struct {
before_root: Buffer.Root,
@ -385,9 +384,8 @@ pub const Editor = struct {
}
pub fn write_state(self: *const Self, writer: Buffer.MetaWriter) !void {
try cbor.writeArrayHeader(writer, 12);
try cbor.writeArrayHeader(writer, 11);
try cbor.writeValue(writer, self.file_path orelse "");
try cbor.writeValue(writer, self.clipboard orelse "");
try cbor.writeValue(writer, self.last_find_query orelse "");
try cbor.writeValue(writer, self.enable_format_on_save);
try cbor.writeValue(writer, self.enable_auto_save);
@ -419,12 +417,10 @@ pub const Editor = struct {
var file_path: []const u8 = undefined;
var view_cbor: []const u8 = undefined;
var cursels_cbor: []const u8 = undefined;
var clipboard: []const u8 = undefined;
var last_find_query: []const u8 = undefined;
var find_history: []const u8 = undefined;
if (!try cbor.matchValue(iter, .{
tp.extract(&file_path),
tp.extract(&clipboard),
tp.extract(&last_find_query),
tp.extract(&self.enable_format_on_save),
tp.extract(&self.enable_auto_save),
@ -440,7 +436,6 @@ pub const Editor = struct {
self.refresh_tab_width();
if (op == .open_file)
try self.open(file_path);
self.clipboard = if (clipboard.len > 0) try self.allocator.dupe(u8, clipboard) else null;
self.last_find_query = if (last_find_query.len > 0) try self.allocator.dupe(u8, last_find_query) else null;
const rows = self.view.rows;
const cols = self.view.cols;
@ -2605,9 +2600,7 @@ pub const Editor = struct {
pub const scroll_view_bottom_meta: Meta = .{};
fn set_clipboard(self: *Self, text: []const u8) void {
if (self.clipboard) |old|
self.allocator.free(old);
self.clipboard = text;
tui.set_clipboard(text);
if (builtin.os.tag == .windows) {
@import("renderer").copy_to_windows_clipboard(text) catch |e|
self.logger.print_err("clipboard", "failed to set clipboard: {any}", .{e});
@ -2616,10 +2609,8 @@ pub const Editor = struct {
}
}
pub fn set_clipboard_internal(self: *Self, text: []const u8) void {
if (self.clipboard) |old|
self.allocator.free(old);
self.clipboard = text;
pub fn set_clipboard_internal(_: *Self, text: []const u8) void {
tui.set_clipboard(text);
}
pub fn copy_selection(root: Buffer.Root, sel: Selection, text_allocator: Allocator, metrics: Buffer.Metrics) ![]u8 {
@ -2952,7 +2943,7 @@ pub const Editor = struct {
pub fn paste(self: *Self, ctx: Context) Result {
var text: []const u8 = undefined;
if (!(ctx.args.buf.len > 0 and try ctx.args.match(.{tp.extract(&text)}))) {
if (self.clipboard) |text_| text = text_ else return;
if (tui.get_clipboard()) |text_| text = text_ else return;
}
self.logger.print("paste: {d} bytes", .{text.len});
const b = try self.buf_for_update();
@ -2987,7 +2978,7 @@ pub const Editor = struct {
pub fn paste_internal_vim(self: *Self, ctx: Context) Result {
var text: []const u8 = undefined;
if (!(ctx.args.buf.len > 0 and try ctx.args.match(.{tp.extract(&text)}))) {
if (self.clipboard) |text_| text = text_ else return;
if (tui.get_clipboard()) |text_| text = text_ else return;
}
self.logger.print("paste: {d} bytes", .{text.len});

View file

@ -267,7 +267,7 @@ const cmds_ = struct {
var text: []const u8 = undefined;
if (!(ctx.args.buf.len > 0 and try ctx.args.match(.{tp.extract(&text)}))) {
if (ed.clipboard) |text_| text = text_ else return;
if (tui.get_clipboard()) |text_| text = text_ else return;
}
ed.logger.print("paste: {d} bytes", .{text.len});

View file

@ -64,6 +64,7 @@ fontfaces_: std.ArrayListUnmanaged([]const u8) = .{},
enable_mouse_idle_timer: bool = false,
query_cache_: *syntax.QueryCache,
frames_rendered_: usize = 0,
clipboard: ?[]const u8 = null,
const keepalive = std.time.us_per_day * 365; // one year
const idle_frames = 0;
@ -252,6 +253,7 @@ fn deinit(self: *Self) void {
self.logger.deinit();
self.query_cache_.deinit();
root.free_config(self.allocator, self.config_bufs);
if (self.clipboard) |text| self.allocator.free(text);
self.allocator.destroy(self);
}
@ -1645,3 +1647,15 @@ fn widget_type_config_variable(widget_type: WidgetType) *ConfigWidgetStyle {
.home => &config_.home_style,
};
}
pub fn get_clipboard() ?[]const u8 {
const self = current();
return self.clipboard;
}
pub fn set_clipboard(text: []const u8) void {
const self = current();
if (self.clipboard) |old|
self.allocator.free(old);
self.clipboard = text;
}