# Copyright Epic Games, Inc. All Rights Reserved. import os import sys import flow.cmd from pathlib import Path #------------------------------------------------------------------------------- class Cmd(object): def register_shells(self, registrar): registrar.add("cmd", _Shell) return super().register_shells(registrar) def run(self, env): if os.name != "nt": return super().run(env) # Give the user a convenient way to add customisations in to the session self.print_info("Customisation") home_dir = Path(self.get_home_dir()) tags = ( flow.cmd.text.grey("none"), flow.cmd.text.white("okay"), ) # These are really a no-op. It is here to hint to the user how they can # add their own channels candidate = home_dir / "channels" found = candidate.is_dir() print(tags[int(found)], candidate / "*") # Indicate to the user that there's a way to hook the boot process too candidate = home_dir / "hooks/boot.bat" found = candidate.is_file() print(tags[int(found)], candidate) # This is run just before the prompt is shown candidate = home_dir / "hooks/startup.bat" found = candidate.is_file() print(tags[int(found)], candidate) if found: self._user_script = candidate print() return super().run(env) #------------------------------------------------------------------------------- class _Shell(object): def __init__(self, system): self._system = system def get_system(self): return self._system def _add_clink_lua(self): system = self.get_system() working_dir = system.get_working_dir() lua_path = working_dir + "complete.clink.lua" if not system.is_path_stale(lua_path): return cmd_tree = system.get_command_tree() tree_root = cmd_tree.get_root_node() lua = open(lua_path, "w") lua.write("local commands = {") for name,_ in tree_root.read_children(): lua.write(f"'{name}',") lua.write("}\n") run_py_path = os.path.abspath(__file__ + "/../../core/system/run.py") cmd = rf'"{sys.executable}" -Xutf8 -Esu "{run_py_path}" "{working_dir}/manifest" $complete --daemon' cmd = cmd.replace("\\", "/") lua.write(f"local py_server_cmd = '{cmd}'") clink_lua = _get_clink_lua() lua.write(clink_lua) lua.close() def boot_shell(self, env, cookie, user_script): self._add_clink_lua() system = self.get_system() working_dir = system.get_working_dir() env["CLINK_PATH"] = working_dir env["DIRCMD"] = "/ogen" if prompt := env.get("FLOW_PROMPT", None): prompt = prompt.replace("\n", "\r") env["FLOW_PROMPT"] = prompt try: os.makedirs(os.path.dirname(cookie)) except: pass thefuzz_path = Path(__file__).parent / "cmd_thefuzz.bat" thefuzz_path = thefuzz_path.resolve() with open(cookie, "wt") as out: print(f"cd /d \"{os.getcwd()}\"", file=out) for key, value in env.read_changes(): value = value or "" print(fr'set "{key}={value}"', file=out) print(rf'doskey ff=fd $B fzf $B clip', file=out) print(rf'doskey qq="{thefuzz_path}" history', file=out) print(rf'doskey de="{thefuzz_path}" explore $*', file=out) print(rf'doskey dc="{thefuzz_path}" chdir $*', file=out) print(rf'doskey dc.="{thefuzz_path}" chdir .', file=out) print(rf'doskey dp="{thefuzz_path}" pushdir $*', file=out) print(rf'doskey dp.="{thefuzz_path}" pushdir .', file=out) print("clink_x64.exe inject", file=out) print("$tip.exe --nocrlf", file=out) if user_script: print(rf'call "{user_script}"', file=out) #------------------------------------------------------------------------------- def _get_clink_lua(): return r""" local py_server = io.popen2(py_server_cmd) for _, tree_root in ipairs(commands) do local arg_handler = function(index, line) py_server:write("\x01\n") py_server:write(tree_root.."\n") local n = line:getwordcount() for i = 2, n do py_server:write(line:getword(i).."\n") end local delim = line:getwordinfo(n).delim if delim ~= " " then py_server:write("\x03"..delim.."\n") end py_server:write("\x02\n") local ret = {} while true do match = py_server:read() if match == nil then return end if match == "\x01" then return ret end if match == "\x02" then return end table.insert(ret, match) end end clink.argmatcher(tree_root) :loop(1) :setflagprefix("-") :addarg(arg_handler) :addflags(arg_handler) end local cmd_generator = clink.generator(0) function cmd_generator:generate(line_state, match_builder) if line_state:getwordcount() ~= 1 then return end if line_state:getword(1) ~= "." then return end match_builder:setprefixincluded() for _, command in ipairs(commands) do if command:sub(1, 1) == "." then match_builder:addmatch(command) end end return true end function cmd_generator:getprefixlength(line_state) if line_state:getwordcount() ~= 1 then return end local prefix = line_state:getword(1):sub(1, 1) if prefix == "." then return 1 end return 0 end local cliff_prompt = clink.promptfilter(-493) function cliff_prompt:filter(prompt) prompt_override = os.getenv("FLOW_PROMPT") if prompt_override == nil then return prompt end py_server:write("\x01\n") py_server:write("$\n") py_server:write(prompt_override) py_server:write("\n\x02\n") prompt = nil while true do ret = py_server:read() if ret == nil then return end if ret == "\x01" then return prompt end if ret == "\x02" then return end if not prompt then prompt = ret else prompt = prompt.."\n"..ret end end end """