|
231 | 231 | -- @param new_file_contents string Contents of the new file
|
232 | 232 | -- @param tab_name string Name for the diff tab/view
|
233 | 233 | -- @return table Result with provider, tab_name, and success status
|
| 234 | +-- Detect filetype from a path or existing buffer (best-effort) |
| 235 | +local function _detect_filetype(path, buf) |
| 236 | + -- 1) Try Neovim's builtin matcher if available (>=0.10) |
| 237 | + if vim.filetype and type(vim.filetype.match) == "function" then |
| 238 | + local ok, ft = pcall(vim.filetype.match, { filename = path }) |
| 239 | + if ok and ft and ft ~= "" then |
| 240 | + return ft |
| 241 | + end |
| 242 | + end |
| 243 | + |
| 244 | + -- 2) Try reading from existing buffer |
| 245 | + if buf and vim.api.nvim_buf_is_valid(buf) then |
| 246 | + local ft = vim.api.nvim_buf_get_option(buf, "filetype") |
| 247 | + if ft and ft ~= "" then |
| 248 | + return ft |
| 249 | + end |
| 250 | + end |
| 251 | + |
| 252 | + -- 3) Fallback to simple extension mapping |
| 253 | + local ext = path:match("%.([%w_%-]+)$") or "" |
| 254 | + local simple_map = { |
| 255 | + lua = "lua", |
| 256 | + ts = "typescript", |
| 257 | + js = "javascript", |
| 258 | + jsx = "javascriptreact", |
| 259 | + tsx = "typescriptreact", |
| 260 | + py = "python", |
| 261 | + go = "go", |
| 262 | + rs = "rust", |
| 263 | + c = "c", |
| 264 | + h = "c", |
| 265 | + cpp = "cpp", |
| 266 | + hpp = "cpp", |
| 267 | + md = "markdown", |
| 268 | + sh = "sh", |
| 269 | + zsh = "zsh", |
| 270 | + bash = "bash", |
| 271 | + json = "json", |
| 272 | + yaml = "yaml", |
| 273 | + yml = "yaml", |
| 274 | + toml = "toml", |
| 275 | + } |
| 276 | + return simple_map[ext] |
| 277 | +end |
| 278 | + |
234 | 279 | function M._open_native_diff(old_file_path, new_file_path, new_file_contents, tab_name)
|
235 | 280 | local new_filename = vim.fn.fnamemodify(new_file_path, ":t") .. ".new"
|
236 | 281 | local tmp_file, err = M._create_temp_file(new_file_contents, new_filename)
|
@@ -259,9 +304,16 @@ function M._open_native_diff(old_file_path, new_file_path, new_file_contents, ta
|
259 | 304 | vim.cmd("edit " .. vim.fn.fnameescape(tmp_file))
|
260 | 305 | vim.api.nvim_buf_set_name(0, new_file_path .. " (New)")
|
261 | 306 |
|
| 307 | + -- Propagate filetype to the proposed buffer for proper syntax highlighting (#20) |
| 308 | + local proposed_buf = vim.api.nvim_get_current_buf() |
| 309 | + local old_filetype = _detect_filetype(old_file_path) |
| 310 | + if old_filetype and old_filetype ~= "" then |
| 311 | + vim.api.nvim_set_option_value("filetype", old_filetype, { buf = proposed_buf }) |
| 312 | + end |
| 313 | + |
262 | 314 | vim.cmd("wincmd =")
|
263 | 315 |
|
264 |
| - local new_buf = vim.api.nvim_get_current_buf() |
| 316 | + local new_buf = proposed_buf |
265 | 317 | vim.api.nvim_set_option_value("buftype", "nofile", { buf = new_buf })
|
266 | 318 | vim.api.nvim_set_option_value("bufhidden", "wipe", { buf = new_buf })
|
267 | 319 | vim.api.nvim_set_option_value("swapfile", false, { buf = new_buf })
|
@@ -665,6 +717,12 @@ function M._create_diff_view_from_window(target_window, old_file_path, new_buffe
|
665 | 717 | vim.cmd("vsplit")
|
666 | 718 | local new_win = vim.api.nvim_get_current_win()
|
667 | 719 | vim.api.nvim_win_set_buf(new_win, new_buffer)
|
| 720 | + |
| 721 | + -- Ensure new buffer inherits filetype from original for syntax highlighting (#20) |
| 722 | + local original_ft = _detect_filetype(old_file_path, original_buffer) |
| 723 | + if original_ft and original_ft ~= "" then |
| 724 | + vim.api.nvim_set_option_value("filetype", original_ft, { buf = new_buffer }) |
| 725 | + end |
668 | 726 | vim.cmd("diffthis")
|
669 | 727 | logger.debug("diff", "Created split window", new_win, "with new buffer", new_buffer)
|
670 | 728 |
|
|
0 commit comments