Skip to content

Instantly share code, notes, and snippets.

@Jerakin
Last active October 16, 2024 10:01
Show Gist options
  • Save Jerakin/2bce5afb88e40b406780dc6019aaaaaf to your computer and use it in GitHub Desktop.
Save Jerakin/2bce5afb88e40b406780dc6019aaaaaf to your computer and use it in GitHub Desktop.
Modified clinkprompt

Changes from clink builtin

  • Added time module
    • Format is default "%H:%M:%S" but can be overwritten with an environment variable PURE_TIME_FORMAT
  • Added dist module
    • Can be used to insert a distance to right aline values. Only works on first line and only once.
  • Changed virtualenv module
    • Uses VIRTUAL_ENV_PROMPT (name of virtual env) if set over VIRTUAL_ENV (path of virtual env).
-- Based on Pure (https://github.com/sindresorhus/pure)
-- MIT License
-- DON'T EDIT THIS FILE DIRECTLY; IT GETS OVERWRITTEN WHEN CLINK IS UPDATED.
-- INSTEAD MAKE A COPY OF THIS FILE AND EDIT THE COPY.
-- Pure is a pretty, minimal, and fast prompt.
--
-- Pure can be configured by setting environment variables. You can set the
-- environment variables via a batch script, or in the Windows Settings app.
--
-- Pure doesn't need a special font.
--
-- To activate this prompt, run `clink config prompt use pure`.
-- To deactivate it, run `clink config prompt clear`.
--
-- CHOOSING WHAT INFORMATION IS SHOWN IN THE PROMPT:
--
-- These environment variables specify what information to include in the
-- prompt:
-- PURE_LINE1_MODULES = The prompt modules for the first line.
-- PURE_LINE2_MODULES = The prompt modules for the second line.
--
-- The available prompt modules are:
-- execution_time
-- git
-- host
-- path
-- prompt
-- user
-- virtualenv
-- time
--
-- The "prompt" prompt module colors the prompt symbol based on the last exit
-- code (see the color variables further below).
--
-- The "execution_time" prompt module uses an environment variable to decide
-- whether to show the execution time of the previous command:
-- PURE_CMD_MAX_EXEC_TIME = Show execution time when greater than
-- this number of seconds (default is 5).
--
-- CONFIGURING THE COLORS IN THE PROMPT:
--
-- By default, the prompt uses custom colors in Windows Terminal, otherwise it
-- uses colors from the terminal's current color scheme.
--
-- Setting this environment variable makes it always use colors from the
-- terminal's current color scheme, even in Windows Terminal.
-- PURE_USE_TERMINAL_COLORS = Set to any value to force using the
-- terminal's color scheme.
--
-- These environment variables override the default colors. Set them to the
-- SGR Parameters of an ANSI escape code color. For more information on ANSI
-- color codes and SGR Parameters, visit wikipedia:
-- https://en.wikipedia.org/wiki/ANSI_escape_code#SGR
-- PURE_COLOR_EXECUTION_TIME
-- PURE_COLOR_GIT_ARROW
-- PURE_COLOR_GIT_STASH
-- PURE_COLOR_GIT_BRANCH
-- PURE_COLOR_GIT_ACTION
-- PURE_COLOR_GIT_DIRTY
-- PURE_COLOR_HOST_AT
-- PURE_COLOR_HOST
-- PURE_COLOR_PATH
-- PURE_COLOR_PROMPT_ERROR
-- PURE_COLOR_PROMPT_SUCCESS
-- PURE_COLOR_USER
-- PURE_COLOR_USER_ROOT
-- PURE_COLOR_VIRTUALENV
-- PURE_COLOR_TIME
--
-- These environment variables override the default symbols. Set them to the
-- text to be shown.
-- PURE_PROMPT_SYMBOL = The prompt symbol (e.g. ">").
-- PURE_GIT_DIRTY = The symbol to indicate the git workspace is dirty.
-- PURE_GIT_DOWN_ARROW = The symbol to indicate the branch is behind the upstream.
-- PURE_GIT_UP_ARROW = The symbol to indicate the branch is ahead of the upstream.
-- PURE_GIT_STASH_SYMBOL = The symbol to indicate one or more stashes exist.
--
-- NOTE: This version of the Pure prompt does not automatically perform git
-- fetches in the background.
--
-- Changes from clink builtin
-- Added time module
-- Format is default "%H:%M:%S" but can be overwritten with an environment variable PURE_TIME_FORMAT
-- Added dist module
-- Can be used to insert a distance to right aline values. Only works on first line and only once.
-- Changed virtualenv module
-- Uses VIRTUAL_ENV_PROMPT (name of virtual env) if set over VIRTUAL_ENV (path of virtual env).
local default_colors_terminal = {
["execution_time"] = "yellow",
["git_arrow"] = "cyan",
["git_stash"] = "cyan",
["git_branch"] = "sgr 38;5;242",
--["git_branch_cached"] = "red",
["git_action"] = "yellow",
["git_dirty"] = "sgr 38;5;218",
["host_at"] = "sgr 38;5;242",
["host"] = "sgr 38;5;242",
["path"] = "bold blue",
["prompt_error"] = "red",
["prompt_success"] = "magenta",
["user"] = "sgr 38;5;242",
["user_root"] = "default",
["virtualenv"] = "sgr 38;5;242",
["time"] = "blue",
}
local default_colors_custom = {
["execution_time"] = "#A3BE8C",
["git_arrow"] = "#88C0D0",
["git_stash"] = "#6C6C6C",
["git_branch"] = "#6C6C6C",
--["git_branch_cached"] = "red",
["git_action"] = "#B48E61",--"yellow",
["git_dirty"] = "sgr 38;5;218",
["host_at"] = "#6C6C6C",
["host"] = "#BF616A",
["path"] = "#81A1C1",
["prompt_error"] = "#BF616A",
["prompt_success"] = "#B48EAD",
["user"] = "#BF616A",
["user_root"] = "default",
["virtualenv"] = "#6C6C6C",
["time"] = "#81A1C1",
}
local term_emoji = (clink.getansihost() == "winterminal") and true or nil
local default_symbols = {
["PURE_PROMPT_SYMBOL"] = term_emoji and "❯" or ">",
["PURE_GIT_DIRTY"] = "*",
["PURE_GIT_DOWN_ARROW"] = term_emoji and "⇣" or "↓",
["PURE_GIT_UP_ARROW"] = term_emoji and "⇡" or "↑",
["PURE_GIT_STASH_SYMBOL"] = "≡",
}
local colors = {}
local symbols = {}
local function sgr(code)
return "\x1b["..(code or "").."m"
end
local function update_config()
local default_colors = os.getenv("PURE_USE_TERMINAL_COLORS") and default_colors_terminal or default_colors_custom
for k,v in pairs(default_colors) do
local c = os.getenv("pure_color_"..k) or v
colors[k] = sgr((settings.parsecolor(c) or ""):gsub("^0;", ""))
end
for k,v in pairs(default_symbols) do
symbols[k] = os.getenv(k) or v
end
end
local last_duration
local last_exitcode
local last_gitstatus
local function execution_time_func()
if last_duration then
local max = tonumber(os.getenv("PURE_CMD_MAX_EXEC_TIME") or "5")
if last_duration >= max then
local d, h, m, s
local duration = last_duration
local tenths = duration < 30
local t = math.floor(duration * 10) % 10
duration = math.floor(duration)
s = (duration % 60)
duration = math.floor(duration / 60)
if duration > 0 then
m = (duration % 60)
duration = math.floor(duration / 60)
if duration > 0 then
h = (duration % 24)
duration = math.floor(duration / 24)
if duration > 0 then
d = duration
end
end
end
t = tenths and "."..t or ""
local text = ""
if (t ~= "") or (s and (s > 0)) then
text = tostring(s or "0")..t
if text == "0.0" then
text = ""
else
text = text.."s "
end
end
if m and (m > 0) then
text = tostring(m).."m "..text
end
if h and (h > 0) then
text = tostring(h).."h "..text
end
if d and (d > 0) then
text = tostring(d).."d "..text
end
return text:gsub("%s+$", "")
end
end
end
local function getstatus()
local status = git.getstatus()
if status then
status.hasstash = git.hasstash()
status.action = git.getaction()
end
return status
end
local function getvenv()
local status = git.getstatus()
if status then
status.hasstash = git.hasstash()
status.action = git.getaction()
end
return status
end
local function git_func()
if not git.getgitdir() then return end
local status = clink.promptcoroutine(getstatus)
if status then
last_gitstatus = status
else
status = last_gitstatus or { branch=git.getbranch() }
end
local text = colors.git_branch..status.branch..sgr()
if status.dirty then
text = text..colors.git_dirty..symbols.PURE_GIT_DIRTY..sgr()
end
if status.action then
text = text.." "..colors.git_action..status.action..sgr()
end
local arrows = ""
if tonumber(status.behind or 0) > 0 then
arrows = arrows..symbols.PURE_GIT_DOWN_ARROW
end
if tonumber(status.ahead or 0) > 0 then
arrows = arrows..symbols.PURE_GIT_UP_ARROW
end
if arrows ~= "" then
arrows = " "..colors.git_arrow..arrows..sgr()
end
local stash = ""
if status.hasstash then
stash = " "..colors.git_stash..symbols.PURE_GIT_STASH_SYMBOL..sgr()
end
return text..arrows..stash
end
local function host_func()
return os.getenv("COMPUTERNAME")
end
local function path_func()
return rl.collapsetilde(os.getcwd())
end
local function prompt_func()
local color
if last_exitcode and last_exitcode ~= 0 then
color = colors.prompt_error
else
color = colors.prompt_success
end
return color..(symbols.PURE_PROMPT_SYMBOL).." "
end
local function user_func()
local text = os.getenv("USERNAME")
if os.isuseradmin() then
return colors.user_root..(text or "ADMIN")
elseif text then
return colors.user..text
end
end
local function virtualenv_func()
local text
-- Check if a Conda environment is active and display its name.
local conda = os.getenv("CONDA_DEFAULT_ENV")
if conda then
text = conda
end
-- Check VIRTUAL_ENV and display its name.
local venv = os.getenv("VIRTUAL_ENV")
if venv then
text = venv
end
-- Check VIRTUAL_ENV_PROMPT and display its name.
local venv = os.getenv("VIRTUAL_ENV_PROMPT")
if venv then
text = venv
end
if text then
return text:gsub("\t\r\n", "")
end
end
local function time_func()
local format = os.getenv("PURE_TIME_FORMAT") or "%H:%M:%S"
local text = colors.time..os.date(format, os.time())..sgr()
return text
end
local function dist_func()
return "dist_replace"
end
-- If you want to add more modules, this is where to add them.
--
-- BUT FIRST MAKE A COPY OF THIS FILE, AND MODIFY THE COPY, NOT THE ORIGINAL
-- FILE. BECAUSE ANY CHANGES TO THE ORIGINAL FILE WILL BE LOST EACH TIME A
-- CLINK UPDATE IS INSTALLED.
local modules = {
-- Module Name Module Function
["execution_time"] = execution_time_func,
["git"] = git_func,
["host"] = host_func,
["path"] = path_func,
["prompt"] = prompt_func,
["user"] = user_func,
["virtualenv"] = virtualenv_func,
["time"] = time_func,
["dist"] = dist_func,
}
local function format_modules(list)
local t = {}
local prev
local dist_index
for _,m in ipairs(string.explode(list)) do
local func = modules[m]
if func then
local color = colors[m] or ""
local text = func()
if text then
local sep = " "
if m == "host" and prev == "user" then
sep = colors.host_at.."@"
end
if m == "dist" then
dist_index = #t + 1
end
table.insert(t, sep..color..text)
end
end
prev = m
end
if dist_index then
table.remove(t, dist_index)
local width = console.getwidth()
local cellcount = console.cellcount(table.concat(t):gsub("^%s+", ""))
table.insert(t, dist_index, string.rep(" ", width - cellcount))
end
return table.concat(t):gsub("^%s+", "")
end
local pureprompt = clink.promptfilter(5)
function pureprompt:filter() -- luacheck: no unused
local line1_modules = os.getenv("PURE_LINE1_MODULES") or "host path git execution_time dist time"
local line2_modules = os.getenv("PURE_LINE2_MODULES") or "virtualenv"
local line1 = format_modules(line1_modules)
local line2 = format_modules(line2_modules.." prompt")
local text = line1.."\n"..line2
return text
end
function pureprompt:transientfilter() -- luacheck: no unused
return format_modules("prompt")
end
local begin_duration
clink.onendedit(function(line)
if line:gsub("%s+$", "") == "" then
-- Don't measure empty commands.
begin_duration = nil
else
-- Begin a duration measurement.
begin_duration = os.clock()
end
last_duration = nil
last_exitcode = nil
end)
local last_cwd
local last_gitdir
clink.onbeginedit(function()
-- Discard cached git status if the cwd or repo changes.
local cwd = os.getcwd()
if last_cwd ~= cwd then
last_cwd = cwd
local gitdir = git.getgitdir()
if last_gitdir ~= gitdir then
last_gitdir = gitdir
last_gitstatus = nil
end
end
-- End a duration measurement.
if begin_duration then
last_duration = os.clock() - begin_duration
begin_duration = nil
end
-- Remember the exit code.
last_exitcode = os.geterrorlevel()
-- Update config options.
update_config()
end)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment