Skip to content
This repository was archived by the owner on Aug 12, 2023. It is now read-only.

feat: add command :TypescriptRenameFolder #59

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
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
27 changes: 27 additions & 0 deletions lua/typescript/commands.lua

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

49 changes: 49 additions & 0 deletions lua/typescript/rename-folder.lua

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

37 changes: 37 additions & 0 deletions src/commands.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { config } from "@ts/config";
import { goToSourceDefinition } from "@ts/go-to-source-definition";
import { renameFile } from "@ts/rename-file";
import { renameFolder } from "@ts/rename-folder";
import {
addMissingImports,
fixAll,
Expand All @@ -26,6 +27,42 @@ export const setupCommands = (bufnr: number): void => {
{ bang: true }
);

vim.api.nvim_buf_create_user_command(
bufnr,
"TypescriptRenameFolder",
(opts) => {
const sourceFile = vim.api.nvim_buf_get_name(bufnr);
vim.ui.input(
{ prompt: "Old path: ", default: sourceFile },

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should default to the source file's parent directory and not the source file itself.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what do you thing of using vim.ui.select and prompting the user to select any of the parent directory to be renamed.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure about this - it would work well with Telescope / other pickers but might be kind of janky with the default handler, especially if there's a lot of choices. Let's keep it consistent with :TypescriptRenameFile for now and consider that as a future improvement.

(sourceInput) => {
if (
sourceInput === "" ||

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can validate sourceInput and targetInput after prompting for both, since we should validate that they are not the same.

sourceInput === sourceFile ||
sourceInput === undefined
) {
return;
}
vim.ui.input(
{ prompt: "New path: ", default: sourceFile },
(targetInput) => {
if (
targetInput === "" ||
targetInput === sourceFile ||
targetInput === undefined
) {
return;
}
renameFolder(sourceInput, targetInput, {
force: opts.bang,
});
}
);
}
);
},
{ bang: true }
);

vim.api.nvim_buf_create_user_command(
bufnr,
"TypescriptGoToSourceDefinition",
Expand Down
46 changes: 46 additions & 0 deletions src/rename-folder.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { util } from "lspconfig";
import { renameFile } from "@ts/rename-file";
import { debugLog } from "@ts/utils";

interface Opts {
force?: boolean;
}

export const renameFolder = (
source: string,

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd prefer to rename these variables to something like sourceDir and targetDir to avoid confusion.

target: string,
opts: Opts = {}
): boolean => {
debugLog(source, target);
const sourceBufnr = vim.fn.bufadd(source);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know if these 2 lines are still needed, since we would be loading a folder as a buffer.

vim.fn.bufload(sourceBufnr);

if (!util.path.is_dir(source)) {
debugLog("source is not a directory");
return false;
}

if (
util.path.exists(target) &&
util.path.is_dir(target) &&

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this check may cause issues, since we are not handling the case where the target exists but is not a directory (which should just throw an error).

(opts.force === undefined || opts.force === false)
) {
const status = vim.fn.confirm("Folder exists! Overwrite?", "&Yes\n&No");
if (status !== 1) {
debugLog("user declined to overrwrite file; aborting");
return false;
}
}
vim.fn.mkdir(vim.fn.fnamemodify(target, ":p:h"), "p");
const files = vim.fn.readdir(source);
for (const file of files) {
debugLog(file);
if (
file.endsWith(".ts") &&
renameFile(source + file, target + file, opts)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't seem to currently work since the combined paths don't include a separator. We can use nvim-lspconfig's utils.path.join, or we can use vim.fs.find():

  // files is an array of absolute paths
  const files = vim.fs.find(
    (file) => string.find(file, "[.][tj][s]x?$")[0] !== undefined,
    {
      path: source,
      type: "file",
    }
  );

Then for the new path, we can replace source with target in the current path:

  for (const file of files) {
    debugLog(file);
    if (renameFile(file, file.replace(source, target), opts)) {
      debugLog("OK");
    }
  }

Though I think the above would look clearer if we change variable names as I mentioned in another comment.

) {
debugLog("OK");
}
}
return true;
};
1 change: 1 addition & 0 deletions src/types/lspconfig.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ declare module "lspconfig" {
namespace util {
namespace path {
const exists: (path: string) => boolean;
const is_dir: (path: string) => boolean;
}
}
}
1 change: 1 addition & 0 deletions src/types/nvim.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,7 @@ declare namespace vim {
const bufload: (bufnr: number) => void;
const has: (feature: string) => 0 | 1;
const mkdir: (name: string, path?: string, prot?: number) => void;
const readdir: (name: string) => string[];
const fnamemodify: (fname: string, mods: string) => string;
}

Expand Down