JanDeDobbeleer / oh-my-posh

The most customisable and low-latency cross platform/shell prompt renderer
https://ohmyposh.dev
MIT License
16.79k stars 2.35k forks source link

Error with Windows Command Prompt & CLink: "'C:/Program' is not recognized as an internal or external command, operable program or batch file." #1852

Closed RonAmihai closed 2 years ago

RonAmihai commented 2 years ago

Code of Conduct

What happened?

I'm using the latest version (7.30.0) on Windows 11 (build 22000.527) with Windows Terminal. I had recently set up CMD for some legacy usage, so I've installed CLink and tried to set up Oh-My-Posh with it.

It looks like OMP + CMD has an escape-path-characters issue (similar to the one OMP + Git Bash for Windows had).

I've created the following Clink Lua script (inside Clink's default scripts folder, aka C:\Program Files (x86)\clink):

load(io.popen('oh-my-posh --config="~/cli-theme.omp.json" --init --shell cmd'):read("*a"))()

And whenever starting a CMD session, I'm getting the following error:

'C:/Program' is not recognized as an internal or external command,
operable program or batch file.
'C:/Program' is not recognized as an internal or external command,
operable program or batch file.

Manual Fix

Creating a soft link to oh-my-posh.exe in a path without spaces (for example: C:/Utils/oh-my-posh.exe) and changing the CLink's Lua script:

load(io.popen('C:/Utils/oh-my-posh.exe --config="~/cli-theme.omp.json" --init --shell cmd'):read("*a"))()

Probably removing oh-my-posh and reinstalling it to a path without spaces (for example: "C:\oh-my-posh") should also solve the issue. But haven't tried.

Theme

aliens theme

What OS are you seeing the problem on?

Windows

Which shell are you using?

other (please specify)

Log output

Version: 7.30.0

Segments:

ConsoleTitle(false) -   0 ms -
session(true)  -   0 ms -  ronam@RON-AM-PC 
path(true)     -   0 ms -  ~
shell(true)    -   0 ms -  uni
text(true)     -   0 ms -  no config
exit(true)     -   0 ms -  

Run duration: 2.1717ms

Cache path: C:\Users\ronam\AppData\Local\oh-my-posh

Logs:

2022/03/01 20:06:55 Args duration: 0s, args:
2022/03/01 20:06:55 Args duration: 0s, args:
2022/03/01 20:06:55 Args duration: 0s, args:
2022/03/01 20:06:55 Shell duration: 0s, args:
2022/03/01 20:06:55 debug: Getenv

2022/03/01 20:06:55 Getenv duration: 0s, args: OMP_CACHE_DISABLED
2022/03/01 20:06:55 debug: Pwd
C:\Users\ronam
2022/03/01 20:06:55 Pwd duration: 0s, args:
2022/03/01 20:06:55 debug: Home
C:\Users\ronam
2022/03/01 20:06:55 PathSeparator duration: 0s, args:
2022/03/01 20:06:55 PathSeparator duration: 0s, args:
2022/03/01 20:06:55 debug: Pwd
C:\Users\ronam
2022/03/01 20:06:55 Pwd duration: 0s, args:
2022/03/01 20:06:55 debug: Home
C:\Users\ronam
2022/03/01 20:06:55 debug: Getenv

2022/03/01 20:06:55 Getenv duration: 0s, args: SSH_CONNECTION
2022/03/01 20:06:55 debug: Getenv

