Merge branch 'master' into zig-0.15.0
This commit is contained in:
		
						commit
						abcdea15b5
					
				
					 5 changed files with 165 additions and 43 deletions
				
			
		| 
						 | 
					@ -26,6 +26,7 @@ limit_auto_save_file_types: ?[]const []const u8 = null, // null means *all*
 | 
				
			||||||
 | 
					
 | 
				
			||||||
indent_size: usize = 4,
 | 
					indent_size: usize = 4,
 | 
				
			||||||
tab_width: usize = 8,
 | 
					tab_width: usize = 8,
 | 
				
			||||||
 | 
					indent_mode: IndentMode = .auto,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
top_bar: []const u8 = "tabs",
 | 
					top_bar: []const u8 = "tabs",
 | 
				
			||||||
bottom_bar: []const u8 = "mode file log selection diagnostics keybind branch linenumber clock spacer",
 | 
					bottom_bar: []const u8 = "mode file log selection diagnostics keybind branch linenumber clock spacer",
 | 
				
			||||||
| 
						 | 
					@ -48,3 +49,9 @@ pub const LineNumberMode = enum {
 | 
				
			||||||
    relative,
 | 
					    relative,
 | 
				
			||||||
    absolute,
 | 
					    absolute,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub const IndentMode = enum {
 | 
				
			||||||
 | 
					    auto,
 | 
				
			||||||
 | 
					    spaces,
 | 
				
			||||||
 | 
					    tabs,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -249,6 +249,19 @@
 | 
				
			||||||
        "inherit": "project",
 | 
					        "inherit": "project",
 | 
				
			||||||
        "on_match_failure": "ignore",
 | 
					        "on_match_failure": "ignore",
 | 
				
			||||||
        "press": [
 | 
					        "press": [
 | 
				
			||||||
 | 
					            ["ctrl+e", "find_file"],
 | 
				
			||||||
 | 
					            ["f", "find_file"],
 | 
				
			||||||
 | 
					            ["e", "find_file"],
 | 
				
			||||||
 | 
					            ["ctrl+shift+n", "create_new_file"],
 | 
				
			||||||
 | 
					            ["n", "create_new_file"],
 | 
				
			||||||
 | 
					            ["ctrl+o", "open_file"],
 | 
				
			||||||
 | 
					            ["o", "open_file"],
 | 
				
			||||||
 | 
					            ["ctrl+r", "open_recent_project"],
 | 
				
			||||||
 | 
					            ["r", "open_recent_project"],
 | 
				
			||||||
 | 
					            ["ctrl+shift+p", "open_command_palette"],
 | 
				
			||||||
 | 
					            ["p", "open_command_palette"],
 | 
				
			||||||
 | 
					            ["t", "change_theme"],
 | 
				
			||||||
 | 
					            ["a", "add_task"],
 | 
				
			||||||
            ["c", "open_config"],
 | 
					            ["c", "open_config"],
 | 
				
			||||||
            ["g", "open_gui_config"],
 | 
					            ["g", "open_gui_config"],
 | 
				
			||||||
            ["k", "open_keybind_config"],
 | 
					            ["k", "open_keybind_config"],
 | 
				
			||||||
| 
						 | 
					@ -256,6 +269,9 @@
 | 
				
			||||||
            ["ctrl+f ctrl+f ctrl+f ctrl+f ctrl+f", "home_sheeran"],
 | 
					            ["ctrl+f ctrl+f ctrl+f ctrl+f ctrl+f", "home_sheeran"],
 | 
				
			||||||
            ["ctrl+shift+r", "restart"],
 | 
					            ["ctrl+shift+r", "restart"],
 | 
				
			||||||
            ["f6", "open_config"],
 | 
					            ["f6", "open_config"],
 | 
				
			||||||
 | 
					            ["v", "open_version_info"],
 | 
				
			||||||
 | 
					            ["ctrl+q", "quit"],
 | 
				
			||||||
 | 
					            ["q", "quit"],
 | 
				
			||||||
            ["up", "home_menu_up"],
 | 
					            ["up", "home_menu_up"],
 | 
				
			||||||
            ["down", "home_menu_down"],
 | 
					            ["down", "home_menu_down"],
 | 
				
			||||||
            ["enter", "home_menu_activate"]
 | 
					            ["enter", "home_menu_activate"]
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -23,6 +23,7 @@ const editor_gutter = @import("editor_gutter.zig");
 | 
				
			||||||
const Widget = @import("Widget.zig");
 | 
					const Widget = @import("Widget.zig");
 | 
				
			||||||
const WidgetList = @import("WidgetList.zig");
 | 
					const WidgetList = @import("WidgetList.zig");
 | 
				
			||||||
const tui = @import("tui.zig");
 | 
					const tui = @import("tui.zig");
 | 
				
			||||||
 | 
					const IndentMode = @import("config").IndentMode;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub const Cursor = Buffer.Cursor;
 | 
					pub const Cursor = Buffer.Cursor;
 | 
				
			||||||
pub const View = Buffer.View;
 | 
					pub const View = Buffer.View;
 | 
				
			||||||
| 
						 | 
					@ -318,6 +319,7 @@ pub const Editor = struct {
 | 
				
			||||||
    render_whitespace: WhitespaceMode,
 | 
					    render_whitespace: WhitespaceMode,
 | 
				
			||||||
    indent_size: usize,
 | 
					    indent_size: usize,
 | 
				
			||||||
    tab_width: usize,
 | 
					    tab_width: usize,
 | 
				
			||||||
 | 
					    indent_mode: IndentMode,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    last: struct {
 | 
					    last: struct {
 | 
				
			||||||
        root: ?Buffer.Root = null,
 | 
					        root: ?Buffer.Root = null,
 | 
				
			||||||
| 
						 | 
					@ -370,12 +372,15 @@ pub const Editor = struct {
 | 
				
			||||||
    const Result = command.Result;
 | 
					    const Result = command.Result;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pub fn write_state(self: *const Self, writer: Buffer.MetaWriter) !void {
 | 
					    pub fn write_state(self: *const Self, writer: Buffer.MetaWriter) !void {
 | 
				
			||||||
        try cbor.writeArrayHeader(writer, 8);
 | 
					        try cbor.writeArrayHeader(writer, 11);
 | 
				
			||||||
        try cbor.writeValue(writer, self.file_path orelse "");
 | 
					        try cbor.writeValue(writer, self.file_path orelse "");
 | 
				
			||||||
        try cbor.writeValue(writer, self.clipboard orelse "");
 | 
					        try cbor.writeValue(writer, self.clipboard orelse "");
 | 
				
			||||||
        try cbor.writeValue(writer, self.last_find_query 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_format_on_save);
 | 
				
			||||||
        try cbor.writeValue(writer, self.enable_auto_save);
 | 
					        try cbor.writeValue(writer, self.enable_auto_save);
 | 
				
			||||||
 | 
					        try cbor.writeValue(writer, self.indent_size);
 | 
				
			||||||
 | 
					        try cbor.writeValue(writer, self.tab_width);
 | 
				
			||||||
 | 
					        try cbor.writeValue(writer, self.indent_mode);
 | 
				
			||||||
        if (self.find_history) |history| {
 | 
					        if (self.find_history) |history| {
 | 
				
			||||||
            try cbor.writeArrayHeader(writer, history.items.len);
 | 
					            try cbor.writeArrayHeader(writer, history.items.len);
 | 
				
			||||||
            for (history.items) |item|
 | 
					            for (history.items) |item|
 | 
				
			||||||
| 
						 | 
					@ -411,6 +416,9 @@ pub const Editor = struct {
 | 
				
			||||||
            tp.extract(&last_find_query),
 | 
					            tp.extract(&last_find_query),
 | 
				
			||||||
            tp.extract(&self.enable_format_on_save),
 | 
					            tp.extract(&self.enable_format_on_save),
 | 
				
			||||||
            tp.extract(&self.enable_auto_save),
 | 
					            tp.extract(&self.enable_auto_save),
 | 
				
			||||||
 | 
					            tp.extract(&self.indent_size),
 | 
				
			||||||
 | 
					            tp.extract(&self.tab_width),
 | 
				
			||||||
 | 
					            tp.extract(&self.indent_mode),
 | 
				
			||||||
            tp.extract_cbor(&find_history),
 | 
					            tp.extract_cbor(&find_history),
 | 
				
			||||||
            tp.extract_cbor(&view_cbor),
 | 
					            tp.extract_cbor(&view_cbor),
 | 
				
			||||||
            tp.extract_cbor(&cursels_cbor),
 | 
					            tp.extract_cbor(&cursels_cbor),
 | 
				
			||||||
| 
						 | 
					@ -452,13 +460,15 @@ pub const Editor = struct {
 | 
				
			||||||
    fn init(self: *Self, allocator: Allocator, n: Plane, buffer_manager: *Buffer.Manager) void {
 | 
					    fn init(self: *Self, allocator: Allocator, n: Plane, buffer_manager: *Buffer.Manager) void {
 | 
				
			||||||
        const logger = log.logger("editor");
 | 
					        const logger = log.logger("editor");
 | 
				
			||||||
        const frame_rate = tp.env.get().num("frame-rate");
 | 
					        const frame_rate = tp.env.get().num("frame-rate");
 | 
				
			||||||
        const indent_size = tui.config().indent_size;
 | 
					 | 
				
			||||||
        const tab_width = tui.config().tab_width;
 | 
					        const tab_width = tui.config().tab_width;
 | 
				
			||||||
 | 
					        const indent_mode = tui.config().indent_mode;
 | 
				
			||||||
 | 
					        const indent_size = if (indent_mode == .tabs) tab_width else tui.config().indent_size;
 | 
				
			||||||
        self.* = Self{
 | 
					        self.* = Self{
 | 
				
			||||||
            .allocator = allocator,
 | 
					            .allocator = allocator,
 | 
				
			||||||
            .plane = n,
 | 
					            .plane = n,
 | 
				
			||||||
            .indent_size = indent_size,
 | 
					            .indent_size = indent_size,
 | 
				
			||||||
            .tab_width = tab_width,
 | 
					            .tab_width = tab_width,
 | 
				
			||||||
 | 
					            .indent_mode = indent_mode,
 | 
				
			||||||
            .metrics = self.plane.metrics(tab_width),
 | 
					            .metrics = self.plane.metrics(tab_width),
 | 
				
			||||||
            .logger = logger,
 | 
					            .logger = logger,
 | 
				
			||||||
            .file_path = null,
 | 
					            .file_path = null,
 | 
				
			||||||
| 
						 | 
					@ -574,6 +584,7 @@ pub const Editor = struct {
 | 
				
			||||||
        if (self.buffer) |_| try self.close();
 | 
					        if (self.buffer) |_| try self.close();
 | 
				
			||||||
        self.buffer = new_buf;
 | 
					        self.buffer = new_buf;
 | 
				
			||||||
        const file_type = file_type_ orelse new_buf.file_type_name;
 | 
					        const file_type = file_type_ orelse new_buf.file_type_name;
 | 
				
			||||||
 | 
					        const buffer_meta = if (self.buffer) |buffer| buffer.get_meta() else null;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (new_buf.root.lines() > root_mod.max_syntax_lines) {
 | 
					        if (new_buf.root.lines() > root_mod.max_syntax_lines) {
 | 
				
			||||||
            self.logger.print("large file threshold {d} lines < file size {d} lines", .{
 | 
					            self.logger.print("large file threshold {d} lines < file size {d} lines", .{
 | 
				
			||||||
| 
						 | 
					@ -583,8 +594,7 @@ pub const Editor = struct {
 | 
				
			||||||
            self.logger.print("syntax highlighting disabled", .{});
 | 
					            self.logger.print("syntax highlighting disabled", .{});
 | 
				
			||||||
            self.syntax_no_render = true;
 | 
					            self.syntax_no_render = true;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        self.syntax = syntax: {
 | 
					
 | 
				
			||||||
            const lang_override = file_type orelse tp.env.get().str("language");
 | 
					 | 
				
			||||||
        var content = std.ArrayListUnmanaged(u8).empty;
 | 
					        var content = std.ArrayListUnmanaged(u8).empty;
 | 
				
			||||||
        defer content.deinit(std.heap.c_allocator);
 | 
					        defer content.deinit(std.heap.c_allocator);
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
| 
						 | 
					@ -592,6 +602,11 @@ pub const Editor = struct {
 | 
				
			||||||
            defer frame_.deinit();
 | 
					            defer frame_.deinit();
 | 
				
			||||||
            try new_buf.root.store(content.writer(std.heap.c_allocator), new_buf.file_eol_mode);
 | 
					            try new_buf.root.store(content.writer(std.heap.c_allocator), new_buf.file_eol_mode);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					        if (self.indent_mode == .auto)
 | 
				
			||||||
 | 
					            self.detect_indent_mode(content.items);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.syntax = syntax: {
 | 
				
			||||||
 | 
					            const lang_override = file_type orelse tp.env.get().str("language");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            self.file_type = blk: {
 | 
					            self.file_type = blk: {
 | 
				
			||||||
                const frame_ = tracy.initZone(@src(), .{ .name = "guess" });
 | 
					                const frame_ = tracy.initZone(@src(), .{ .name = "guess" });
 | 
				
			||||||
| 
						 | 
					@ -613,7 +628,7 @@ pub const Editor = struct {
 | 
				
			||||||
                    null;
 | 
					                    null;
 | 
				
			||||||
            };
 | 
					            };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (self.file_type) |ft| {
 | 
					            if (buffer_meta == null) if (self.file_type) |ft| {
 | 
				
			||||||
                const frame_ = tracy.initZone(@src(), .{ .name = "did_open" });
 | 
					                const frame_ = tracy.initZone(@src(), .{ .name = "did_open" });
 | 
				
			||||||
                defer frame_.deinit();
 | 
					                defer frame_.deinit();
 | 
				
			||||||
                project_manager.did_open(
 | 
					                project_manager.did_open(
 | 
				
			||||||
| 
						 | 
					@ -624,7 +639,7 @@ pub const Editor = struct {
 | 
				
			||||||
                    new_buf.is_ephemeral(),
 | 
					                    new_buf.is_ephemeral(),
 | 
				
			||||||
                ) catch |e|
 | 
					                ) catch |e|
 | 
				
			||||||
                    self.logger.print("project_manager.did_open failed: {any}", .{e});
 | 
					                    self.logger.print("project_manager.did_open failed: {any}", .{e});
 | 
				
			||||||
            }
 | 
					            };
 | 
				
			||||||
            break :syntax syn;
 | 
					            break :syntax syn;
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
        self.syntax_no_render = tp.env.get().is("no-syntax");
 | 
					        self.syntax_no_render = tp.env.get().is("no-syntax");
 | 
				
			||||||
| 
						 | 
					@ -639,11 +654,11 @@ pub const Editor = struct {
 | 
				
			||||||
            buffer.file_type_color = ftc;
 | 
					            buffer.file_type_color = ftc;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (self.buffer) |buffer| if (buffer.get_meta()) |meta| {
 | 
					        if (buffer_meta) |meta| {
 | 
				
			||||||
            const frame_ = tracy.initZone(@src(), .{ .name = "extract_state" });
 | 
					            const frame_ = tracy.initZone(@src(), .{ .name = "extract_state" });
 | 
				
			||||||
            defer frame_.deinit();
 | 
					            defer frame_.deinit();
 | 
				
			||||||
            try self.extract_state(meta, .none);
 | 
					            try self.extract_state(meta, .none);
 | 
				
			||||||
        };
 | 
					        }
 | 
				
			||||||
        try self.send_editor_open(file_path, new_buf.file_exists, ftn, fti, ftc);
 | 
					        try self.send_editor_open(file_path, new_buf.file_exists, ftn, fti, ftc);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -663,6 +678,21 @@ pub const Editor = struct {
 | 
				
			||||||
        self.enable_auto_save = true;
 | 
					        self.enable_auto_save = true;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fn detect_indent_mode(self: *Self, content: []const u8) void {
 | 
				
			||||||
 | 
					        var it = std.mem.splitScalar(u8, content, '\n');
 | 
				
			||||||
 | 
					        while (it.next()) |line| {
 | 
				
			||||||
 | 
					            if (line.len == 0) continue;
 | 
				
			||||||
 | 
					            if (line[0] == '\t') {
 | 
				
			||||||
 | 
					                self.indent_size = self.tab_width;
 | 
				
			||||||
 | 
					                self.indent_mode = .tabs;
 | 
				
			||||||
 | 
					                return;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        self.indent_size = tui.config().indent_size;
 | 
				
			||||||
 | 
					        self.indent_mode = .spaces;
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn close(self: *Self) !void {
 | 
					    fn close(self: *Self) !void {
 | 
				
			||||||
        var meta = std.ArrayListUnmanaged(u8).empty;
 | 
					        var meta = std.ArrayListUnmanaged(u8).empty;
 | 
				
			||||||
        defer meta.deinit(self.allocator);
 | 
					        defer meta.deinit(self.allocator);
 | 
				
			||||||
| 
						 | 
					@ -3651,9 +3681,16 @@ pub const Editor = struct {
 | 
				
			||||||
        const space = "                                ";
 | 
					        const space = "                                ";
 | 
				
			||||||
        var cursel: CurSel = .{};
 | 
					        var cursel: CurSel = .{};
 | 
				
			||||||
        cursel.cursor = cursor;
 | 
					        cursel.cursor = cursor;
 | 
				
			||||||
        const cols = self.indent_size - find_first_non_ws(root, cursel.cursor.row, self.metrics) % self.indent_size;
 | 
					 | 
				
			||||||
        try move_cursor_begin(root, &cursel.cursor, self.metrics);
 | 
					        try move_cursor_begin(root, &cursel.cursor, self.metrics);
 | 
				
			||||||
 | 
					        switch (self.indent_mode) {
 | 
				
			||||||
 | 
					            .spaces, .auto => {
 | 
				
			||||||
 | 
					                const cols = self.indent_size - find_first_non_ws(root, cursel.cursor.row, self.metrics) % self.indent_size;
 | 
				
			||||||
                return self.insert(root, &cursel, space[0..cols], allocator) catch return error.Stop;
 | 
					                return self.insert(root, &cursel, space[0..cols], allocator) catch return error.Stop;
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            .tabs => {
 | 
				
			||||||
 | 
					                return self.insert(root, &cursel, "\t", allocator) catch return error.Stop;
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn indent_cursel(self: *Self, root_: Buffer.Root, cursel: *CurSel, allocator: Allocator) error{Stop}!Buffer.Root {
 | 
					    fn indent_cursel(self: *Self, root_: Buffer.Root, cursel: *CurSel, allocator: Allocator) error{Stop}!Buffer.Root {
 | 
				
			||||||
| 
						 | 
					@ -3688,16 +3725,16 @@ pub const Editor = struct {
 | 
				
			||||||
        const off = first % self.indent_size;
 | 
					        const off = first % self.indent_size;
 | 
				
			||||||
        const cols = if (off == 0) self.indent_size else off;
 | 
					        const cols = if (off == 0) self.indent_size else off;
 | 
				
			||||||
        const sel = cursel.enable_selection(root, self.metrics) catch return error.Stop;
 | 
					        const sel = cursel.enable_selection(root, self.metrics) catch return error.Stop;
 | 
				
			||||||
        sel.begin.move_begin();
 | 
					        try sel.begin.move_to(root, sel.begin.row, first, self.metrics);
 | 
				
			||||||
        try sel.end.move_to(root, sel.end.row, cols, self.metrics);
 | 
					        try sel.end.move_to(root, sel.end.row, first - cols, self.metrics);
 | 
				
			||||||
        var saved = false;
 | 
					        var saved = false;
 | 
				
			||||||
        if (cursor_protect) |cp| if (cp.row == cursor.row and cp.col < cols) {
 | 
					        if (cursor_protect) |cp| if (cp.row == cursor.row and cp.col < first and cp.col >= first - cols) {
 | 
				
			||||||
            cp.col = cols + 1;
 | 
					            cp.col = first + 1;
 | 
				
			||||||
            saved = true;
 | 
					            saved = true;
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
        newroot = try self.delete_selection(root, &cursel, allocator);
 | 
					        newroot = try self.delete_selection(root, &cursel, allocator);
 | 
				
			||||||
        if (cursor_protect) |cp| if (saved) {
 | 
					        if (cursor_protect) |cp| if (saved) {
 | 
				
			||||||
            try cp.move_to(root, cp.row, 0, self.metrics);
 | 
					            try cp.move_to(root, cp.row, first - cols, self.metrics);
 | 
				
			||||||
            cp.clamp_to_buffer(newroot, self.metrics);
 | 
					            cp.clamp_to_buffer(newroot, self.metrics);
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
        return newroot;
 | 
					        return newroot;
 | 
				
			||||||
| 
						 | 
					@ -4368,16 +4405,39 @@ pub const Editor = struct {
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    pub const insert_line_meta: Meta = .{ .description = "Insert line" };
 | 
					    pub const insert_line_meta: Meta = .{ .description = "Insert line" };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fn generate_leading_ws(self: *Self, writer: anytype, leading_ws: usize) !void {
 | 
				
			||||||
 | 
					        return switch (self.indent_mode) {
 | 
				
			||||||
 | 
					            .spaces, .auto => generate_leading_spaces(writer, leading_ws),
 | 
				
			||||||
 | 
					            .tabs => generate_leading_tabs(writer, leading_ws, self.tab_width),
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fn generate_leading_spaces(writer: anytype, leading_ws: usize) !void {
 | 
				
			||||||
 | 
					        var width = leading_ws;
 | 
				
			||||||
 | 
					        while (width > 0) : (width -= 1)
 | 
				
			||||||
 | 
					            try writer.writeByte(' ');
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fn generate_leading_tabs(writer: anytype, leading_ws: usize, tab_width: usize) !void {
 | 
				
			||||||
 | 
					        var width = leading_ws;
 | 
				
			||||||
 | 
					        while (width > 0) if (width >= tab_width) {
 | 
				
			||||||
 | 
					            width -= tab_width;
 | 
				
			||||||
 | 
					            try writer.writeByte('\t');
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            width -= 1;
 | 
				
			||||||
 | 
					            try writer.writeByte(' ');
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn cursel_smart_insert_line(self: *Self, root: Buffer.Root, cursel: *CurSel, b_allocator: std.mem.Allocator) !Buffer.Root {
 | 
					    fn cursel_smart_insert_line(self: *Self, root: Buffer.Root, cursel: *CurSel, b_allocator: std.mem.Allocator) !Buffer.Root {
 | 
				
			||||||
        var leading_ws = @min(find_first_non_ws(root, cursel.cursor.row, self.metrics), cursel.cursor.col);
 | 
					        const leading_ws = @min(find_first_non_ws(root, cursel.cursor.row, self.metrics), cursel.cursor.col);
 | 
				
			||||||
        var sfa = std.heap.stackFallback(512, self.allocator);
 | 
					        var sfa = std.heap.stackFallback(512, self.allocator);
 | 
				
			||||||
        const allocator = sfa.get();
 | 
					        const allocator = sfa.get();
 | 
				
			||||||
        var stream = std.ArrayListUnmanaged(u8).empty;
 | 
					        var stream = std.ArrayListUnmanaged(u8).empty;
 | 
				
			||||||
        defer stream.deinit(allocator);
 | 
					        defer stream.deinit(allocator);
 | 
				
			||||||
        var writer = stream.writer(allocator);
 | 
					        var writer = stream.writer(allocator);
 | 
				
			||||||
        _ = try writer.write("\n");
 | 
					        _ = try writer.write("\n");
 | 
				
			||||||
        while (leading_ws > 0) : (leading_ws -= 1)
 | 
					        try self.generate_leading_ws(&writer, leading_ws);
 | 
				
			||||||
            _ = try writer.write(" ");
 | 
					 | 
				
			||||||
        return self.insert(root, cursel, stream.items, b_allocator);
 | 
					        return self.insert(root, cursel, stream.items, b_allocator);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -4431,7 +4491,7 @@ pub const Editor = struct {
 | 
				
			||||||
        const b = try self.buf_for_update();
 | 
					        const b = try self.buf_for_update();
 | 
				
			||||||
        var root = b.root;
 | 
					        var root = b.root;
 | 
				
			||||||
        for (self.cursels.items) |*cursel_| if (cursel_.*) |*cursel| {
 | 
					        for (self.cursels.items) |*cursel_| if (cursel_.*) |*cursel| {
 | 
				
			||||||
            var leading_ws = @min(find_first_non_ws(root, cursel.cursor.row, self.metrics), cursel.cursor.col);
 | 
					            const leading_ws = @min(find_first_non_ws(root, cursel.cursor.row, self.metrics), cursel.cursor.col);
 | 
				
			||||||
            try move_cursor_begin(root, &cursel.cursor, self.metrics);
 | 
					            try move_cursor_begin(root, &cursel.cursor, self.metrics);
 | 
				
			||||||
            root = try self.insert(root, cursel, "\n", b.allocator);
 | 
					            root = try self.insert(root, cursel, "\n", b.allocator);
 | 
				
			||||||
            try move_cursor_left(root, &cursel.cursor, self.metrics);
 | 
					            try move_cursor_left(root, &cursel.cursor, self.metrics);
 | 
				
			||||||
| 
						 | 
					@ -4440,8 +4500,7 @@ pub const Editor = struct {
 | 
				
			||||||
            var stream = std.ArrayListUnmanaged(u8).empty;
 | 
					            var stream = std.ArrayListUnmanaged(u8).empty;
 | 
				
			||||||
            defer stream.deinit(allocator);
 | 
					            defer stream.deinit(allocator);
 | 
				
			||||||
            var writer = stream.writer(self.allocator);
 | 
					            var writer = stream.writer(self.allocator);
 | 
				
			||||||
            while (leading_ws > 0) : (leading_ws -= 1)
 | 
					            try self.generate_leading_ws(&writer, leading_ws);
 | 
				
			||||||
                _ = try writer.write(" ");
 | 
					 | 
				
			||||||
            if (stream.items.len > 0)
 | 
					            if (stream.items.len > 0)
 | 
				
			||||||
                root = try self.insert(root, cursel, stream.items, b.allocator);
 | 
					                root = try self.insert(root, cursel, stream.items, b.allocator);
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
| 
						 | 
					@ -4466,7 +4525,7 @@ pub const Editor = struct {
 | 
				
			||||||
        const b = try self.buf_for_update();
 | 
					        const b = try self.buf_for_update();
 | 
				
			||||||
        var root = b.root;
 | 
					        var root = b.root;
 | 
				
			||||||
        for (self.cursels.items) |*cursel_| if (cursel_.*) |*cursel| {
 | 
					        for (self.cursels.items) |*cursel_| if (cursel_.*) |*cursel| {
 | 
				
			||||||
            var leading_ws = @min(find_first_non_ws(root, cursel.cursor.row, self.metrics), cursel.cursor.col);
 | 
					            const leading_ws = @min(find_first_non_ws(root, cursel.cursor.row, self.metrics), cursel.cursor.col);
 | 
				
			||||||
            try move_cursor_end(root, &cursel.cursor, self.metrics);
 | 
					            try move_cursor_end(root, &cursel.cursor, self.metrics);
 | 
				
			||||||
            var sfa = std.heap.stackFallback(512, self.allocator);
 | 
					            var sfa = std.heap.stackFallback(512, self.allocator);
 | 
				
			||||||
            const allocator = sfa.get();
 | 
					            const allocator = sfa.get();
 | 
				
			||||||
| 
						 | 
					@ -4474,8 +4533,7 @@ pub const Editor = struct {
 | 
				
			||||||
            defer stream.deinit(allocator);
 | 
					            defer stream.deinit(allocator);
 | 
				
			||||||
            var writer = stream.writer(allocator);
 | 
					            var writer = stream.writer(allocator);
 | 
				
			||||||
            _ = try writer.write("\n");
 | 
					            _ = try writer.write("\n");
 | 
				
			||||||
            while (leading_ws > 0) : (leading_ws -= 1)
 | 
					            try self.generate_leading_ws(&writer, leading_ws);
 | 
				
			||||||
                _ = try writer.write(" ");
 | 
					 | 
				
			||||||
            if (stream.items.len > 0)
 | 
					            if (stream.items.len > 0)
 | 
				
			||||||
                root = try self.insert(root, cursel, stream.items, b.allocator);
 | 
					                root = try self.insert(root, cursel, stream.items, b.allocator);
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
| 
						 | 
					@ -5906,9 +5964,14 @@ pub const Editor = struct {
 | 
				
			||||||
        self.syntax_no_render = tp.env.get().is("no-syntax");
 | 
					        self.syntax_no_render = tp.env.get().is("no-syntax");
 | 
				
			||||||
        self.syntax_report_timing = tp.env.get().is("syntax-report-timing");
 | 
					        self.syntax_report_timing = tp.env.get().is("syntax-report-timing");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        const ftn = if (self.file_type) |ft| ft.name else "text";
 | 
					        const ftn = if (self.file_type) |ft| ft.name else file_type_config.default.name;
 | 
				
			||||||
        const fti = if (self.file_type) |ft| ft.icon orelse "🖹" else "🖹";
 | 
					        const fti = if (self.file_type) |ft| ft.icon orelse file_type_config.default.icon else file_type_config.default.icon;
 | 
				
			||||||
        const ftc = if (self.file_type) |ft| ft.color orelse 0x000000 else 0x000000;
 | 
					        const ftc = if (self.file_type) |ft| ft.color orelse file_type_config.default.color else file_type_config.default.color;
 | 
				
			||||||
 | 
					        if (self.buffer) |buffer| {
 | 
				
			||||||
 | 
					            buffer.file_type_name = ftn;
 | 
				
			||||||
 | 
					            buffer.file_type_icon = fti;
 | 
				
			||||||
 | 
					            buffer.file_type_color = ftc;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
        const file_exists = if (self.buffer) |b| b.file_exists else false;
 | 
					        const file_exists = if (self.buffer) |b| b.file_exists else false;
 | 
				
			||||||
        try self.send_editor_open(self.file_path orelse "", file_exists, ftn, fti, ftc);
 | 
					        try self.send_editor_open(self.file_path orelse "", file_exists, ftn, fti, ftc);
 | 
				
			||||||
        self.logger.print("file type {s}", .{file_type});
 | 
					        self.logger.print("file type {s}", .{file_type});
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -44,6 +44,7 @@ pub fn create(
 | 
				
			||||||
        .on_click = on_click,
 | 
					        .on_click = on_click,
 | 
				
			||||||
        .on_layout = layout,
 | 
					        .on_layout = layout,
 | 
				
			||||||
        .on_render = render,
 | 
					        .on_render = render,
 | 
				
			||||||
 | 
					        .on_receive = receive,
 | 
				
			||||||
        .on_event = event_handler,
 | 
					        .on_event = event_handler,
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -60,18 +61,46 @@ pub fn ctx_deinit(self: *Self) void {
 | 
				
			||||||
    if (self.behind) |p| self.allocator.free(p);
 | 
					    if (self.behind) |p| self.allocator.free(p);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
fn on_click(_: *Self, _: *Button.State(Self)) void {
 | 
					fn on_click(self: *Self, _: *Button.State(Self)) void {
 | 
				
			||||||
    git.status(0) catch {};
 | 
					    self.refresh_git_status();
 | 
				
			||||||
    command.executeName("show_git_status", .{}) catch {};
 | 
					    command.executeName("show_git_status", .{}) catch {};
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fn refresh_git_status(_: *Self) void {
 | 
				
			||||||
 | 
					    git.status(0) catch {};
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub fn receive(self: *Self, _: *Button.State(Self), _: tp.pid_ref, m: tp.message) error{Exit}!bool {
 | 
				
			||||||
 | 
					    if (try m.match(.{ "E", tp.more }))
 | 
				
			||||||
 | 
					        return self.process_event(m);
 | 
				
			||||||
 | 
					    if (try m.match(.{ "PRJ", "open" }))
 | 
				
			||||||
 | 
					        self.refresh_git_status();
 | 
				
			||||||
 | 
					    return false;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fn process_event(self: *Self, m: tp.message) error{Exit}!bool {
 | 
				
			||||||
 | 
					    if (try m.match(.{ tp.any, "dirty", tp.more }) or
 | 
				
			||||||
 | 
					        try m.match(.{ tp.any, "save", tp.more }) or
 | 
				
			||||||
 | 
					        try m.match(.{ tp.any, "open", tp.more }) or
 | 
				
			||||||
 | 
					        try m.match(.{ tp.any, "close" }))
 | 
				
			||||||
 | 
					        self.refresh_git_status();
 | 
				
			||||||
 | 
					    return false;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
fn receive_git(self: *Self, _: tp.pid_ref, m: tp.message) MessageFilter.Error!bool {
 | 
					fn receive_git(self: *Self, _: tp.pid_ref, m: tp.message) MessageFilter.Error!bool {
 | 
				
			||||||
    return if (try match(m.buf, .{ "git", more }))
 | 
					    return if (try match(m.buf, .{ "git", more }))
 | 
				
			||||||
        self.process_git(m)
 | 
					        self.process_git(m)
 | 
				
			||||||
 | 
					    else if (try match(m.buf, .{"focus_in"}))
 | 
				
			||||||
 | 
					        self.process_focus_in()
 | 
				
			||||||
    else
 | 
					    else
 | 
				
			||||||
        false;
 | 
					        false;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fn process_focus_in(self: *Self) MessageFilter.Error!bool {
 | 
				
			||||||
 | 
					    self.refresh_git_status();
 | 
				
			||||||
 | 
					    return false;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
fn process_git(self: *Self, m: tp.message) MessageFilter.Error!bool {
 | 
					fn process_git(self: *Self, m: tp.message) MessageFilter.Error!bool {
 | 
				
			||||||
    var value: []const u8 = undefined;
 | 
					    var value: []const u8 = undefined;
 | 
				
			||||||
    if (try match(m.buf, .{ any, any, "workspace_path", null_ })) {
 | 
					    if (try match(m.buf, .{ any, any, "workspace_path", null_ })) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -200,24 +200,34 @@ fn render_terminal_title(self: *Self) void {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub fn receive(self: *Self, _: *Button.State(Self), _: tp.pid_ref, m: tp.message) error{Exit}!bool {
 | 
					pub fn receive(self: *Self, _: *Button.State(Self), _: tp.pid_ref, m: tp.message) error{Exit}!bool {
 | 
				
			||||||
 | 
					    if (try m.match(.{ "E", tp.more }))
 | 
				
			||||||
 | 
					        return self.process_event(m);
 | 
				
			||||||
 | 
					    if (try m.match(.{ "PRJ", "open" })) {
 | 
				
			||||||
 | 
					        if (!self.file)
 | 
				
			||||||
 | 
					            self.show_project();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return false;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fn process_event(self: *Self, m: tp.message) error{Exit}!bool {
 | 
				
			||||||
    var file_path: []const u8 = undefined;
 | 
					    var file_path: []const u8 = undefined;
 | 
				
			||||||
    var file_type: []const u8 = undefined;
 | 
					    var file_type: []const u8 = undefined;
 | 
				
			||||||
    var file_icon: []const u8 = undefined;
 | 
					    var file_icon: []const u8 = undefined;
 | 
				
			||||||
    var file_dirty: bool = undefined;
 | 
					    var file_dirty: bool = undefined;
 | 
				
			||||||
    var eol_mode: Buffer.EolModeTag = @intFromEnum(Buffer.EolMode.lf);
 | 
					    var eol_mode: Buffer.EolModeTag = @intFromEnum(Buffer.EolMode.lf);
 | 
				
			||||||
    if (try m.match(.{ "E", "pos", tp.extract(&self.lines), tp.extract(&self.line), tp.extract(&self.column) }))
 | 
					    if (try m.match(.{ tp.any, "pos", tp.extract(&self.lines), tp.extract(&self.line), tp.extract(&self.column) }))
 | 
				
			||||||
        return false;
 | 
					        return false;
 | 
				
			||||||
    if (try m.match(.{ "E", "dirty", tp.extract(&file_dirty) })) {
 | 
					    if (try m.match(.{ tp.any, "dirty", tp.extract(&file_dirty) })) {
 | 
				
			||||||
        self.file_dirty = file_dirty;
 | 
					        self.file_dirty = file_dirty;
 | 
				
			||||||
    } else if (try m.match(.{ "E", "eol_mode", tp.extract(&eol_mode), tp.extract(&self.utf8_sanitized) })) {
 | 
					    } else if (try m.match(.{ tp.any, "eol_mode", tp.extract(&eol_mode), tp.extract(&self.utf8_sanitized) })) {
 | 
				
			||||||
        self.eol_mode = @enumFromInt(eol_mode);
 | 
					        self.eol_mode = @enumFromInt(eol_mode);
 | 
				
			||||||
    } else if (try m.match(.{ "E", "save", tp.extract(&file_path) })) {
 | 
					    } else if (try m.match(.{ tp.any, "save", tp.extract(&file_path) })) {
 | 
				
			||||||
        @memcpy(self.name_buf[0..file_path.len], file_path);
 | 
					        @memcpy(self.name_buf[0..file_path.len], file_path);
 | 
				
			||||||
        self.name = self.name_buf[0..file_path.len];
 | 
					        self.name = self.name_buf[0..file_path.len];
 | 
				
			||||||
        self.file_exists = true;
 | 
					        self.file_exists = true;
 | 
				
			||||||
        self.file_dirty = false;
 | 
					        self.file_dirty = false;
 | 
				
			||||||
        self.name = project_manager.abbreviate_home(&self.name_buf, self.name);
 | 
					        self.name = project_manager.abbreviate_home(&self.name_buf, self.name);
 | 
				
			||||||
    } else if (try m.match(.{ "E", "open", tp.extract(&file_path), tp.extract(&self.file_exists), tp.extract(&file_type), tp.extract(&file_icon), tp.extract(&self.file_color) })) {
 | 
					    } else if (try m.match(.{ tp.any, "open", tp.extract(&file_path), tp.extract(&self.file_exists), tp.extract(&file_type), tp.extract(&file_icon), tp.extract(&self.file_color) })) {
 | 
				
			||||||
        self.eol_mode = .lf;
 | 
					        self.eol_mode = .lf;
 | 
				
			||||||
        @memcpy(self.name_buf[0..file_path.len], file_path);
 | 
					        @memcpy(self.name_buf[0..file_path.len], file_path);
 | 
				
			||||||
        self.name = self.name_buf[0..file_path.len];
 | 
					        self.name = self.name_buf[0..file_path.len];
 | 
				
			||||||
| 
						 | 
					@ -229,7 +239,7 @@ pub fn receive(self: *Self, _: *Button.State(Self), _: tp.pid_ref, m: tp.message
 | 
				
			||||||
        self.file_dirty = false;
 | 
					        self.file_dirty = false;
 | 
				
			||||||
        self.name = project_manager.abbreviate_home(&self.name_buf, self.name);
 | 
					        self.name = project_manager.abbreviate_home(&self.name_buf, self.name);
 | 
				
			||||||
        self.file = true;
 | 
					        self.file = true;
 | 
				
			||||||
    } else if (try m.match(.{ "E", "close" })) {
 | 
					    } else if (try m.match(.{ tp.any, "close" })) {
 | 
				
			||||||
        self.name = "";
 | 
					        self.name = "";
 | 
				
			||||||
        self.lines = 0;
 | 
					        self.lines = 0;
 | 
				
			||||||
        self.line = 0;
 | 
					        self.line = 0;
 | 
				
			||||||
| 
						 | 
					@ -238,9 +248,6 @@ pub fn receive(self: *Self, _: *Button.State(Self), _: tp.pid_ref, m: tp.message
 | 
				
			||||||
        self.file = false;
 | 
					        self.file = false;
 | 
				
			||||||
        self.eol_mode = .lf;
 | 
					        self.eol_mode = .lf;
 | 
				
			||||||
        self.show_project();
 | 
					        self.show_project();
 | 
				
			||||||
    } else if (try m.match(.{ "PRJ", "open" })) {
 | 
					 | 
				
			||||||
        if (!self.file)
 | 
					 | 
				
			||||||
            self.show_project();
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    return false;
 | 
					    return false;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue