Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ name: CI
env:
TRIPTYCH_DIR: .local/share/nvim/site/pack/simonmclean/start/triptych
LUA_LS_LOG_PATH: /home/runner/lua-language-server/logs
LATEST_NVIM_VERSION: "0.11.3"
LATEST_NVIM_VERSION: "0.12.1"

on:
workflow_dispatch:
Expand Down Expand Up @@ -42,7 +42,6 @@ jobs:
- name: install neovim plugins
run: |
git config --global advice.detachedHead false
git clone https://github.com/nvim-lua/plenary.nvim.git $HOME/.local/share/nvim/site/pack/plenary/start/plenary
git clone https://github.com/nvim-tree/nvim-web-devicons $HOME/.local/share/nvim/site/pack/nvim-tree/start/nvim-web-devicons
git clone --recurse-submodules https://github.com/$GITHUB_REPOSITORY $HOME/$TRIPTYCH_DIR
cd $HOME/$TRIPTYCH_DIR
Expand Down
2 changes: 0 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@ You only ever control or focus the middle window.
## ⚡️ Requirements

- Neovim >= 0.9.0
- [nvim-lua/plenary.nvim](https://github.com/nvim-lua/plenary.nvim)
- Optional, if you want fancy icons
- [nvim-tree/nvim-web-devicons](https://github.com/nvim-tree/nvim-web-devicons)
- A [Nerd Font](https://www.nerdfonts.com/)
Expand All @@ -54,7 +53,6 @@ Example using [Lazy](https://github.com/folke/lazy.nvim).
{
'simonmclean/triptych.nvim',
dependencies = {
'nvim-lua/plenary.nvim', -- required
'nvim-tree/nvim-web-devicons', -- optional for icons
'antosha417/nvim-lsp-file-operations' -- optional LSP integration
},
Expand Down
2 changes: 0 additions & 2 deletions doc/triptych.nvim.txt
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@ FEATURES *triptych.nvim-features*
REQUIREMENTS *triptych.nvim-requirements*

- Neovim >= 0.9.0
- nvim-lua/plenary.nvim <https://github.com/nvim-lua/plenary.nvim>
- Optional, if you want fancy icons
- nvim-tree/nvim-web-devicons <https://github.com/nvim-tree/nvim-web-devicons>
- A Nerd Font <https://www.nerdfonts.com/>
Expand All @@ -60,7 +59,6 @@ Example using Lazy <https://github.com/folke/lazy.nvim>.
{
'simonmclean/triptych.nvim',
dependencies = {
'nvim-lua/plenary.nvim', -- required
'nvim-tree/nvim-web-devicons', -- optional for icons
'antosha417/nvim-lsp-file-operations' -- optional LSP integration
},
Expand Down
73 changes: 47 additions & 26 deletions lua/triptych/actions.lua
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
local u = require 'triptych.utils'
local float = require 'triptych.float'
local view = require 'triptych.view'
local plenary_path = require 'plenary.path'
local float = require 'triptych.float'
local triptych_help = require 'triptych.help'
local autocmds = require 'triptych.autocmds'
local log = require 'triptych.logger'
Expand Down Expand Up @@ -45,7 +44,51 @@ local function rename_node_and_publish(from, to)
end
end

---Wraps plenary Path:copy with public events
---Recursively copy a file or directory to a destination path.
---Returns a flat list of all file paths that were created.
---@param src string
---@param dest string
---@return string[] created_files
local function copy_recursive(src, dest)
local created = {}
local src_type = vim.fn.getftype(src)

if src_type == 'dir' then
vim.fn.mkdir(dest, 'p')
local handle = vim.loop.fs_scandir(src)
if handle then
while true do
local name, _ = vim.loop.fs_scandir_next(handle)
if not name then
break
end
local sub_created = copy_recursive(src .. '/' .. name, dest .. '/' .. name)
for _, p in ipairs(sub_created) do
table.insert(created, p)
end
end
end
else
-- Read source file and write to destination
local f_in = io.open(src, 'rb')
if f_in then
local data = f_in:read '*a'
f_in:close()
local dest_dir = vim.fn.fnamemodify(dest, ':h')
vim.fn.mkdir(dest_dir, 'p')
local f_out = io.open(dest, 'wb')
if f_out then
f_out:write(data)
f_out:close()
table.insert(created, dest)
end
end
end

return created
end

---Copy a node (file or directory) to destination, publishing events for created files.
---Note: It only publishes events for files, not folders. This is probably fine for LSP purposes
---@param target PathDetails
---@param destination string
Expand All @@ -56,29 +99,7 @@ local function duplicate_node_and_publish(target, destination)
autocmds.publish_will_create_node(destination)
end

local p = plenary_path:new(target.path)
-- Note: Plenary has a bug whereby a copying a directory into itself creates hundreds of nested copies
-- https://github.com/nvim-lua/plenary.nvim/pull/358
local results = p:copy {
destination = destination,
recursive = true,
override = false,
interactive = true,
}

local files_created = {}

local function handle_results(results)
for key, value in pairs(results) do
if type(value) == 'table' then
handle_results(value)
elseif value then
table.insert(files_created, key.filename)
end
end
end

handle_results(results)
local files_created = copy_recursive(target.path, destination)

-- Sorting to avoid flakey test
table.sort(files_created)
Expand Down
52 changes: 37 additions & 15 deletions lua/triptych/fs.lua
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
local u = require 'triptych.utils'
local plenary_filetype = require 'plenary.filetype'
local plenary_path = require 'plenary.path'
local plenary_async = require 'plenary.async'

local M = {}

Expand All @@ -15,28 +12,53 @@ end
---@param path string
---@return string?
function M.get_filetype_from_path(path)
-- plenary locks up when trying to read a fifo file, so we're sniffing this out first
-- Bail out early for fifo files to avoid hangs
if vim.fn.getftype(path) == 'fifo' then
return 'fifo'
end
-- We still want to use plenary though, because it has more advanced filetype detection
local success, result = pcall(plenary_filetype.detect, path)
if success then
local success, result = pcall(vim.filetype.match, { filename = path })
if success and result then
return result
end
-- Fallback: read a small chunk to sniff the filetype by content
local f = io.open(path, 'r')
if f then
local sample = f:read(512) or ''
f:close()
local ok, ft = pcall(vim.filetype.match, { filename = path, contents = vim.split(sample, '\n') })
if ok and ft then
return ft
end
end
end

M.read_file_async = plenary_async.wrap(function(file_path, callback)
local file = plenary_path:new(file_path)
---Read a file asynchronously and call callback(err, lines)
---@param file_path string
---@param callback fun(err: string|nil, lines: string[]|nil)
function M.read_file_async(file_path, callback)
local uv = vim.uv or vim.loop

if not file:exists() then
return callback('File does not exist', nil)
end
uv.fs_open(file_path, 'r', 438, function(open_err, fd)
if open_err or not fd then
return callback('Could not open file: ' .. (open_err or 'unknown error'), nil)
end

file:read(function(content)
callback(nil, u.multiline_str_to_table(content))
uv.fs_fstat(fd, function(stat_err, stat)
if stat_err or not stat then
uv.fs_close(fd, function() end)
return callback('Could not stat file: ' .. (stat_err or 'unknown error'), nil)
end

uv.fs_read(fd, stat.size, 0, function(read_err, data)
uv.fs_close(fd, function() end)
if read_err then
return callback('Could not read file: ' .. read_err, nil)
end
callback(nil, u.multiline_str_to_table(data))
end)
end)
end)
end, 2)
end

---Keep recursively reading into sub-directories, so long as each sub-directory contains only a single directory and no files
---@param path string
Expand Down
6 changes: 0 additions & 6 deletions lua/triptych/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -149,12 +149,6 @@ local function setup(user_config)
return warn 'triptych.nvim requires Neovim >= 0.9.0'
end

local plenary_installed, _ = pcall(require, 'plenary')

if not plenary_installed then
return warn 'triptych.nvim requires plenary.nvim'
end

vim.g.triptych_is_open = false

vim.api.nvim_create_user_command('Triptych', function(opts)
Expand Down
4 changes: 2 additions & 2 deletions lua/triptych/syntax_highlighting.lua
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ M.start = function(buf, filetype)
if lang then
local success, _ = pcall(vim.treesitter.get_parser, buf, lang)
if success then
vim.treesitter.start(buf, lang)
treesitter_applied = true
local start_success, _ = pcall(vim.treesitter.start, buf, lang)
treesitter_applied = start_success
end
end
if not treesitter_applied then
Expand Down
17 changes: 10 additions & 7 deletions lua/triptych/view.lua
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ local fs = require 'triptych.fs'
local git = require 'triptych.git'
local diagnostics = require 'triptych.diagnostics'
local autocmds = require 'triptych.autocmds'
local plenary_async = require 'plenary.async'
local syntax_highlighting = require 'triptych.syntax_highlighting'

local M = {}
Expand Down Expand Up @@ -54,14 +53,18 @@ end
---@param child_win_buf number
---@param path string
local function read_file_and_publish(child_win_buf, path)
plenary_async.run(function()
fs.read_file_async(path, function(err, lines)
if err then
fs.read_file_async(path, function(err, lines)
if err then
vim.schedule(function()
vim.notify(err, vim.log.levels.ERROR)
else
autocmds.send_file_read(child_win_buf, path, lines)
end)
else
if lines then
vim.schedule(function()
autocmds.send_file_read(child_win_buf, path, lines)
end)
end
end)
end
end)
end

Expand Down
4 changes: 3 additions & 1 deletion test_framework/queue.lua
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,9 @@ function TestQueue:handle_all_tests_succeeded()
.. result_count.skipped
.. ' skipped, '
.. result_count.passed
.. ' passed, 0 failed'
.. ' passed, '
.. result_count.failed
.. ' failed'
)

self:cleanup()
Expand Down
38 changes: 38 additions & 0 deletions test_framework/test.lua
Original file line number Diff line number Diff line change
Expand Up @@ -154,4 +154,42 @@ M.describe = function(description, tests)
end
end

---Deep-equality assertion.
---@param expected any
---@param actual any
---@param msg? string
M.assert_same = function(expected, actual, msg)
local function deep_eq(a, b)
if type(a) ~= type(b) then
return false
end
if type(a) ~= 'table' then
return a == b
end
for k, v in pairs(a) do
if not deep_eq(v, b[k]) then
return false
end
end
for k in pairs(b) do
if a[k] == nil then
return false
end
end
return true
end

if not deep_eq(expected, actual) then
local lines = {}
if msg then
table.insert(lines, msg)
end
table.insert(lines, 'Expected:')
table.insert(lines, vim.inspect(expected))
table.insert(lines, 'Got:')
table.insert(lines, vim.inspect(actual))
error(table.concat(lines, '\n'), 2)
end
end

return M
2 changes: 1 addition & 1 deletion test_framework/utils.lua
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ function M.raise_error(error_message)
if M.is_headless() then
M.print(error_message)
else
error(error_message)
vim.notify(error_message, vim.log.levels.ERROR)
end
end

Expand Down
6 changes: 3 additions & 3 deletions tests/specs/config_spec.lua
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
local assert = require 'luassert'
local u = require 'tests.utils'
local config = require 'triptych.config'
local framework = require 'test_framework.test'
local it = framework.test
local describe = framework.describe
local assert_same = framework.assert_same

local function expected_default_config()
return {
Expand Down Expand Up @@ -80,7 +80,7 @@ end

describe('create_merged_config', {
it('returns the default config when user config is empty', function()
assert.same(expected_default_config(), config.create_merged_config {})
assert_same(expected_default_config(), config.create_merged_config {})
end),

it('merges partial user config with the default', function()
Expand All @@ -99,6 +99,6 @@ describe('create_merged_config', {
result.git_signs.enabled = false
return result
end)
assert.same(expected, config.create_merged_config(user_config))
assert_same(expected, config.create_merged_config(user_config))
end),
})
4 changes: 2 additions & 2 deletions tests/specs/help_spec.lua
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
local help = require 'triptych.help'
local assert = require 'luassert'
local framework = require 'test_framework.test'
local it = framework.test
local describe = framework.describe
local assert_same = framework.assert_same

describe('help_lines', {
it('returns key bindings', function()
local result = help.help_lines()

assert.same({
assert_same({
' Triptych key bindings',
' ',
' add : a',
Expand Down
Loading
Loading