JanDeDobbeleer / oh-my-posh

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

Prompt position calculation after newline #83

Closed fdncred closed 3 years ago

fdncred commented 3 years ago

Prerequisites

Description

After adding a newline the prompt position doesn't seem to be calculated correct. Notice the vertical bar on the right side of the screenshot. image

Environment

Steps to Reproduce

  1. Install Nushell
  2. Use the custom json below.
  3. in nushell's config.toml change set prompt = "= `{{$(c:\\path\\to\\posh-windows-amd64.exe -config C:\\path\\to\\copy.json | str collect)}}`"

Expected behavior: [What you expected to happen] I excpect the prompt location to be next to the > Actual behavior: [What actually happened] the prompt location is moved over to the right about the same spot as if there wasn't a newline in my copy.json.

copy.json

{
  "blocks": [
    {
      "type": "prompt",
      "alignment": "left",
      "segments": [
        {
          "type": "time",
          "style": "plain",
          "foreground": "#E5C07B",
          "properties": {
            "time_format": "2006-01-02 3:04:05.000 AM",
            "prefix": "",
            "postfix": ""
          }
        },
        {
          "type": "root",
          "style": "powerline",
          "powerline_symbol": "",
          "foreground": "#100e23",
          "background": "#ffe9aa",
          "properties": {
            "root_icon": "襁"
          }
        }
      ]
    },
    {
      "type": "newline"
    },
    {
      "type": "prompt",
      "alignment": "left",
      "segments": [
        {
          "type": "path",
          "style": "powerline",
          "powerline_symbol": "",
          "foreground": "#ffffff",
          "background": "#3364a1",
          "properties": {
            "home_icon": "~",
            "folder_icon": "",
            "windows_registry_icon": "",
            "folder_separator_icon": "  ",
            "style": "short"
          }
        },
        {
          "type": "git",
          "style": "powerline",
          "powerline_symbol": "",
          "foreground": "#000000",
          "background": "#95ffa4",
          "properties": {
            "branch_icon": "",
            "branch_identical_icon": "≣",
            "branch_ahead_icon": "↑",
            "branch_behind_icon": "↓",
            "branch_gone_icon": "≢",
            "branch_untracked_icon": "\u2262",
            "local_working_icon": "",
            "local_staged_icon": "",
            "rebase_icon": " ",
            "cherry_pick_icon": " ",
            "detached_icon": " ",
            "tag_icon": "笠",
            "display_stash_count": true,
            "stash_count_icon": "\uF692 ",
            "merge_icon": "\uE726 ",
            "display_upstream_icon": true,
            "github_icon": "\uE709",
            "bitbucket_icon": "\uE703",
            "gitlab_icon": "\uE296",
            "git_icon": "\uE702"
          }
        },
        {
          "type": "python",
          "style": "powerline",
          "powerline_symbol": "",
          "foreground": "#100e23",
          "background": "#906cff",
          "properties": {
            "prefix": "  "
          }
        },
        {
          "type": "exit",
          "style": "powerline",
          "powerline_symbol": "",
          "foreground": "#ffffff",
          "background": "#ff8080",
          "properties": {
            "prefix": ""
          }
        }
      ]
    }
  ],
  "final_space": true
}
JanDeDobbeleer commented 3 years ago

The only way this can happen is that nushell counts the escape characters as well to define where the cursor is. To fix this, we need to escape those in a way that nushell expects. I'll read their docs to check if that's listed somewhere (hopefully). If not we'll need to raise a bug/question on their end.

fdncred commented 3 years ago

nushell doesn't escape characters so it may not have any knowledge of what is an escape and what is not. Nushell uses rustyline as a line editor so rustyline could be involved too. Thanks for the quick response. Nushell https://www.nushell.sh/ Nushell Github https://github.com/nushell/nushell Rustyline https://github.com/kkawakam/rustyline

JanDeDobbeleer commented 3 years ago

