PageRenderTime 46ms CodeModel.GetById 17ms RepoModel.GetById 1ms app.codeStats 0ms

/cmder_mini/vendor/clink.lua

https://gitlab.com/MarcuSacramento/ferramentas
Lua | 257 lines | 149 code | 42 blank | 66 comment | 30 complexity | 1c70ddf7933d3e5ba03065ded0b4ff4e MD5 | raw file
  1. -- default script for clink, called by init.bat when injecting clink
  2. -- !!! THIS FILE IS OVERWRITTEN WHEN CMDER IS UPDATED
  3. -- !!! Use "%CMDER_ROOT%\config\<whatever>.lua" to add your lua startup scripts
  4. -- At first, load the original clink.lua file
  5. -- this is needed as we set the script path to this dir and therefore the original
  6. -- clink.lua is not loaded.
  7. local clink_lua_file = clink.get_env('CMDER_ROOT')..'\\vendor\\clink\\clink.lua'
  8. dofile(clink_lua_file)
  9. -- now add our own things...
  10. ---
  11. -- Setting the prompt in clink means that commands which rewrite the prompt do
  12. -- not destroy our own prompt. It also means that started cmds (or batch files
  13. -- which echo) don't get the ugly '{lamb}' shown.
  14. ---
  15. function set_prompt_filter()
  16. -- orig: $E[1;32;40m$P$S{git}{hg}$S$_$E[1;30;40m{lamb}$S$E[0m
  17. -- color codes: "\x1b[1;37;40m"
  18. cwd = clink.get_cwd()
  19. prompt = "\x1b[1;32;40m{cwd} {git}{hg} \n\x1b[1;30;40m{lamb} \x1b[0m"
  20. new_value = string.gsub(prompt, "{cwd}", cwd)
  21. clink.prompt.value = string.gsub(new_value, "{lamb}", "λ")
  22. end
  23. ---
  24. -- Resolves closest directory location for specified directory.
  25. -- Navigates subsequently up one level and tries to find specified directory
  26. -- @param {string} path Path to directory will be checked. If not provided
  27. -- current directory will be used
  28. -- @param {string} dirname Directory name to search for
  29. -- @return {string} Path to specified directory or nil if such dir not found
  30. local function get_dir_contains(path, dirname)
  31. -- return parent path for specified entry (either file or directory)
  32. local function pathname(path)
  33. local prefix = ""
  34. local i = path:find("[\\/:][^\\/:]*$")
  35. if i then
  36. prefix = path:sub(1, i-1)
  37. end
  38. return prefix
  39. end
  40. -- Navigates up one level
  41. local function up_one_level(path)
  42. if path == nil then path = '.' end
  43. if path == '.' then path = clink.get_cwd() end
  44. return pathname(path)
  45. end
  46. -- Checks if provided directory contains git directory
  47. local function has_specified_dir(path, specified_dir)
  48. if path == nil then path = '.' end
  49. local found_dirs = clink.find_dirs(path..'/'..specified_dir)
  50. if #found_dirs > 0 then return true end
  51. return false
  52. end
  53. -- Set default path to current directory
  54. if path == nil then path = '.' end
  55. -- If we're already have .git directory here, then return current path
  56. if has_specified_dir(path, dirname) then
  57. return path..'/'..dirname
  58. else
  59. -- Otherwise go up one level and make a recursive call
  60. local parent_path = up_one_level(path)
  61. if parent_path == path then
  62. return nil
  63. else
  64. return get_dir_contains(parent_path, dirname)
  65. end
  66. end
  67. end
  68. local function get_hg_dir(path)
  69. return get_dir_contains(path, '.hg')
  70. end
  71. -- adapted from from clink-completions' git.lua
  72. local function get_git_dir(path)
  73. -- return parent path for specified entry (either file or directory)
  74. local function pathname(path)
  75. local prefix = ""
  76. local i = path:find("[\\/:][^\\/:]*$")
  77. if i then
  78. prefix = path:sub(1, i-1)
  79. end
  80. return prefix
  81. end
  82. -- Checks if provided directory contains git directory
  83. local function has_git_dir(dir)
  84. return #clink.find_dirs(dir..'/.git') > 0 and dir..'/.git'
  85. end
  86. local function has_git_file(dir)
  87. local gitfile = io.open(dir..'/.git')
  88. if not gitfile then return false end
  89. local git_dir = gitfile:read():match('gitdir: (.*)')
  90. gitfile:close()
  91. return git_dir and dir..'/'..git_dir
  92. end
  93. -- Set default path to current directory
  94. if not path or path == '.' then path = clink.get_cwd() end
  95. -- Calculate parent path now otherwise we won't be
  96. -- able to do that inside of logical operator
  97. local parent_path = pathname(path)
  98. return has_git_dir(path)
  99. or has_git_file(path)
  100. -- Otherwise go up one level and make a recursive call
  101. or (parent_path ~= path and get_git_dir(parent_path) or nil)
  102. end
  103. ---
  104. -- Find out current branch
  105. -- @return {false|mercurial branch name}
  106. ---
  107. function get_hg_branch()
  108. for line in io.popen("hg branch 2>nul"):lines() do
  109. local m = line:match("(.+)$")
  110. if m then
  111. return m
  112. end
  113. end
  114. return false
  115. end
  116. ---
  117. -- Get the status of working dir
  118. -- @return {bool}
  119. ---
  120. function get_hg_status()
  121. for line in io.popen("hg status"):lines() do
  122. return false
  123. end
  124. return true
  125. end
  126. function hg_prompt_filter()
  127. -- Colors for mercurial status
  128. local colors = {
  129. clean = "\x1b[1;37;40m",
  130. dirty = "\x1b[31;1m",
  131. }
  132. if get_hg_dir() then
  133. -- if we're inside of mercurial repo then try to detect current branch
  134. local branch = get_hg_branch()
  135. if branch then
  136. -- Has branch => therefore it is a mercurial folder, now figure out status
  137. if get_hg_status() then
  138. color = colors.clean
  139. else
  140. color = colors.dirty
  141. end
  142. clink.prompt.value = string.gsub(clink.prompt.value, "{hg}", color.."("..branch..")")
  143. return false
  144. end
  145. end
  146. -- No mercurial present or not in mercurial file
  147. clink.prompt.value = string.gsub(clink.prompt.value, "{hg}", "")
  148. return false
  149. end
  150. ---
  151. -- Find out current branch
  152. -- @return {nil|git branch name}
  153. ---
  154. function get_git_branch(git_dir)
  155. local git_dir = git_dir or get_git_dir()
  156. -- If git directory not found then we're probably outside of repo
  157. -- or something went wrong. The same is when head_file is nil
  158. local head_file = git_dir and io.open(git_dir..'/HEAD')
  159. if not head_file then return end
  160. local HEAD = head_file:read()
  161. head_file:close()
  162. -- if HEAD matches branch expression, then we're on named branch
  163. -- otherwise it is a detached commit
  164. local branch_name = HEAD:match('ref: refs/heads/(.+)')
  165. return branch_name or 'HEAD detached at '..HEAD:sub(1, 7)
  166. end
  167. ---
  168. -- Get the status of working dir
  169. -- @return {bool}
  170. ---
  171. function get_git_status()
  172. for line in io.popen("git status --porcelain 2>nul"):lines() do
  173. return false
  174. end
  175. return true
  176. end
  177. function git_prompt_filter()
  178. -- Colors for git status
  179. local colors = {
  180. clean = "\x1b[1;37;40m",
  181. dirty = "\x1b[31;1m",
  182. }
  183. local git_dir = get_git_dir()
  184. if git_dir then
  185. -- if we're inside of git repo then try to detect current branch
  186. local branch = get_git_branch(git_dir)
  187. if branch then
  188. -- Has branch => therefore it is a git folder, now figure out status
  189. if get_git_status() then
  190. color = colors.clean
  191. else
  192. color = colors.dirty
  193. end
  194. clink.prompt.value = string.gsub(clink.prompt.value, "{git}", color.."("..branch..")")
  195. return false
  196. end
  197. end
  198. -- No git present or not in git file
  199. clink.prompt.value = string.gsub(clink.prompt.value, "{git}", "")
  200. return false
  201. end
  202. -- insert the set_prompt at the very beginning so that it runs first
  203. clink.prompt.register_filter(set_prompt_filter, 1)
  204. clink.prompt.register_filter(hg_prompt_filter, 50)
  205. clink.prompt.register_filter(git_prompt_filter, 50)
  206. local completions_dir = clink.get_env('CMDER_ROOT')..'/vendor/clink-completions/'
  207. for _,lua_module in ipairs(clink.find_files(completions_dir..'*.lua')) do
  208. -- Skip files that starts with _. This could be useful if some files should be ignored
  209. if not string.match(lua_module, '^_.*') then
  210. local filename = completions_dir..lua_module
  211. -- use dofile instead of require because require caches loaded modules
  212. -- so config reloading using Alt-Q won't reload updated modules.
  213. dofile(filename)
  214. end
  215. end