Skip to content

Commit 8ec4789

Browse files
committed
Fix #3020; hg prompt is slow.
Cmder's hg prompt didn't use async prompt filtering yet. Cmder's svn prompt only used async prompt filtering if a special config variable was set (the commit which contributed it seems to have misunderstood the git config settings for the git async prompt). This commit makes the following changes: 1. Adds async prompt filtering for hg. 2. Makes async prompt filtering for svn the default. 3. Removes the prompt_overrideSvnStatusOptIn variable. 4. Fixes a bug where any errors during `svn status` in the svn prompt accidentally show up in the terminal. 5. Fixes a bug where any errors during `hg branch` in the hg prompt turn into Lua errors. 6. Simplifies the code for colors in the hg and svn prompts. 7. Clean up the svn prompt code and make it consistent with the git and hg prompt code.
1 parent 43ab19a commit 8ec4789

File tree

2 files changed

+83
-74
lines changed

2 files changed

+83
-74
lines changed

vendor/clink.lua

Lines changed: 83 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
-- luacheck: globals uah_color cwd_color lamb_color clean_color dirty_color conflict_color unknown_color
88
-- luacheck: globals prompt_homeSymbol prompt_lambSymbol prompt_type prompt_useHomeSymbol prompt_useUserAtHost
99
-- luacheck: globals prompt_singleLine prompt_includeVersionControl
10-
-- luacheck: globals prompt_overrideGitStatusOptIn prompt_overrideSvnStatusOptIn
10+
-- luacheck: globals prompt_overrideGitStatusOptIn
1111
-- luacheck: globals clink io.popenyield os.isdir settings.get
1212

1313
-- At first, load the original clink.lua file
@@ -350,13 +350,8 @@ end
350350
-- @return {false|mercurial branch information}
351351
---
352352
local function get_hg_branch()
353-
-- Return the branch information. The default is to get just the
354-
-- branch name, but you could e.g. use the "hg-prompt" extension to
355-
-- get more information, such as any applied mq patches. Here's an
356-
-- example of that:
357-
-- local cmd = "hg prompt \"{branch}{status}{|{patch}}{update}\""
358-
local cmd = "hg branch 2>nul"
359-
local file = io.popen(cmd)
353+
-- Return the branch information.
354+
local file = io.popen("hg branch 2>nul")
360355
if not file then
361356
return false
362357
end
@@ -424,12 +419,33 @@ local function get_git_status()
424419
return { status = is_status, conflict = conflict_found }
425420
end
426421

422+
---
423+
-- Get the status of working dir
424+
-- @return {bool}
425+
---
426+
local function get_hg_status()
427+
-- The default is to just use the branch name, but you could e.g. use the
428+
-- "hg-prompt" extension to get more information, such as any applied mq
429+
-- patches. Here's an example of that:
430+
-- "hg prompt \"{branch}{status}{|{patch}}{update}\""
431+
local pipe = io_popenyield("hg status -amrd 2>&1")
432+
if not pipe then
433+
return { error = true }
434+
end
435+
436+
local output = pipe:read('*all')
437+
pipe:close()
438+
439+
local dirty = (output ~= nil and output ~= "")
440+
return { clean = not dirty }
441+
end
442+
427443
---
428444
-- Get the status of working dir
429445
-- @return {bool}
430446
---
431447
local function get_svn_status()
432-
local file = io_popenyield("svn status -q")
448+
local file = io_popenyield("svn status -q 2>nul")
433449
if not file then
434450
return { error = true }
435451
end
@@ -520,14 +536,6 @@ local function git_prompt_filter()
520536
return false
521537
end
522538

523-
-- Colors for git status
524-
local colors = {
525-
clean = get_clean_color(),
526-
dirty = get_dirty_color(),
527-
conflict = get_conflict_color(),
528-
nostatus = get_unknown_color()
529-
}
530-
531539
local git_dir = get_git_dir()
532540
local color
533541
if git_dir then
@@ -547,18 +555,19 @@ local function git_prompt_filter()
547555
local gitConflict = gitInfo.conflict
548556

549557
if gitStatus == nil then
550-
color = colors.nostatus
558+
color = get_unknown_color()
551559
elseif gitStatus then
552-
color = colors.clean
560+
color = get_clean_color()
553561
else
554-
color = colors.dirty
562+
color = get_dirty_color()
555563
end
556564

557565
if gitConflict then
558-
color = colors.conflict
566+
color = get_conflict_color()
559567
end
560568

561-
clink.prompt.value = gsub_plain(clink.prompt.value, "{git}", " "..color.."("..branch..")")
569+
local result = " "..color.."("..branch..")"
570+
clink.prompt.value = gsub_plain(clink.prompt.value, "{git}", result)
562571
return false
563572
end
564573
end
@@ -568,6 +577,18 @@ local function git_prompt_filter()
568577
return false
569578
end
570579

580+
local function get_hg_info_table()
581+
local info = clink_promptcoroutine(function ()
582+
return get_hg_status() or {}
583+
end)
584+
if not info then
585+
info = cached_info.hg_info or {}
586+
else
587+
cached_info.hg_info = info
588+
end
589+
return info
590+
end
591+
571592
local function hg_prompt_filter()
572593

573594
-- Don't do any hg processing if the prompt doesn't want to show hg info.
@@ -577,33 +598,34 @@ local function hg_prompt_filter()
577598

