initial commit

remotes/origin/HEAD
pseudometa 2022-11-21 13:54:41 +01:00
commit c1f1ec5cc1
3 changed files with 220 additions and 0 deletions

21
LICENSE Normal file
View File

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2022 Christopher Grieser
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

51
README.md Normal file
View File

@ -0,0 +1,51 @@
# nvim-ghengis
Convenience file operations for neovim written in lua.
<!--toc:start-->
- [How is this different from `vim.eunuch`?](#how-is-this-different-from-vimeunuch)
- [Installation and Setup](#installation-and-setup)
- [Available Commands](#available-commands)
- [Why that name?](#why-that-name)
<!--toc:end-->
## How is this different from `vim.eunuch`?
- Written 100% in lua.
- Uses up-to-date nvim features like `vim.ui.input` or `vim.notify`. This means you can get nicer input fields via plugins like [dressing.nvim](https://github.com/stevearc/dressing.nvim), and nice confirmation notices with plugins like [nvim-notify](https://github.com/rcarriga/nvim-notify), if they are installed and setup.
- Some minor improvements like automatically keeping the extensions when no extension is given.
- Except for `trashFile` and `chmodx` only vim commands or lua os-modules are used to keep shell requirements to a minimum.
## Installation and Setup
```lua
-- Packer
use "chrisgrieser/nvim-ghengis"
```
> __Note__
> `ghengis` requires no `.setup()` function. Simply create keybindings for the commands you want to use.
```lua
local ghengis = require("ghengis")
local keymap = vim.keymap.set
keymap("n", "<leader>yp", ghengis.copyFilepath)
keymap("n", "<leader>yn", ghengis.copyFilename)
keymap("n", "<leader>cx", ghengis.chmodx)
keymap("n", "<leader>rf", ghengis.renameFile)
keymap("n", "<leader>nf", ghengis.createNewFile)
keymap("n", "<leader>yf", ghengis.duplicateFile)
keymap("n", "<leader>df", ghengis.trashFile) -- requires macOS or Linux `mv` command
keymap("x", "<leader>x", ghengis.moveSelectionToNewFile)
```
## Available Commands
- `ghengis.copyFilepath`: Copy the absolute file path. When `clipboard='unnamed[plus]`, copies to the `+` register, otherwise to `"`.
- `ghengis.copyFilename`: Copy file name. When `clipboard='unnamed[plus]`, copies to the `+` register, otherwise to `"`.
- `ghengis.chmodx`: Run `chmod +x` on the current file.
- `ghengis.renameFile`: Rename the current file. If no extension is provided, will keep the current file extension.
- `ghengis.createNewFile`: Create a new file. If no extension is provided, will keep use the extension of the current file.
- `ghengis.duplicateFile`: Duplicate the current file. If no extension is provided, will keep the current file extension.
- `ghengis.trashFile`: Move the current file to `$HOME/.Trash`. (Requires macOS or Linux, since is using `mv`.)
- `ghengis.moveSelectionToNewFile`: Visual Mode Command. Prompts for a new file name and moves the current selection to that new file.
## Why that name?
A tribute to [vim.eunuch](https://github.com/tpope/vim-eunuch) as opposed to childless eunuchs, it is said that [Ghengis Khan has fathered thousands of children](https://allthatsinteresting.com/genghis-khan-children).

148
lua/ghengis.lua Normal file
View File

@ -0,0 +1,148 @@
local M = {}
local error = vim.log.levels.ERROR
local expand = vim.fn.expand
local fn = vim.fn
local cmd = vim.cmd
local function leaveVisualMode()
-- https://github.com/neovim/neovim/issues/17735#issuecomment-1068525617
local escKey = vim.api.nvim_replace_termcodes("<Esc>", false, true, true)
vim.api.nvim_feedkeys(escKey, "nx", false)
end
--------------------------------------------------------------------------------
---Performing common file operation tasks
---@param op string rename|duplicate|new|newFromSel
local function fileOp(op)
local dir = expand("%:p:h")
local oldName = expand("%:t")
local oldExt = expand("%:e")
local prevReg
if op == "newFromSel" then
prevReg = fn.getreg("z")
leaveVisualMode()
cmd [['<,'>delete z]]
end
local promptStr
if op == "duplicate" then promptStr = "Duplicate File as: "
elseif op == "rename" then promptStr = "Rename File to: "
elseif op == "new" or op == "newFromSel" then promptStr = "Name for New File: "
end
vim.ui.input({prompt = promptStr}, function(newName)
local invalidName
if newName then
invalidName = newName:find("^%s*$") or newName:find("/") or newName:find(":") or newName:find("\\")
end
if not (newName) or invalidName then -- cancel
if op == "newFromSel" then
cmd [[undo]] -- undo deletion
fn.setreg("z", prevReg) -- restore register content
end
if invalidName then vim.notify(" Invalid Filename.", error) end
return
end
if not (newName) or invalidName then -- cancel
if op == "newFromSel" then
cmd [[undo]] -- undo deletion
fn.setreg("z", prevReg) -- restore register content
end
if invalidName then
vim.notify(" Invalid Filename.", error)
end
return
end
local extProvided = newName:find(".%.") -- non-leading dot to exclude dotfile-dots
local isDotfile = newName:match("^%.")
if not (extProvided) and not (isDotfile) then
newName = newName .. "." .. oldExt
end
local filepath = dir .. "/" .. newName
if op == "duplicate" then
cmd("saveas " .. filepath)
cmd("edit " .. filepath)
vim.notify(" Duplicated '" .. oldName .. "' as '" .. newName .. "'.")
elseif op == "rename" then
os.rename(oldName, newName)
cmd("edit " .. filepath)
cmd("bdelete #")
vim.notify(" Renamed '" .. oldName .. "' to '" .. newName .. "'.")
elseif op == "new" then
cmd("edit " .. filepath)
cmd("write " .. filepath)
elseif op == "newFromSel" then
cmd("edit " .. filepath)
cmd("put z")
cmd("write " .. filepath)
fn.setreg("z", prevReg) -- restore register content
end
end)
end
---Rename Current File
function M.renameFile() fileOp("rename") end
---Duplicate Current File
function M.duplicateFile() fileOp("duplicate") end
---Create New File
function M.createNewFile() fileOp("new") end
---Move Selection to New File
function M.moveSelectionToNewFile() fileOp("newFromSel") end
--------------------------------------------------------------------------------
---copying file information
---@param operation string filename|filepath
local function copyOp(operation)
local useSystemClipb = vim.opt.clipboard:get()[1]:find("unnamed")
local reg = '"'
if useSystemClipb then reg = "+" end
local toCopy
if operation == "filename" then
toCopy = expand("%:t")
elseif operation == "filepath" then
toCopy = expand("%:p")
end
fn.setreg(reg, toCopy)
vim.notify(" COPIED\n " .. toCopy)
end
---Copy absolute path of current file
function M.copyFilepath() copyOp("filepath") end
---Copy name of current file
function M.copyFilename() copyOp("filename") end
--------------------------------------------------------------------------------
---Run `chmod +x` on the current file. Requires `chmod`.
function M.chmodx()
local currentFile = expand("%:p")
os.execute("chmod +x '" .. currentFile .. "'")
vim.notify(" Execution permission granted. ")
end
---Trash the Current File. Requires `mv`.
---@param opts? table
function M.trashFile(opts)
if not (opts) then opts = {trashLocation = "$HOME/.Trash/"} end
local currentFile = fn.expand("%:p")
local filename = fn.expand("%:t")
cmd [[update!]]
os.execute('mv -f "' .. currentFile .. '" "' .. opts.trashLocation .. '"')
cmd [[bdelete]]
vim.notify(" '" .. filename .. "' deleted. ")
end
return M