Merge pull request #3021 from chrisant996/fix_3020_hg_prompt_is_slow

Fix cmderdev/cmder#3020; hg prompt is slow.
This commit is contained in:
David Refoua
2025-11-07 20:22:25 +03:30
committed by GitHub
2 changed files with 82 additions and 77 deletions

154
vendor/clink.lua vendored
View File

@@ -7,7 +7,7 @@
-- luacheck: globals uah_color cwd_color lamb_color clean_color dirty_color conflict_color unknown_color -- luacheck: globals uah_color cwd_color lamb_color clean_color dirty_color conflict_color unknown_color
-- luacheck: globals prompt_homeSymbol prompt_lambSymbol prompt_type prompt_useHomeSymbol prompt_useUserAtHost -- luacheck: globals prompt_homeSymbol prompt_lambSymbol prompt_type prompt_useHomeSymbol prompt_useUserAtHost
-- luacheck: globals prompt_singleLine prompt_includeVersionControl -- luacheck: globals prompt_singleLine prompt_includeVersionControl
-- luacheck: globals prompt_overrideGitStatusOptIn prompt_overrideSvnStatusOptIn -- luacheck: globals prompt_overrideGitStatusOptIn
-- luacheck: globals clink io.popenyield os.isdir settings.get -- luacheck: globals clink io.popenyield os.isdir settings.get
-- At first, load the original clink.lua file -- At first, load the original clink.lua file
@@ -350,13 +350,8 @@ end
-- @return {false|mercurial branch information} -- @return {false|mercurial branch information}
--- ---
local function get_hg_branch() local function get_hg_branch()
-- Return the branch information. The default is to get just the -- Return the branch information.
-- branch name, but you could e.g. use the "hg-prompt" extension to local file = io.popen("hg branch 2>nul")
-- get more information, such as any applied mq patches. Here's an
-- example of that:
-- local cmd = "hg prompt \"{branch}{status}{|{patch}}{update}\""
local cmd = "hg branch 2>nul"
local file = io.popen(cmd)
if not file then if not file then
return false return false
end end
@@ -424,12 +419,33 @@ local function get_git_status()
return { status = is_status, conflict = conflict_found } return { status = is_status, conflict = conflict_found }
end end
---
-- Get the status of working dir
-- @return {bool}
---
local function get_hg_status()
-- The default is to just use the branch name, but you could e.g. use the
-- "hg-prompt" extension to get more information, such as any applied mq
-- patches. Here's an example of that:
-- "hg prompt \"{branch}{status}{|{patch}}{update}\""
local pipe = io_popenyield("hg status -amrd 2>&1")
if not pipe then
return { error = true }
end
local output = pipe:read('*all')
pipe:close()
local dirty = (output ~= nil and output ~= "")
return { clean = not dirty }
end
--- ---
-- Get the status of working dir -- Get the status of working dir
-- @return {bool} -- @return {bool}
--- ---
local function get_svn_status() local function get_svn_status()
local file = io_popenyield("svn status -q") local file = io_popenyield("svn status -q 2>nul")
if not file then if not file then
return { error = true } return { error = true }
end end
@@ -520,14 +536,6 @@ local function git_prompt_filter()
return false return false
end end
-- Colors for git status
local colors = {
clean = get_clean_color(),
dirty = get_dirty_color(),
conflict = get_conflict_color(),
nostatus = get_unknown_color()
}
local git_dir = get_git_dir() local git_dir = get_git_dir()
local color local color
if git_dir then if git_dir then
@@ -547,18 +555,19 @@ local function git_prompt_filter()
local gitConflict = gitInfo.conflict local gitConflict = gitInfo.conflict
if gitStatus == nil then if gitStatus == nil then
color = colors.nostatus color = get_unknown_color()
elseif gitStatus then elseif gitStatus then
color = colors.clean color = get_clean_color()
else else
color = colors.dirty color = get_dirty_color()
end end
if gitConflict then if gitConflict then
color = colors.conflict color = get_conflict_color()
end end
clink.prompt.value = gsub_plain(clink.prompt.value, "{git}", " "..color.."("..branch..")") local result = " "..color.."("..branch..")"
clink.prompt.value = gsub_plain(clink.prompt.value, "{git}", result)
return false return false
end end
end end
@@ -568,6 +577,18 @@ local function git_prompt_filter()
return false return false
end end
local function get_hg_info_table()
local info = clink_promptcoroutine(function ()
return get_hg_status() or {}
end)
if not info then
info = cached_info.hg_info or {}
else
cached_info.hg_info = info
end
return info
end
local function hg_prompt_filter() local function hg_prompt_filter()
-- Don't do any hg processing if the prompt doesn't want to show hg info. -- Don't do any hg processing if the prompt doesn't want to show hg info.
@@ -577,33 +598,30 @@ local function hg_prompt_filter()
local hg_dir = get_hg_dir() local hg_dir = get_hg_dir()
if hg_dir then if hg_dir then
-- Colors for mercurial status local branch = get_hg_branch()
local colors = { if branch and
clean = get_clean_color(),
dirty = get_dirty_color(),
nostatus = get_unknown_color()
}
local output = get_hg_branch()
-- strip the trailing newline from the branch name
local n = #output
while n > 0 and output:find("^%s", n) do n = n - 1 end
local branch = output:sub(1, n)
if branch ~= nil and
string.sub(branch,1,7) ~= "abort: " and -- not an HG working copy string.sub(branch,1,7) ~= "abort: " and -- not an HG working copy
(not string.find(branch, "is not recognized")) then -- 'hg' not in path (not string.find(branch, "is not recognized")) then -- 'hg' not in path
local color = colors.clean -- If in a different repo or branch than last time, discard cached info
if cached_info.hg_dir ~= hg_dir or cached_info.hg_branch ~= branch then
local pipe = io.popen("hg status -amrd 2>&1") cached_info.hg_info = nil
if pipe then cached_info.hg_dir = hg_dir
output = pipe:read('*all') cached_info.hg_branch = branch
pipe:close()
if output ~= nil and output ~= "" then color = colors.dirty end
end end
local result = color .. "(" .. branch .. ")" local hgInfo = get_hg_info_table()
clink.prompt.value = gsub_plain(clink.prompt.value, "{hg}", " "..result)
local color
if not hgInfo or hgInfo.error then
color = get_unknown_color()
elseif hgInfo.clean then
color = get_clean_color()
else
color = get_dirty_color()
end
local result = " "..color.."("..branch..")"
clink.prompt.value = gsub_plain(clink.prompt.value, "{hg}", result)
return false return false
end end
end end
@@ -612,6 +630,18 @@ local function hg_prompt_filter()
clink.prompt.value = gsub_plain(clink.prompt.value, "{hg}", "") clink.prompt.value = gsub_plain(clink.prompt.value, "{hg}", "")
end end
local function get_svn_info_table()
local info = clink_promptcoroutine(function ()
return get_svn_status() or {}
end)
if not info then
info = cached_info.svn_info or {}
else
cached_info.svn_info = info
end
return info
end
local function svn_prompt_filter() local function svn_prompt_filter()
-- Don't do any svn processing if the prompt doesn't want to show svn info. -- Don't do any svn processing if the prompt doesn't want to show svn info.
@@ -619,13 +649,6 @@ local function svn_prompt_filter()
return false return false
end end
-- Colors for svn status
local colors = {
clean = get_clean_color(),
dirty = get_dirty_color(),
nostatus = get_unknown_color()
}
local svn_dir = get_svn_dir() local svn_dir = get_svn_dir()
if svn_dir then if svn_dir then
-- if we're inside of svn repo then try to detect current branch -- if we're inside of svn repo then try to detect current branch
@@ -637,29 +660,16 @@ local function svn_prompt_filter()
cached_info.svn_dir = svn_dir cached_info.svn_dir = svn_dir
cached_info.svn_branch = branch cached_info.svn_branch = branch
end end
-- Get the svn status using coroutine if available and option is enabled. Otherwise use a blocking call
local svnStatus local svnInfo = get_svn_info_table()
if clink.promptcoroutine and io.popenyield and settings.get("prompt.async") and prompt_overrideSvnStatusOptIn then -- luacheck: no max line length
svnStatus = clink_promptcoroutine(function ()
return get_svn_status()
end)
-- If the status result is pending, use the cached version instead, otherwise store it to the cache
if svnStatus == nil then
svnStatus = cached_info.svn_info
else
cached_info.svn_info = svnStatus
end
else
svnStatus = get_svn_status()
end
local color local color
if not svnStatus or svnStatus.error then if not svnInfo or svnInfo.error then
color = colors.nostatus color = get_unknown_color()
elseif svnStatus.clean then elseif svnInfo.clean then
color = colors.clean color = get_clean_color()
else else
color = colors.dirty color = get_dirty_color()
end end
clink.prompt.value = gsub_plain(clink.prompt.value, "{svn}", " "..color.."("..branch..")") clink.prompt.value = gsub_plain(clink.prompt.value, "{svn}", " "..color.."("..branch..")")

View File

@@ -38,11 +38,6 @@ prompt_includeVersionControl = true
-- NOTE: This only takes effect if using Clink v1.2.10 or higher. -- NOTE: This only takes effect if using Clink v1.2.10 or higher.
prompt_overrideGitStatusOptIn = false prompt_overrideGitStatusOptIn = false
-- OPTIONAL. If true then always ignore the cmder.status and cmder.cmdstatus svn config settings and run the svn prompt commands in the background.
-- default is false
-- NOTE: This only takes effect if using Clink v1.2.10 or higher.
prompt_overrideSvnStatusOptIn = false
-- Prompt Attributes -- Prompt Attributes
-- --
-- Colors: https://github.com/cmderdev/cmder/wiki/Customization#list-of-colors -- Colors: https://github.com/cmderdev/cmder/wiki/Customization#list-of-colors