Skip to content

Commit 620f56a

Browse files
authored
Merge pull request #158 from lambdalisue/support-worktree
Add `git worktree` support actions and `:x` variants to `rebase` actions
2 parents 05a183c + 3d26c2c commit 620f56a

File tree

6 files changed

+196
-38
lines changed

6 files changed

+196
-38
lines changed

denops/gin/action/branch_delete.ts

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { define, GatherCandidates, Range } from "./core.ts";
44

55
export type Candidate =
66
| { kind: "remote"; branch: string; remote: string }
7-
| { kind?: "alias" | "local"; branch: string };
7+
| { kind?: "alias" | "local"; branch: string; worktree?: string };
88

99
export async function init(
1010
denops: Denops,
@@ -50,11 +50,19 @@ async function doDelete(
5050
]);
5151
break;
5252
default:
53-
await denops.dispatch("gin", "command", "", [
54-
"branch",
55-
force ? "-D" : "-d",
56-
x.branch,
57-
]);
53+
if (x.worktree) {
54+
await denops.dispatch("gin", "command", "", [
55+
"worktree",
56+
"remove",
57+
x.worktree,
58+
]);
59+
} else {
60+
await denops.dispatch("gin", "command", "", [
61+
"branch",
62+
force ? "-D" : "-d",
63+
x.branch,
64+
]);
65+
}
5866
break;
5967
}
6068
}

denops/gin/action/branch_move.ts

Lines changed: 37 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import * as batch from "jsr:@denops/std@^7.0.0/batch";
33
import * as helper from "jsr:@denops/std@^7.0.0/helper";
44
import { define, GatherCandidates, Range } from "./core.ts";
55

6-
export type Candidate = { branch: string };
6+
export type Candidate = { branch: string; worktree?: string };
77