2022/03/01 20:06:55 Getenv duration: 0s, args: SSH_CLIENT
2022/03/01 20:06:55 Root duration: 0s, args:
2022/03/01 20:06:55 Shell duration: 0s, args:
2022/03/01 20:06:55 ErrorCode duration: 0s, args:
2022/03/01 20:06:55 IsWsl duration: 0s, args:
2022/03/01 20:06:55 debug: Pwd
C:\Users\ronam
2022/03/01 20:06:55 Pwd duration: 0s, args:
2022/03/01 20:06:55 debug: Home
C:\Users\ronam
2022/03/01 20:06:55 PathSeparator duration: 0s, args:
2022/03/01 20:06:55 PathSeparator duration: 0s, args:
2022/03/01 20:06:55 User duration: 0s, args:
2022/03/01 20:06:55 Host duration: 0s, args:
2022/03/01 20:06:55 GOOS duration: 0s, args:
2022/03/01 20:06:55 TemplateCache duration: 548.8µs, args:
2022/03/01 20:06:55 debug: Pwd
C:\Users\ronam
2022/03/01 20:06:55 Pwd duration: 0s, args:
2022/03/01 20:06:55 debug: Home
C:\Users\ronam
2022/03/01 20:06:55 debug: Pwd
C:\Users\ronam
2022/03/01 20:06:55 Pwd duration: 0s, args:
2022/03/01 20:06:55 Args duration: 0s, args:
2022/03/01 20:06:55 debug: Pwd
C:\Users\ronam
2022/03/01 20:06:55 Pwd duration: 0s, args:
2022/03/01 20:06:55 debug: Home
C:\Users\ronam
2022/03/01 20:06:55 GOOS duration: 0s, args:
2022/03/01 20:06:55 GOOS duration: 0s, args:
2022/03/01 20:06:55 PathSeparator duration: 0s, args:
2022/03/01 20:06:55 PathSeparator duration: 0s, args:
2022/03/01 20:06:55 PathSeparator duration: 0s, args:
2022/03/01 20:06:55 GOOS duration: 0s, args:
2022/03/01 20:06:55 IsWsl duration: 0s, args:
2022/03/01 20:06:55 StackCount duration: 0s, args:
2022/03/01 20:06:55 TemplateCache duration: 0s, args:
2022/03/01 20:06:55 debug: Pwd
C:\Users\ronam
2022/03/01 20:06:55 Pwd duration: 0s, args:
2022/03/01 20:06:55 debug: Home
C:\Users\ronam
2022/03/01 20:06:55 Shell duration: 0s, args:
2022/03/01 20:06:55 TemplateCache duration: 0s, args:
2022/03/01 20:06:55 debug: Pwd
C:\Users\ronam
2022/03/01 20:06:55 Pwd duration: 0s, args:
2022/03/01 20:06:55 debug: Home
C:\Users\ronam
2022/03/01 20:06:55 TemplateCache duration: 0s, args:
2022/03/01 20:06:55 debug: Pwd
C:\Users\ronam
2022/03/01 20:06:55 Pwd duration: 0s, args:
2022/03/01 20:06:55 debug: Home
C:\Users\ronam
2022/03/01 20:06:55 ErrorCode duration: 0s, args:
2022/03/01 20:06:55 TemplateCache duration: 0s, args:
2022/03/01 20:06:55 TemplateCache duration: 0s, args:
2022/03/01 20:06:55 debug: Getenv
C:\Users\ronam\AppData\Local
2022/03/01 20:06:55 Getenv duration: 0s, args: LOCALAPPDATA
2022/03/01 20:06:55 CachePath duration: 544.9µs, args:

'C:/Program' is not recognized as an internal or external command,
operable program or batch file.
'C:/Program' is not recognized as an internal or external command,
operable program or batch file.
JanDeDobbeleer commented 2 years ago

@RonAmihai I'm not the expert here as Lua is still some voodoo magic every time I read it.

@chrisant996 any clue on how to correctly resolve this? I tried and failed gracefully. We set those values here:

local function omp_exe()
    return [[::OMP::]]
end

local function omp_config()
    return [[::CONFIG::]]
end

But I have no idea where and how I can/need to add enclosing quotes (if that's the correct solution, the internet does point me in that direction).

JanDeDobbeleer commented 2 years ago

The above fix doesn't work. This shouldn't be this hard but here I am 😆

chrisant996 commented 2 years ago

The [[string]] syntax in Lua is the same as "string", except that [[ ]] means "do not treat \ as an escape character".

The [[::OMP::]] makes it so OMP's ReplaceAll here will work even if the input path contains backslashes.

The change https://github.com/JanDeDobbeleer/oh-my-posh/commit/23704f970e02d6d0d37a2a90867eb7bda4cc440f puts quotes around the entire command line, which tells CMD.EXE to find and execute a file named literally "oh-my-posh.exe --millis". The quotes need to be only around the executable name.

E.g.

In os_clock_millis():

-         return io.popen(omp_exe().." --millis"):read("*n")
+         return io.popen(string.format('"%s" --millis', omp_exe()):read("*n")

And in get_posh_prompt(): (The change is %s --> "%s" inside the string.)

-     local prompt_exe = string.format('%s --shell=cmd --config="%s" %s %s --rprompt=%s', omp_exe(), omp_config(), execution_time_option(), error_level_option(), rprompt)
+     local prompt_exe = string.format('"%s" --shell=cmd --config="%s" %s %s --rprompt=%s', omp_exe(), omp_config(), execution_time_option(), error_level_option(), rprompt)
chrisant996 commented 2 years ago

But I have no idea where and how I can/need to add enclosing quotes (if that's the correct solution, the internet does point me in that direction).

Alternatively, you could use [["::OMP::"]] and [["::CONFIG::"]]. Which, actually, is probably much simpler. 🙂

JanDeDobbeleer commented 2 years ago

Alternatively, you could use [["::OMP::"]] and [["::CONFIG::"]]. Which, actually, is probably much simpler. 🙂

I tried that, didn't work. Will give your first comment a whirl! 🙏🏻

JanDeDobbeleer commented 2 years ago

@chrisant996 the first comment also doesn't do the trick:

diff --git a/src/engine/init/omp.lua b/src/engine/init/omp.lua
index e8032f7f..cd34dcce 100644
--- a/src/engine/init/omp.lua
+++ b/src/engine/init/omp.lua
@@ -19,7 +19,8 @@ local function os_clock_millis()
     if (clink.version_encoded or 0) >= 10020030 then
         return math.floor(os.clock() * 1000)
     else
-        return io.popen(omp_exe().." --millis"):read("*n")
+        local prompt_exe = string.format('"%s" --millis', omp_exe())
+        return io.popen(prompt_exe):read("*n")
     end
 end

@@ -55,7 +56,7 @@ local function error_level_option()
 end

 local function get_posh_prompt(rprompt)
-    local prompt_exe = string.format('%s --shell=cmd --config="%s" %s %s --rprompt=%s', omp_exe(), omp_config(), execution_time_option(), error_level_option(), rprompt)
+    local prompt_exe = string.format('"%s" --shell=cmd --config="%s" %s %s --rprompt=%s', omp_exe(), omp_config(), execution_time_option(), error_level_option(), rprompt)
     prompt = io.popen(prompt_exe):read("*a")
     return prompt
 end
@@ -68,7 +69,7 @@ function p:rightfilter(prompt)
     if tip_word == nil then
         return get_posh_prompt(true), false
     end
-    local prompt_exe = string.format('%s --shell=cmd --config="%s" --command="%s"', omp_exe(), omp_config(), tip_word)
+    local prompt_exe = string.format('"%s" --shell=cmd --config="%s" --command="%s"', omp_exe(), omp_config(), tip_word)
     tooltip = io.popen(prompt_exe):read("*a")
     if tooltip ~= "" then
         return tooltip, false
@@ -76,7 +77,7 @@ function p:rightfilter(prompt)
     return get_posh_prompt(true), false
 end
 function p:transientfilter(prompt)
-    local prompt_exe = string.format('%s --shell=cmd --config="%s" --print-transient', omp_exe(), omp_config())
+    local prompt_exe = string.format('"%s" --shell=cmd --config="%s" --print-transient', omp_exe(), omp_config())
     prompt = io.popen(prompt_exe):read("*a")
     if prompt == "" then
         prompt = nil
image
JanDeDobbeleer commented 2 years ago

@RonAmihai I created an intermediate fix while we take our time to create a structural change :-)

chrisant996 commented 2 years ago

Aha. If you omit the --config="..." part then there is no problem.

I debugged a bit:

Apparently, if the command line will have more than one pair of quotes, then you have to also surround the entire line with quotes as well. This is a quirk of how cmd.exe parses the command line passed to it, when starting a new cmd.exe.

So, you need to do your original change (quotes around the entire command line) AND the change for [["::OMP::"]].

And then you'll find that the ~/blah.json path is not a valid Windows path and so oh-my-posh itself complains about the config file path. To fix that, you should be able to do something like this:

local function omp_config()
    return rl.expandtilde([[::CONFIG::]])
end
JanDeDobbeleer commented 2 years ago

@chrisant996 yup, that seems to fix it indeed. Thanks!!

github-actions[bot] commented 7 months ago

This issue has been automatically locked since there has not been any recent activity (i.e. last half year) after it was closed. It helps our maintainers focus on the active issues. If you have found a problem that seems similar, please open a discussion first, complete the body with all the details necessary to reproduce, and mention this issue as reference.