diff --git a/src/commands/commit.ts b/src/commands/commit.ts
index b1c9eab..89baa14 100644
--- a/src/commands/commit.ts
+++ b/src/commands/commit.ts
@@ -18,7 +18,11 @@ along with RCZ. If not, see .
*/
import { Command } from "commander";
-import { checkForUpdates, getConfig } from "../utils/functions";
+import {
+ checkForUpdates,
+ getConfig,
+ getDefaultEditor,
+} from "../utils/functions";
import {
cancel,
confirm,
@@ -33,6 +37,32 @@ import {
import { existsSync } from "fs";
import { join } from "path";
import simpleGit, { ResetMode } from "simple-git";
+import { readFile, writeFile } from "fs/promises";
+import { tmpdir } from "os";
+import { spawn } from "child_process";
+
+const getEditorInput = async (defaultValue = "") => {
+ const tempFilePath = join(tmpdir(), `io.resultium.rcz-${Date.now()}.txt`);
+ await writeFile(tempFilePath, defaultValue);
+
+ const editor = spawn(getDefaultEditor(), [tempFilePath], {
+ stdio: "inherit",
+ });
+
+ return await new Promise((resolve) => {
+ editor.on("exit", async (code) => {
+ if (code !== 0) {
+ throw new Error(`Editor exited with code ${code}`);
+ }
+
+ resolve((await readFile(tempFilePath)).toString());
+ });
+
+ editor.on("error", (err) => {
+ throw err;
+ });
+ });
+};
const command = new Command("commit")
.alias("c")
@@ -224,27 +254,56 @@ const command = new Command("commit")
process.exit(0);
}
- const body = await text({
- message: `Insert a commit body (motivation or elaboration for the change), can be left empty`,
- placeholder:
- "improves regex for suspicious character check in router requests",
+ let body: null | string = null;
+ const writeBody = await confirm({
+ message: `Would you like to insert a commit body (elaboration for the change)?`,
+ initialValue: false,
});
- if (isCancel(body)) {
+ if (isCancel(writeBody)) {
cancel("Commit creation cancelled");
process.exit(0);
}
- const footer = await text({
- message: `Insert commit footer, can be left empty, e.g. Acked-by: @johndoe`,
- placeholder: "Acked-by: @security",
+ if (writeBody) {
+ // Stop clack input
+ process.stdin.pause();
+
+ body = await getEditorInput(
+ `e.g.
+* Revert "Guard against SMTP smuggling", commit faf23f1, by restoring the setting to its default.
+* Revert "[security] SMTP smuggling: update short term fix (#2346)", commmit e931e10, by restoring the setting to its default.
+* Set smtpd_forbid_bare_newline=normalize.
+
+Fixes #444
+`,
+ );
+
+ // Resume clack input
+ process.stdin.resume();
+ }
+
+ let footer: null | string = null;
+ const writeFooter = await confirm({
+ message: `Would you like to insert a commit footer?`,
+ initialValue: false,
});
- if (isCancel(footer)) {
+ if (isCancel(writeFooter)) {
cancel("Commit creation cancelled");
process.exit(0);
}
+ if (writeFooter) {
+ process.stdin.pause();
+ footer = await getEditorInput(
+ `e.g.
+Co-authored-by: @john
+`,
+ );
+ process.stdin.resume();
+ }
+
const isBreaking = await confirm({
message: "Does this commit have breaking changes?",
initialValue: false,
diff --git a/src/utils/functions.ts b/src/utils/functions.ts
index b31a131..0c911ce 100644
--- a/src/utils/functions.ts
+++ b/src/utils/functions.ts
@@ -23,7 +23,7 @@ import { join } from "path";
import { cwd } from "process";
import { Config } from "../types";
import { request } from "http";
-import { tmpdir } from "os";
+import { platform, tmpdir } from "os";
import { execSync } from "child_process";
import { gt } from "semver";
import { note } from "@clack/prompts";
@@ -110,3 +110,20 @@ export const checkForUpdates = async () => {
if (gt(cachedVersion, localVersion)) note(updateText);
}
};
+
+export const getDefaultEditor = () => {
+ if (process.env.EDITOR) {
+ return process.env.EDITOR;
+ }
+
+ if (process.env.VISUAL) {
+ return process.env.VISUAL;
+ }
+
+ // Windows as always being the special kid
+ if (platform() === "win32") {
+ return "notepad";
+ } else {
+ return "vi";
+ }
+};