88
export async function init(
99
denops: Denops,
@@ -40,21 +40,41 @@ async function doMove(
4040
if (!x) {
4141
return;
4242
}
43-
const from = x.branch;
44-
const name = await helper.input(denops, {
45-
prompt: `Rename (from ${from}): `,
46-
text: from,
47-
});
48-
await denops.cmd('redraw | echo ""');
49-
if (!name) {
50-
await helper.echoerr(denops, "Cancelled");
51-
return;
43+
if (x.worktree) {
44+
const from = x.worktree;
45+
const newPath = await helper.input(denops, {
46+
prompt: `New path (from ${from}): `,
47+
text: from,
48+
});
49+
await denops.cmd('redraw | echo ""');
50+
if (!newPath) {
51+
await helper.echoerr(denops, "Cancelled");
52+
return;
53+
}
54+
await denops.dispatch("gin", "command", "", [
55+
"worktree",
56+
"move",
57+
...(force ? ["--force"] : []),
58+
from,
59+
newPath,
60+
]);
61+
} else {
62+
const from = x.branch;
63+
const newName = await helper.input(denops, {
64+
prompt: `Rename (from ${from}): `,
65+
text: from,
66+
});
67+
await denops.cmd('redraw | echo ""');
68+
if (!newName) {
69+
await helper.echoerr(denops, "Cancelled");
70+
return;
71+
}
72+
await denops.dispatch("gin", "command", "", [
73+
"branch",
74+
...(force ? ["--force"] : []),
75+
"--move",
76+
from,
77+
newName,
78+
]);
5279
}
53-
await denops.dispatch("gin", "command", "", [
54-
"branch",
55-
...(force ? ["--force"] : []),
56-
"--move",
57-
from,
58-
name,
59-
]);
6080
}

denops/gin/action/branch_new.ts

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -45,19 +45,19 @@ async function doNew(
4545
const xs = await gatherCandidates(denops, bufnr, range);
4646
const x = xs.at(0);
4747
const from = x?.target ?? "HEAD";
48-
const name = await helper.input(denops, {
48+
const branchName = await helper.input(denops, {
4949
prompt: `New branch (from ${from}): `,
5050
text: from,
5151
});
5252
await denops.cmd('redraw | echo ""');
53-
if (!name) {
53+
if (!branchName) {
5454
await helper.echoerr(denops, "Cancelled");
5555
return;
5656
}
5757
await denops.dispatch("gin", "command", "", [
5858
"switch",
5959
force ? "-C" : "-c",
60-
name,
60+
branchName,
6161
from,
6262
]);
6363
}
@@ -68,13 +68,17 @@ async function doNewOrphan(
6868
_range: Range,
6969
_gatherCandidates: GatherCandidates<unknown>,
7070
): Promise<void> {
71-
const name = await helper.input(denops, {
71+
const branchName = await helper.input(denops, {
7272
prompt: "New branch (orphan): ",
7373
});
7474
await denops.cmd('redraw | echo ""');
75-
if (!name) {
75+
if (!branchName) {
7676
await helper.echoerr(denops, "Cancelled");
7777
return;
7878
}
79-
await denops.dispatch("gin", "command", "", ["switch", "--orphan", name]);
79+
await denops.dispatch("gin", "command", "", [
80+
"switch",
81+
"--orphan",
82+
branchName,
83+
]);
8084
}

denops/gin/action/rebase.ts

Lines changed: 46 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,27 @@ export async function init(
1818
(denops, bufnr, range) =>
1919
doRebase(denops, bufnr, range, gatherCandidates),
2020
);
21+
await define(
22+
denops,
23+
bufnr,
24+
"rebase:x",
25+
(denops, bufnr, range) =>
26+
doRebase(denops, bufnr, range, gatherCandidates, true),
27+
);
2128
await define(
2229
denops,
2330
bufnr,
2431
"rebase:i",
2532
(denops, bufnr, range) =>
2633
doRebaseInteractive(denops, bufnr, range, gatherCandidates),
2734
);
35+
await define(
36+
denops,
37+
bufnr,
38+
"rebase:i:x",
39+
(denops, bufnr, range) =>
40+
doRebaseInteractive(denops, bufnr, range, gatherCandidates, true),
41+
);
2842
await define(
2943
denops,
3044
bufnr,
@@ -40,16 +54,26 @@ async function doRebase(
4054
bufnr: number,
4155
range: Range,
4256
gatherCandidates: GatherCandidates<Candidate>,
57+
execute?: boolean,
4358
): Promise<void> {
4459
const xs = await gatherCandidates(denops, bufnr, range);
4560
const x = xs.at(0);
4661
if (!x) {
4762
return;
4863
}
49-
await denops.dispatch("gin", "command", "", [
50-
"rebase",
51-
x.commit,
52-
]);
64+
const args = ["rebase", x.commit];
65+
if (execute) {
66+
const cmd = await helper.input(denops, {
67+
prompt: "Execute command after rebase: ",
68+
}) ?? "";
69+
await denops.cmd('redraw | echo ""');
70+
if (!cmd) {
71+
await helper.echoerr(denops, "Cancelled");
72+
return;
73+
}
74+
args.push("-x", cmd);
75+
}
76+
await denops.dispatch("gin", "command", "", args);
5377

5478
// suppress false-positive detection of file changes
5579
await denops.cmd("silent checktime");
@@ -60,20 +84,33 @@ async function doRebaseInteractive(
6084
bufnr: number,
6185
range: Range,
6286
gatherCandidates: GatherCandidates<Candidate>,
87+
execute?: boolean,
6388
): Promise<void> {
6489
const xs = await gatherCandidates(denops, bufnr, range);
6590
const x = xs.at(0);
6691
if (!x) {
6792
return;
6893
}
69-
// NOTE:
70-
// We must NOT await the command otherwise Vim would freeze
71-
// because command proxy could not work if we await here.
72-
denops.dispatch("gin", "command", "", [
94+
const args = [
7395
"rebase",
7496
"--interactive",
7597
x.commit,
76-
]).catch(async (e) => {
98+
];
99+
if (execute) {
100+
const cmd = await helper.input(denops, {
101+
prompt: "Execute command after rebase: ",
102+
}) ?? "";
103+
await denops.cmd('redraw | echo ""');
104+
if (!cmd) {
105+
await helper.echoerr(denops, "Cancelled");
106+
return;
107+
}
108+
args.push("-x", cmd);
109+
}
110+
// NOTE:
111+
// We must NOT await the command otherwise Vim would freeze
112+
// because command proxy could not work if we await here.
113+
denops.dispatch("gin", "command", "", args).catch(async (e) => {
77114
await helper.echoerr(denops, e.toString());
78115
}).then(
79116
// suppress false-positive detection of file changes

denops/gin/action/worktree_new.ts

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
import type { Denops } from "jsr:@denops/std@^7.0.0";
2+
import * as batch from "jsr:@denops/std@^7.0.0/batch";
3+
import * as helper from "jsr:@denops/std@^7.0.0/helper";
4+
import { define, GatherCandidates, Range } from "./core.ts";
5+
6+
export type Candidate = { target?: string };
7+
8+
export async function init(
9+
denops: Denops,
10+
bufnr: number,
11+
gatherCandidates: GatherCandidates<Candidate>,
12+
): Promise<void> {
13+
await batch.batch(denops, async (denops) => {
14+
await define(
15+
denops,
16+
bufnr,
17+
"worktree",
18+
(denops, bufnr, range) =>
19+
doNew(denops, bufnr, range, false, gatherCandidates),
20+
);
21+
await define(
22+
denops,
23+
bufnr,
24+
"worktree:force",
25+
(denops, bufnr, range) =>
26+
doNew(denops, bufnr, range, true, gatherCandidates),
27+
);
28+
await define(
29+
denops,
30+
bufnr,
31+
"worktree:orphan",
32+
(denops, bufnr, range) =>
33+
doNewOrphan(denops, bufnr, range, gatherCandidates),
34+
);
35+
});
36+
}
37+
38+
async function doNew(
39+
denops: Denops,
40+
bufnr: number,
41+
range: Range,
42+
force: boolean,
43+
gatherCandidates: GatherCandidates<Candidate>,
44+
): Promise<void> {
45+
const xs = await gatherCandidates(denops, bufnr, range);
46+
const x = xs.at(0);
47+
const target = x?.target ?? "HEAD";
48+
const worktreePath = await helper.input(denops, {
49+
prompt: `Worktree path (for ${target}): `,
50+
text: `.worktrees/${target}`,
51+
});
52+
await denops.cmd('redraw | echo ""');
53+
if (!worktreePath) {
54+
await helper.echoerr(denops, "Cancelled");
55+
return;
56+
}
57+
await denops.dispatch("gin", "command", "", [
58+
"worktree",
59+
"add",
60+
...(force ? ["-f"] : []),
61+
worktreePath,
62+
target,
63+
]);
64+
}
65+
66+
async function doNewOrphan(
67+
denops: Denops,
68+
_bufnr: number,
69+
_range: Range,
70+
_gatherCandidates: GatherCandidates<unknown>,
71+
): Promise<void> {
72+
const worktreePath = await helper.input(denops, {
73+
prompt: "Worktree path (orphan): ",
74+
text: `.worktrees/orphan`,
75+
});
76+
await denops.cmd('redraw | echo ""');
77+
if (!worktreePath) {
78+
await helper.echoerr(denops, "Cancelled");
79+
return;
80+
}
81+
await denops.dispatch("gin", "command", "", [
82+
"worktree",
83+
"add",
84+
"--orphan",
85+
worktreePath,
86+
]);
87+
}

denops/gin/command/branch/edit.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import { init as initActionMerge } from "../../action/merge.ts";
1919
import { init as initActionRebase } from "../../action/rebase.ts";
2020
import { init as initActionSwitch } from "../../action/switch.ts";
2121
import { init as initActionYank } from "../../action/yank.ts";
22+
import { init as initActionWorktreeNew } from "../../action/worktree_new.ts";
2223
import { Branch, parse as parseBranch } from "./parser.ts";
2324

2425
export async function edit(
@@ -71,6 +72,7 @@ export async function exec(
7172
await initActionBranchDelete(denops, bufnr, gatherCandidates);
7273
await initActionBranchMove(denops, bufnr, gatherCandidates);
7374
await initActionBranchNew(denops, bufnr, gatherCandidates);
75+
await initActionWorktreeNew(denops, bufnr, gatherCandidates);
7476
await initActionBrowse(denops, bufnr, async (denops, bufnr, range) => {
7577
const xs = await gatherCandidates(denops, bufnr, range);
7678
return xs.map((b) => ({ commit: b.target, ...b }));

0 commit comments

Comments
 (0)