@fdncred what you could maybe try as a first approach is to remove the newline block and add a new segment to the first block with a \n

{
  "type": "text",
  "style": "plain",
  "foreground": "#ffffff",
  "properties": {
    "text": "\n",
    "prefix": "",
    "postfix": ""
  }
}

On some prompts this works (zsh, bash), but it doesn't work on PowerShell on MacOS for example which is why the default is ANSI escape sequences to change the line rather than \n. If this reduces the line length, something is off with counting the prompt length at nushell for which I'll have to acquire some rust knowledge (long time goal). Curious to see what the effect is of this change, it might bring us closer to finding a cause.

EDIT: I just setup and entire dev env and installed nushell so we'll see for how long I can postpone that goal 😅

fdncred commented 3 years ago

LOL. This works great! image

JanDeDobbeleer commented 3 years ago

I'll add that to the shell configs in that case. That way the newline block will work as expected. Nonetheless, nushell still needs to interpret those ANSI characters correctly (even though that's also an issue at zsh,...).

fdncred commented 3 years ago

If you can point me to the line(s) of code in your code base that is spitting out ansi characters that nushell is ignoring, I may be able to work on this issue for nushell. I just need to be able to pinpoint what is coming in from the prompt and how nushell/rustyline is failing. Thanks for all your help.

JanDeDobbeleer commented 3 years ago

The default prints "\x1b[1000C " which moves the cursor all the way to the right with 1 space meaning it starts on a new line. That's what's causing the issue here.

LuanVSO commented 3 years ago