578599
local hg_dir = get_hg_dir()
579600
if hg_dir then
580-
-- Colors for mercurial status
581-
local colors = {
582-
clean = get_clean_color(),
583-
dirty = get_dirty_color(),
584-
nostatus = get_unknown_color()
585-
}
586-
local output = get_hg_branch()
587-
588-
-- strip the trailing newline from the branch name
589-
local n = #output
590-
while n > 0 and output:find("^%s", n) do n = n - 1 end
591-
local branch = output:sub(1, n)
601+
local output = get_hg_branch() or ""
602+
603+
-- strip the trailing spaces and newline from the branch name
604+
local branch = output:gsub("%s+$", "")
592605

593606
if branch ~= nil and
594607
string.sub(branch,1,7) ~= "abort: " and -- not an HG working copy
595608
(not string.find(branch, "is not recognized")) then -- 'hg' not in path
596-
local color = colors.clean
609+
-- If in a different repo or branch than last time, discard cached info
610+
if cached_info.hg_dir ~= hg_dir or cached_info.hg_branch ~= branch then
611+
cached_info.hg_info = nil
612+
cached_info.hg_dir = hg_dir
613+
cached_info.hg_branch = branch
614+
end
597615

598-
local pipe = io.popen("hg status -amrd 2>&1")
599-
if pipe then
600-
output = pipe:read('*all')
601-
pipe:close()
602-
if output ~= nil and output ~= "" then color = colors.dirty end
616+
local hgInfo = get_hg_info_table()
617+
618+
local color
619+
if not hgInfo or hgInfo.error then
620+
color = get_unknown_color()
621+
elseif hgInfo.clean then
622+
color = get_clean_color()
623+
else
624+
color = get_dirty_color()
603625
end
604626

605-
local result = color .. "(" .. branch .. ")"
606-
clink.prompt.value = gsub_plain(clink.prompt.value, "{hg}", " "..result)
627+
local result = " "..color.."("..branch..")"
628+
clink.prompt.value = gsub_plain(clink.prompt.value, "{hg}", result)
607629
return false
608630
end
609631
end
@@ -612,20 +634,25 @@ local function hg_prompt_filter()
612634
clink.prompt.value = gsub_plain(clink.prompt.value, "{hg}", "")
613635
end
614636

637+
local function get_svn_info_table()
638+
local info = clink_promptcoroutine(function ()
639+
return get_svn_status() or {}
640+
end)
641+
if not info then
642+
info = cached_info.svn_info or {}
643+
else
644+
cached_info.svn_info = info
645+
end
646+
return info
647+
end
648+
615649
local function svn_prompt_filter()
616650

617651
-- Don't do any svn processing if the prompt doesn't want to show svn info.
618652
if not clink.prompt.value:find("{svn}") then
619653
return false
620654
end
621655

622-
-- Colors for svn status
623-
local colors = {
624-
clean = get_clean_color(),
625-
dirty = get_dirty_color(),
626-
nostatus = get_unknown_color()
627-
}
628-
629656
local svn_dir = get_svn_dir()
630657
if svn_dir then
631658
-- if we're inside of svn repo then try to detect current branch
@@ -637,29 +664,16 @@ local function svn_prompt_filter()
637664
cached_info.svn_dir = svn_dir
638665
cached_info.svn_branch = branch
639666
end
640-
-- Get the svn status using coroutine if available and option is enabled. Otherwise use a blocking call
641-
local svnStatus
642-
if clink.promptcoroutine and io.popenyield and settings.get("prompt.async") and prompt_overrideSvnStatusOptIn then -- luacheck: no max line length
643-
svnStatus = clink_promptcoroutine(function ()
644-
return get_svn_status()
645-
end)
646-
-- If the status result is pending, use the cached version instead, otherwise store it to the cache
647-
if svnStatus == nil then
648-
svnStatus = cached_info.svn_info
649-
else
650-
cached_info.svn_info = svnStatus
651-
end
652-
else
653-
svnStatus = get_svn_status()
654-
end
667+
668+
local svnInfo = get_svn_info_table()
655669

656670
local color
657-
if not svnStatus or svnStatus.error then
658-
color = colors.nostatus
659-
elseif svnStatus.clean then
660-
color = colors.clean
671+
if not svnInfo or svnInfo.error then
672+
color = get_unknown_color()
673+
elseif svnInfo.clean then
674+
color = get_clean_color()
661675
else
662-
color = colors.dirty
676+
color = get_dirty_color()
663677
end
664678

665679
clink.prompt.value = gsub_plain(clink.prompt.value, "{svn}", " "..color.."("..branch..")")

vendor/cmder_prompt_config.lua.default

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -38,11 +38,6 @@ prompt_includeVersionControl = true
3838
-- NOTE: This only takes effect if using Clink v1.2.10 or higher.
3939
prompt_overrideGitStatusOptIn = false
4040

41-
-- OPTIONAL. If true then always ignore the cmder.status and cmder.cmdstatus svn config settings and run the svn prompt commands in the background.
42-
-- default is false
43-
-- NOTE: This only takes effect if using Clink v1.2.10 or higher.
44-
prompt_overrideSvnStatusOptIn = false
45-
4641
-- Prompt Attributes
4742
--
4843
-- Colors: https://github.com/cmderdev/cmder/wiki/Customization#list-of-colors

0 commit comments

Comments
 (0)