Skip to content

Commit

Permalink
New feature: split file paths into its components (#110)
Browse files Browse the repository at this point in the history
* ✨ (maps.lua): Add new key mappings for RSplitPathPaste and RSplitPathHere
✨ (path.lua): Create new path.lua file to handle path splitting functionality for paste and here commands

* ✨ (maps.lua): Add new commands RSplitPathPaste and RSplitPathHere for splitting file path and pasting or opening it respectively

* ✨ (path.lua): Add support for 's3://' in path matching to handle S3 URLs

* 📝 (README.md): Remove unnecessary blank lines and correct the formatting of the assignment operator
✨ (README.md): Add documentation for two new commands to separate a file path into its components

* 📝 (README.md): Add example usage for <localleader>sp command to improve documentation clarity
  • Loading branch information
PMassicotte authored Apr 7, 2024
1 parent 55f03f8 commit 630c16a
Show file tree
Hide file tree
Showing 3 changed files with 111 additions and 3 deletions.
30 changes: 27 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,6 @@ instructions on usage. See also the output of `:RMapsDesc`.

## Transitioning from Nvim-R


During the conversion of VimScript to Lua, we decided to end support for features
that were useful in the past but no longer sufficiently valuable to be worth
the effort of conversion. We removed support for `Rrst` (it seems that not
Expand All @@ -92,7 +91,7 @@ legacy omni-completion (auto completion with
functions from .GlobalEnv (difficult to make compatible with tree-sitter + LSP
highlighting).

We changed the default key binding to insert the assignment operator (` <- `) from an
We changed the default key binding to insert the assignment operator (`<-`) from an
underscore (which was familiar to Emacs-ESS users) to `Alt+-` which is more
convenient (but does not work on Vim). See the option `assign_map`.

Expand Down Expand Up @@ -140,6 +139,32 @@ function `colorout::isColorOut()` which unduly enables the colorizing of
output in the released version of [colorout]. This bug was fixed in [this
commit](https://github.com/jalvesaq/colorout/commit/1080187f9474b71f16c3c0be676de4c54863d1e7).

There are two new commands available to separate a file path into its different
components.

The first command, <localleader>sp, will take the file path under
the cursor and break it down into its components, then surround it with the
`paste()` function.

The second command, <localleader>sh, will also break down
the file path under the cursor into its components, but instead surround it
with the `here()` function.

It's important to note that both functions require
the [nvim-treesitter](https://github.com/nvim-treesitter/nvim-treesitter)
plugin to be installed.

For example, if you have the following file path under the cursor:

```r
read.csv("/home/user/Documents/file.csv")
```

Running the <localleader>sp command will transform it into:

```r
read.csv(paste("/home", "user", "Documents", "file.csv", sep = "/"))
```

## Screenshots and videos

Expand Down Expand Up @@ -193,7 +218,6 @@ but temporary files are used in a few cases.

- [colorout](https://github.com/jalvesaq/colorout): a package to colorize R's output.


[cmp-r]: https://github.com/R-nvim/cmp-r
[Neovim]: https://github.com/neovim/neovim
[southernlights]: https://github.com/jalvesaq/southernlights
Expand Down
5 changes: 5 additions & 0 deletions lua/r/maps.lua
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ local map_desc = {
RViewDFv = { m = "", k = "", c = "Edit", d = "View the data.frame or matrix under cursor in a vertically split window" },
RViewDFa = { m = "", k = "", c = "Edit", d = "View the head of a data.frame or matrix under cursor in a split window" },
RShowEx = { m = "", k = "", c = "Edit", d = "Extract the Examples section and paste it in a split window" },
RSeparatePathPaste = { m = "", k = "", c = "Edit", d = "Split the path of the file under the cursor and paste it using the paste() prefix function" },
RSeparatePathHere = { m = "", k = "", c = "Edit", d = "Split the path of the file under the cursor and open it using the here() prefix function" },
RNextRChunk = { m = "", k = "", c = "Navigate", d = "Go to the next chunk of R code" },
RGoToTeX = { m = "", k = "", c = "Navigate", d = "Go the corresponding line in the generated LaTeX document" },
RDocExSection = { m = "", k = "", c = "Navigate", d = "Go to Examples section of R documentation" },
Expand Down Expand Up @@ -137,6 +139,9 @@ local control = function(file_type)
create_maps("v", "RViewDF", "rv", "<Cmd>lua require('r.run').action('viewobj', 'v')")
create_maps("v", "RDputObj", "td", "<Cmd>lua require('r.run').action('dputtab', 'v')")

create_maps("nvi", "RSeparatePathPaste", "sp", "<Cmd>lua require('r.path').separate('paste')")
create_maps("nvi", "RSeparatePathHere", "sh", "<Cmd>lua require('r.path').separate('here')")

if type(config.csv_app) == "function" or config.csv_app == "" then
create_maps("ni", "RViewDFs", "vs", "<Cmd>lua require('r.run').action('viewobj', 'n', ', howto=\"split\"')")
create_maps("ni", "RViewDFv", "vv", "<Cmd>lua require('r.run').action('viewobj', 'n', ', howto=\"vsplit\"')")
Expand Down
79 changes: 79 additions & 0 deletions lua/r/path.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
local M = {}

local unquote_and_split_file_path = function(file_path)
local quote = file_path:match("^[\"']")
if quote then
file_path = file_path:sub(2, -2) -- Remove surrounding quotes
end

-- Split the path into components
local components = {}
for component in file_path:gmatch("[^/]+") do
table.insert(components, component)
end

-- If path starts with a /, add it to the first component
if file_path:sub(1, 1) == "/" then components[1] = "/" .. components[1] end

-- Join the components with the detected quote
local result = table.concat(components, quote .. ", " .. quote)

return result
end

local function replace_path(node, formatted_path)
local bufnr = vim.api.nvim_get_current_buf()
local start_row, start_col, end_row, end_col = node:range()

vim.api.nvim_buf_set_text(
bufnr,
start_row,
start_col,
end_row,
end_col,
{ formatted_path }
)
end

M.separate = function(prefix)
local node = vim.treesitter.get_node()

if node and node:type() == "string" then
local path = vim.treesitter.get_node_text(node, 0)

-- Check if the path is a URL or doesn't contain slashes
if
path:match("https?://")
or path:match("ftp://")
or path:match("s3://")
or not path:match("/")
then
return
end

-- Traverse up the syntax tree until we find a call_expression node
local parent = node:parent()
while parent do
if parent:type() == "call" then
local function_name = vim.treesitter.get_node_text(parent, 0)
if function_name:match("paste") or function_name:match("here") then
return
end
end
parent = parent:parent()
end

-- Format the path
local formatted_path = unquote_and_split_file_path(path)

if prefix == "paste" then
formatted_path = 'paste("' .. formatted_path .. '", sep = "/")'
elseif prefix == "here" then
formatted_path = 'here("' .. formatted_path .. '")'
end

replace_path(node, formatted_path)
end
end

return M

0 comments on commit 630c16a

Please sign in to comment.