mirror of
https://github.com/cmderdev/cmder.git
synced 2024-11-10 09:49:12 +08:00
Fix #2859; script error when cwd name contains %
The `string.gsub()` function in Lua always uses Lua patterns (which are similar to regular expressions). Cmder's custom prompt wants to perform simple plain text find/replace operations on strings. `string.gsub()` is the right Lua function for that, but since it always uses Lua patterns it's necessary to apply escaping to the input strings otherwise they can get misinterpreted and cause runtime errors. For example, if the current working directory name contains a percent sign, such as literally "My%20Home". This change fixes that. It introduces a helper function `gsub_plain()` which behaves like `string.gsub()` but applies appropriate escaping to convert the plain text input strings into the corresponding Lua patterns so that it can achieve plain text find/replace operations. It also introduces separate helper functions for escaping the `find` and `replace` parameters for `string.gsub()`, since they have different escaping rules.
This commit is contained in:
parent
e9750ab73d
commit
84ee96c64f
58
vendor/clink.lua
vendored
58
vendor/clink.lua
vendored
@ -51,11 +51,37 @@ local function get_unknown_color()
|
|||||||
end
|
end
|
||||||
|
|
||||||
---
|
---
|
||||||
-- Makes a string safe to use as the replacement in string.gsub
|
-- Escapes special characters in a string.gsub `find` parameter, so that it
|
||||||
|
-- can be matched as a literal plain text string, i.e. disable Lua pattern
|
||||||
|
-- matching. See "Patterns" (https://www.lua.org/manual/5.2/manual.html#6.4.1).
|
||||||
|
-- @param {string} text Text to escape
|
||||||
|
-- @returns {string} Escaped text
|
||||||
---
|
---
|
||||||
local function verbatim(s)
|
local function escape_gsub_find_arg(text)
|
||||||
s = string.gsub(s, "%%", "%%%%")
|
return text and text:gsub("([-+*?.%%()%[%]$^])", "%%%1") or ""
|
||||||
return s
|
end
|
||||||
|
|
||||||
|
---
|
||||||
|
-- Escapes special characters in a string.gsub `replace` parameter, so that it
|
||||||
|
-- can be replaced as a literal plain text string, i.e. disable Lua pattern
|
||||||
|
-- matching. See "Patterns" (https://www.lua.org/manual/5.2/manual.html#6.4.1).
|
||||||
|
-- @param {string} text Text to escape
|
||||||
|
-- @returns {string} Escaped text
|
||||||
|
---
|
||||||
|
local function escape_gsub_replace_arg(text)
|
||||||
|
return text and text:gsub("%%", "%%%%") or ""
|
||||||
|
end
|
||||||
|
|
||||||
|
---
|
||||||
|
-- Perform string.sub, but disable Lua pattern matching and just treat both
|
||||||
|
-- the `find` and `replace` parameters as a literal plain text replacement.
|
||||||
|
-- @param {string} str Text in which to perform find and replace
|
||||||
|
-- @param {string} find Text to find (plain text; not a Lua pattern)
|
||||||
|
-- @param {string} replace Replacement text (plain text; not a Lua pattern)
|
||||||
|
-- @returns {string} Copy of the input `str` with `find` replaced by `replace`
|
||||||
|
---
|
||||||
|
local function gsub_plain(str, find, replace)
|
||||||
|
return string.gsub(str, escape_gsub_find_arg(find), escape_gsub_replace_arg(replace))
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Extracts only the folder name from the input Path
|
-- Extracts only the folder name from the input Path
|
||||||
@ -153,7 +179,7 @@ local function set_prompt_filter()
|
|||||||
end
|
end
|
||||||
|
|
||||||
if prompt_useHomeSymbol and string.find(cwd, clink.get_env("HOME")) then
|
if prompt_useHomeSymbol and string.find(cwd, clink.get_env("HOME")) then
|
||||||
cwd = string.gsub(cwd, clink.get_env("HOME"), prompt_homeSymbol)
|
cwd = gsub_plain(cwd, clink.get_env("HOME"), prompt_homeSymbol)
|
||||||
end
|
end
|
||||||
|
|
||||||
local uah = ''
|
local uah = ''
|
||||||
@ -176,14 +202,14 @@ local function set_prompt_filter()
|
|||||||
local version_control = prompt_includeVersionControl and "{git}{hg}{svn}" or ""
|
local version_control = prompt_includeVersionControl and "{git}{hg}{svn}" or ""
|
||||||
|
|
||||||
local prompt = "{uah}{cwd}" .. version_control .. cr .. get_lamb_color() .. "{env}{lamb}\x1b[0m "
|
local prompt = "{uah}{cwd}" .. version_control .. cr .. get_lamb_color() .. "{env}{lamb}\x1b[0m "
|
||||||
prompt = string.gsub(prompt, "{uah}", uah)
|
prompt = gsub_plain(prompt, "{uah}", uah)
|
||||||
prompt = string.gsub(prompt, "{cwd}", cwd)
|
prompt = gsub_plain(prompt, "{cwd}", cwd)
|
||||||
prompt = string.gsub(prompt, "{env}", env)
|
prompt = gsub_plain(prompt, "{env}", env)
|
||||||
clink.prompt.value = string.gsub(prompt, "{lamb}", prompt_lambSymbol)
|
clink.prompt.value = gsub_plain(prompt, "{lamb}", prompt_lambSymbol)
|
||||||
end
|
end
|
||||||
|
|
||||||
local function percent_prompt_filter()
|
local function percent_prompt_filter()
|
||||||
clink.prompt.value = string.gsub(clink.prompt.value, "{percent}", "%%")
|
clink.prompt.value = gsub_plain(clink.prompt.value, "{percent}", "%")
|
||||||
end
|
end
|
||||||
|
|
||||||
---
|
---
|
||||||
@ -532,13 +558,13 @@ local function git_prompt_filter()
|
|||||||
color = colors.conflict
|
color = colors.conflict
|
||||||
end
|
end
|
||||||
|
|
||||||
clink.prompt.value = string.gsub(clink.prompt.value, "{git}", " "..color.."("..verbatim(branch)..")")
|
clink.prompt.value = gsub_plain(clink.prompt.value, "{git}", " "..color.."("..branch..")")
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- No git present or not in git file
|
-- No git present or not in git file
|
||||||
clink.prompt.value = string.gsub(clink.prompt.value, "{git}", "")
|
clink.prompt.value = gsub_plain(clink.prompt.value, "{git}", "")
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -577,13 +603,13 @@ local function hg_prompt_filter()
|
|||||||
end
|
end
|
||||||
|
|
||||||
local result = color .. "(" .. branch .. ")"
|
local result = color .. "(" .. branch .. ")"
|
||||||
clink.prompt.value = string.gsub(clink.prompt.value, "{hg}", " "..verbatim(result))
|
clink.prompt.value = gsub_plain(clink.prompt.value, "{hg}", " "..result)
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- No hg present or not in hg repo
|
-- No hg present or not in hg repo
|
||||||
clink.prompt.value = string.gsub(clink.prompt.value, "{hg}", "")
|
clink.prompt.value = gsub_plain(clink.prompt.value, "{hg}", "")
|
||||||
end
|
end
|
||||||
|
|
||||||
local function svn_prompt_filter()
|
local function svn_prompt_filter()
|
||||||
@ -636,13 +662,13 @@ local function svn_prompt_filter()
|
|||||||
color = colors.dirty
|
color = colors.dirty
|
||||||
end
|
end
|
||||||
|
|
||||||
clink.prompt.value = string.gsub(clink.prompt.value, "{svn}", " "..color.."("..verbatim(branch)..")")
|
clink.prompt.value = gsub_plain(clink.prompt.value, "{svn}", " "..color.."("..branch..")")
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- No svn present or not in svn file
|
-- No svn present or not in svn file
|
||||||
clink.prompt.value = string.gsub(clink.prompt.value, "{svn}", "")
|
clink.prompt.value = gsub_plain(clink.prompt.value, "{svn}", "")
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user