maybe \x1b[E is better suited for newline then?

JanDeDobbeleer commented 3 years ago

maybe \x1b[E is better suited for newline then?

That actually works! I always thought (due to some info I found) it needed a number to tell the amount of lines down e.g. \x1b[1E. I'm submitting a PR with that change, looking forward to seeing the effect.

fdncred commented 3 years ago

fwiw - the prompt position is still far to the right in nushell, as first reported, even with 3.20.1, but the work-around still works.

JanDeDobbeleer commented 3 years ago

I'm reverting this fix as it breaks Powershell as well. Line breaks are challenging 😅

LuanVSO commented 3 years ago

how does it breaks? seems to work fine here

JanDeDobbeleer commented 3 years ago

Depends on the shell. Don't get me started.

JanDeDobbeleer commented 3 years ago

@fdncred should be fixed with v3.20.3

fdncred commented 3 years ago

Still shows up at the right with nushell. when i type, the text appears in the right spot but the blinking prompt is still to the right. Also, every character I type creates a new prompt before the newline.

Kind hard to describe so here's a gif. odd-behavior

JanDeDobbeleer commented 3 years ago

Ow, can you add a shell segment so I can see the name? On OSX it's nu, but it might also be nushell here (in which case the fix won't work)

fdncred commented 3 years ago

I added this:

        {
          "type": "shell",
          "style": "powerline",
          "powerline_symbol": "\uE0B0",
          "foreground": "#ffffff",
          "background": "#0077c2",
          "properties": {
            "prefix": " \uFCB5 "
          }
        },

and got this with nushell, which i don't really understand. image

LuanVSO commented 3 years ago

on pwsh on windows the method to move the cursor to the end of the line is borked because it reflows on resize which gets me this: image

JanDeDobbeleer commented 3 years ago

@LuanVSO the whole newline thing on Powershell is strange and this is the only way I could make it work consistently with this disadvantage. You can use \n in the shell directly and it will work, but it always gives really weird behavior when the exact same string is used in the prompt function and I have no idea why. These are the sequences I tried which give a bad result when used in the prompt function:

\n 
`n
\x1b[E
JanDeDobbeleer commented 3 years ago

and got this with nushell, which i don't really understand.

@fdncred that's rather strange as on OSX it displays nu in nushell. I already strip the .exe so in theory setting this for cmd as well should resolve the issue. CMD isn't supported anyways as it can set a prompt but not update it on the fly using an executable. However, might be interesting to see why nushell's executable reports itself as cmd.

fdncred commented 3 years ago

87 helped with this issue. At least now I can have the same json theme for powershell and nushell. For anyone facing the same problem, this is the theme that works for me. Thanks @JanDeDobbeleer for working on this.

pwsh image

nushell (i have no clue why the shell says cmd) image

{
  "blocks": [
    {
      "type": "prompt",
      "alignment": "left",
      "segments": [
        {
          "type": "time",
          "style": "plain",
          "foreground": "#E5C07B",
          "properties": {
            "time_format": "2006-01-02 3:04:05.000 AM",
            "prefix": "",
            "postfix": ""
          }
        },
        {
          "type": "root",
          "style": "powerline",
          "powerline_symbol": "",
          "foreground": "#100e23",
          "background": "#ffe9aa",
          "properties": {
            "root_icon": "襁"
          }
        }
      ]
    },
    {
      "type": "newline"
    },
    {
      "type": "prompt",
      "alignment": "left",
      "segments": [
        {
          "type": "path",
          "style": "powerline",
          "powerline_symbol": "",
          "foreground": "#ffffff",
          "background": "#3364a1",
          "properties": {
            "home_icon": "~",
            "folder_icon": "",
            "windows_registry_icon": "",
            "folder_separator_icon": "  ",
            "style": "short"
          }
        },
        {
          "type": "shell",
          "style": "powerline",
          "powerline_symbol": "\uE0B0",
          "foreground": "#ffffff",
          "background": "#0077c2",
          "properties": {
            "prefix": " \uFCB5 "
          }
        },
        {
          "type": "git",
          "style": "powerline",
          "powerline_symbol": "",
          "foreground": "#000000",
          "background": "#95ffa4",
          "properties": {
            "branch_icon": "",
            "branch_identical_icon": "≣",
            "branch_ahead_icon": "↑",
            "branch_behind_icon": "↓",
            "branch_gone_icon": "≢",
            "branch_untracked_icon": "\u2262",
            "local_working_icon": "",
            "local_staged_icon": "",
            "rebase_icon": " ",
            "cherry_pick_icon": " ",
            "detached_icon": " ",
            "tag_icon": "笠",
            "display_stash_count": true,
            "stash_count_icon": "\uF692 ",
            "merge_icon": "\uE726 ",
            "display_upstream_icon": true,
            "github_icon": "\uE709",
            "bitbucket_icon": "\uE703",
            "gitlab_icon": "\uE296",
            "git_icon": "\uE702"
          }
        },
        {
          "type": "python",
          "style": "powerline",
          "powerline_symbol": "",
          "foreground": "#100e23",
          "background": "#906cff",
          "properties": {
            "prefix": "  "
          }
        },
        {
          "type": "exit",
          "style": "powerline",
          "powerline_symbol": "",
          "foreground": "#ffffff",
          "background": "#ff8080",
          "properties": {
            "prefix": ""
          }
        }
      ]
    }
  ],
  "final_space": true
}
JanDeDobbeleer commented 3 years ago

I honestly don't think it should've been this hard and Powershell should just accept \n in prompt functions too. I have one final thing I want to try and then I'm actually going to ask a Powershell professional over at the repo. Because I'm either not aware of something, or they have a bug.

fdncred commented 3 years ago

Please let me know if you'd like me to test. I've had to revert to my old prompt in nushell because I discovered another problem. When I paste anything, I get many lines like in the gif above when typing. I could open a separate issue if you like.

JanDeDobbeleer commented 3 years ago

Not sure if that's related to oh-my-posh. On other shells that's because the length of the prompt isn't calculated properly. On ZSH and Bash I have to escape certain sequences so it can count correctly and cursor placement is accurate. I couldn't find this information for nushell and I'm quite sure there's still something going on on that end.

Feel free to create a separate issue for that one. We can still link back to nushell if needed.

github-actions[bot] commented 4 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.