cmder/vendor/cmder.lua
Jan Schulz 567889e69f Fix: don't garble the input line for long lines in git projects
If having a long line of input in histroy, which went on into the
second row and using <up> to get back to it, you got the effect
that the input was split over three lines: "text, empty, text",
but using the arrows do move to the front of the first line was
moving the cursor in the second (empty) row. You could change
the text, but you needed to do it "in the dark".  No idea why
s/os.execute/is.popen/ fixes this, but it does.

Partly adresses https://github.com/cmderdev/cmder/issues/749
2015-12-04 19:57:08 +01:00

202 lines
6.0 KiB
Lua

function lambda_prompt_filter()
clink.prompt.value = string.gsub(clink.prompt.value, "{lamb}", "λ")
end
---
-- Resolves closest directory location for specified directory.
-- Navigates subsequently up one level and tries to find specified directory
-- @param {string} path Path to directory will be checked. If not provided
-- current directory will be used
-- @param {string} dirname Directory name to search for
-- @return {string} Path to specified directory or nil if such dir not found
local function get_dir_contains(path, dirname)
-- return parent path for specified entry (either file or directory)
local function pathname(path)
local prefix = ""
local i = path:find("[\\/:][^\\/:]*$")
if i then
prefix = path:sub(1, i-1)
end
return prefix
end
-- Navigates up one level
local function up_one_level(path)
if path == nil then path = '.' end
if path == '.' then path = clink.get_cwd() end
return pathname(path)
end
-- Checks if provided directory contains git directory
local function has_specified_dir(path, specified_dir)
if path == nil then path = '.' end
local found_dirs = clink.find_dirs(path..'/'..specified_dir)
if #found_dirs > 0 then return true end
return false
end
-- Set default path to current directory
if path == nil then path = '.' end
-- If we're already have .git directory here, then return current path
if has_specified_dir(path, dirname) then
return path..'/'..dirname
else
-- Otherwise go up one level and make a recursive call
local parent_path = up_one_level(path)
if parent_path == path then
return nil
else
return get_dir_contains(parent_path, dirname)
end
end
end
local function get_hg_dir(path)
return get_dir_contains(path, '.hg')
end
local function get_git_dir(path)
return get_dir_contains(path, '.git')
end
---
-- Find out current branch
-- @return {false|mercurial branch name}
---
function get_hg_branch()
for line in io.popen("hg branch 2>nul"):lines() do
local m = line:match("(.+)$")
if m then
return m
end
end
return false
end
---
-- Get the status of working dir
-- @return {bool}
---
function get_hg_status()
for line in io.popen("hg status"):lines() do
return false
end
return true
end
function hg_prompt_filter()
-- Colors for mercurial status
local colors = {
clean = "\x1b[1;37;40m",
dirty = "\x1b[31;1m",
}
if get_hg_dir() then
-- if we're inside of mercurial repo then try to detect current branch
local branch = get_hg_branch()
if branch then
-- Has branch => therefore it is a mercurial folder, now figure out status
if get_hg_status() then
color = colors.clean
else
color = colors.dirty
end
clink.prompt.value = string.gsub(clink.prompt.value, "{hg}", color.."("..branch..")")
return false
end
end
-- No mercurial present or not in mercurial file
clink.prompt.value = string.gsub(clink.prompt.value, "{hg}", "")
return false
end
---
-- Find out current branch
-- @return {nil|git branch name}
---
function get_git_branch(git_dir)
local git_dir = git_dir or get_git_dir()
-- If git directory not found then we're probably outside of repo
-- or something went wrong. The same is when head_file is nil
local head_file = git_dir and io.open(git_dir..'/HEAD')
if not head_file then return end
local HEAD = head_file:read()
head_file:close()
-- if HEAD matches branch expression, then we're on named branch
-- otherwise it is a detached commit
local branch_name = HEAD:match('ref: refs/heads/(.+)')
return branch_name or 'HEAD detached at '..HEAD:sub(1, 7)
end
---
-- Get the status of working dir
-- @return {bool}
---
function get_git_status()
return io.popen("git diff --quiet --ignore-submodules HEAD 2>nul")
end
function git_prompt_filter()
-- Colors for git status
local colors = {
clean = "\x1b[1;37;40m",
dirty = "\x1b[31;1m",
}
local git_dir = get_git_dir()
if git_dir then
-- if we're inside of git repo then try to detect current branch
local branch = get_git_branch(git_dir)
if branch then
-- Has branch => therefore it is a git folder, now figure out status
if get_git_status() then
color = colors.clean
else
color = colors.dirty
end
clink.prompt.value = string.gsub(clink.prompt.value, "{git}", color.."("..branch..")")
return false
end
end
-- No git present or not in git file
clink.prompt.value = string.gsub(clink.prompt.value, "{git}", "")
return false
end
clink.prompt.register_filter(lambda_prompt_filter, 40)
clink.prompt.register_filter(hg_prompt_filter, 50)
clink.prompt.register_filter(git_prompt_filter, 50)
local completions_dir = clink.get_env('CMDER_ROOT')..'/vendor/clink-completions/'
for _,lua_module in ipairs(clink.find_files(completions_dir..'*.lua')) do
-- Skip files that starts with _. This could be useful if some files should be ignored
if not string.match(lua_module, '^_.*') then
local filename = completions_dir..lua_module
-- use dofile instead of require because require caches loaded modules
-- so config reloading using Alt-Q won't reload updated modules.
dofile(filename)
end
end
-- now do the same for all lua files in config which do not start with '_'
local user_config_dir = clink.get_env('CMDER_ROOT')..'\\config\\'
for _,lua_module in ipairs(clink.find_files(user_config_dir..'*.lua')) do
-- Skip files that starts with _. This could be useful if some files should be ignored
if not string.match(lua_module, '^_.*') then
local filename = user_config_dir..lua_module
dofile(filename)
end
end