diff --git a/bin/gc.luau b/bin/gc.luau new file mode 100644 index 0000000..8003a7f --- /dev/null +++ b/bin/gc.luau @@ -0,0 +1,102 @@ +local process = require("@lune/process") +local stdio = require("@lune/stdio") + +local dim = function(str) return stdio.style("dim") .. str .. stdio.style("reset") end + +function main(args: {string}) + local gitStatusChild = process.spawn("git", {"status", table.unpack(args)}) + if not gitStatusChild.ok then + stdio.ewrite(gitStatusChild.stderr) + return gitStatusChild.code + end + + local statusDiff:{{ file: string, type: string }} = {} + local statusLines = gitStatusChild.stdout:split("\n") + + for lineCount, line in statusLines do + if lineCount >= 6 and lineCount then + local type, file = line:match("^%s(.+): (.+)$") + if type == nil then + break + end + + file = file:gsub("(%(.*%))", "") + + table.insert(statusDiff, {type = type, file = file}) + end + + continue + end + + local typeCounts = setmetatable({}, { + __index = function(self, key) + self[key] = setmetatable({}, { + __index = function(self, key) + if rawget(self, key) == nil then + self[key] = 0 + end + + return rawget(self, key) + end + }) + + return rawget(self, key) + end + }) + + for _, diff in statusDiff do + typeCounts[diff.type].count += 1 + table.insert(typeCounts[diff.type], diff.file) + end + + print("Changes to commit:") + for type, filesAndCount: { + count: number, + [number]: string, + } in typeCounts do + local count = filesAndCount.count + local bullet = dim("•") + stdio.write(` {bullet} { + stdio.color("yellow") .. stdio.style("bold") .. count .. stdio.style("reset") + } files {type}`) + + if count == 1 then + stdio.write(` ({dim(filesAndCount[1])})`) + continue + end + + stdio.write("\n") + local files = filesAndCount + files.count = nil + for _, file in files do + -- TODO: Map colors to type + print(` {bullet} {stdio.color("cyan") .. file .. stdio.color("reset")}`) + end + + print("Commit message:") + -- TODO: Conventional commit prompts + local commitMessage = stdio.prompt("text") + local gitCommitChild = process.spawn("git", {"commit", "-a", "-m", commitMessage}) + if not gitCommitChild.ok then + stdio.ewrite(gitCommitChild.stderr) + return gitCommitChild.code + end + + stdio.write("\n") + local toPush = stdio.prompt("confirm", "Push changes to remote?") + if toPush then + local pushChild = process.spawn("lune", { "run", "$HOME/bin/gp.luau" }, { + shell = true, + stdio = "forward" + }) + + if not pushChild.ok then + return pushChild.code + end + end + end + + return 0 +end + +return process.exit(main(process.args)) \ No newline at end of file diff --git a/bin/gl.luau b/bin/gl.luau new file mode 100644 index 0000000..16a2f61 --- /dev/null +++ b/bin/gl.luau @@ -0,0 +1,75 @@ +local process = require("@lune/process") +local DateTime = require("@lune/datetime") +local stdio = require("@lune/stdio") + +local function map(tbl: {[K]: V}, fn: (K, V) -> R): {[K]: R} + local ref = tbl + for key, value in tbl do + ref[key] = fn(key, value) + end + + return ref +end + +export type Commit = { + hash: string, + author: string, + message: string, + date: DateTime.DateTime, +} + +local function formatCommits(_, commit): string + local dim = function(str) return stdio.style("dim") .. str .. stdio.style("reset") end + return string.format( + `{dim("•")} %s {dim("→")} %s`, + commit.hash:sub(1, 7), + stdio.color("yellow") .. commit.message .. stdio.color("reset") + ) +end + +local function outputToCommit(_, line) + local parts = line:split("{{SEP}}") + + local hash = parts[1]:gsub("* ", "") + local message = parts[2] + local isoDate = parts[3]:gsub("[()]", "") + local authorName = parts[4]:gsub("[<>]", "") + + return { + hash = hash, + message = message, + date = DateTime.fromIsoDate(isoDate), + author = authorName, + } +end + +function main(args: {string}) + local range = args[1] + local gitLogChild = process.spawn( + "git", + { + "log", + "--graph", + "--pretty=format:%Cred%h%Creset{{SEP}}%s{{SEP}}%Cgreen(%cI){{SEP}}%C(bold blue)<%an>%Creset", + range or "HEAD~5..HEAD", + } + ) + + if not gitLogChild.ok then + stdio.ewrite(gitLogChild.stderr) + return gitLogChild.code + end + + local commits: { Commit } = map(gitLogChild.stdout:split("\n"), outputToCommit) + local formattedList = map(commits, formatCommits) + + print(table.concat(formattedList, "\n")) + return 0 +end + +return { + formatCommits = formatCommits, + outputToCommit = outputToCommit, + map = map, + main = main +} \ No newline at end of file diff --git a/bin/gp.luau b/bin/gp.luau new file mode 100644 index 0000000..f1bb65e --- /dev/null +++ b/bin/gp.luau @@ -0,0 +1,36 @@ +local process = require("@lune/process") +local stdio = require("@lune/stdio") +local task = require("@lune/task") + +local gitLog = require("./gl.luau") +type Commit = gitLog.Commit + +local function dots(count: number) + for i = 1, count do + stdio.write(".") + task.wait(0.2) + end +end + +function main(args: {string}) + print("Unpushed commits:") + + local childExit = gitLog.main({"main..HEAD"}) + if childExit ~= 0 then + return childExit + end + + stdio.write("Pushing to remote") + task.spawn(dots, 3) + local pushChild = process.spawn("git", {"push"}) + if not pushChild.ok then + stdio.ewrite("\r" .. pushChild.stderr) + return pushChild.code + end + + stdio.write(stdio.color("green") .. " done!" .. stdio.color("reset") .. "\n") + + return 0 +end + +return process.exit(main(process.args)) \ No newline at end of file