romkatv / powerlevel10k

A Zsh theme
MIT License
45.58k stars 2.16k forks source link

Custom Element New Lines #1276

Closed MrDogeBro closed 3 years ago

MrDogeBro commented 3 years ago

So I am trying to make a conditional newline where the newline is only put there if specific condition's are met. To do this, I created a custom element. The issue is however, that I can not get it to actually add the newline. I have tried using the API by doing p10k segment -t "\n". I have also tried many, many, many different combinations of charaters to be the text but none of them have worked. For example, if you just put "\n" like in the example above, it literally just writes the text to be \n. Any help or guidance as to if/how this is possible would be greatly appreciated.

romkatv commented 3 years ago

Please describe how you want your prompt to look and behave. Attach a config that works and that is close to what you want.

MrDogeBro commented 3 years ago

Wanted Behavior/Look

Basically the behavior I want is just so that if conditions x are met, put these elements on a new line. Else, keep elements on a single line. This is kinda a example of what it might look like (obviously manually adding/removing the newline).

Example

In a git directory and a py venv = multiline Cap 02-25-21 15 27 59 In a dir without git or a py venv = single line Cap 02-25-21 15 28 35

Similar Configs

Here are the GitHub links to my current configs. One is the theme config and the other is just the file that contains the custom element that detects any conditions I set and if they are met, it should add a newline to the prompt, but it currently just puts the text \n into the prompt as seen below. Cap 02-25-21 15 35 06

Links to Configs

Main theme config — https://github.com/MrDogeBro/dotfiles/blob/master/.config/zsh/theme.zsh Custom elements — https://github.com/MrDogeBro/dotfiles/blob/master/.config/zsh/prompt-elements.zsh

romkatv commented 3 years ago

This should do it: https://github.com/MrDogeBro/dotfiles/compare/master...romkatv:prompt-conditional-newline

diff --git a/.config/zsh/theme.zsh b/.config/zsh/theme.zsh
index a7ea398..24b87ed 100644
--- a/.config/zsh/theme.zsh
+++ b/.config/zsh/theme.zsh
@@ -33,12 +33,8 @@ ZSH_THEME="powerlevel10k/powerlevel10k"

   # The list of segments shown on the left. Fill it with the most important segments.
   typeset -g POWERLEVEL9K_LEFT_PROMPT_ELEMENTS=(
-    os_icon                 # os identifier
-    dir                     # current directory
-    # prompt_char           # prompt symbol
-    conditional_newline
-    vcs                     # git status
-    virtualenv
+    os_icon dir newline
+    os_icon dir vcs virtualenv
   )

   # The list of segments shown on the right. Fill it with less important segments.
@@ -46,65 +42,8 @@ ZSH_THEME="powerlevel10k/powerlevel10k"
   # automatically hidden when the input line reaches it. Right prompt above the
   # last prompt line gets hidden if it would overlap with left prompt.
   typeset -g POWERLEVEL9K_RIGHT_PROMPT_ELEMENTS=(
-    status                  # exit code of the last command
-    command_execution_time  # duration of the last command
-    # background_jobs         # presence of background jobs
-    # direnv                  # direnv status (https://direnv.net/)
-    # asdf                    # asdf version manager (https://github.com/asdf-vm/asdf)
-    # virtualenv              # python virtual environment (https://docs.python.org/3/library/venv.html)
-    # anaconda                # conda environment (https://conda.io/)
-    pyenv                   # python environment (https://github.com/pyenv/pyenv)
-    # goenv                   # go environment (https://github.com/syndbg/goenv)
-    # nodenv                  # node.js version from nodenv (https://github.com/nodenv/nodenv)
-    # nvm                     # node.js version from nvm (https://github.com/nvm-sh/nvm)
-    # nodeenv                 # node.js environment (https://github.com/ekalinin/nodeenv)
-    node_version          # node.js version
-    # go_version            # go version (https://golang.org)
-    rust_version          # rustc version (https://www.rust-lang.org)
-    # dotnet_version        # .NET version (https://dotnet.microsoft.com)
-    # php_version           # php version (https://www.php.net/)
-    # laravel_version       # laravel php framework version (https://laravel.com/)
-    # java_version          # java version (https://www.java.com/)
-    # package               # name@version from package.json (https://docs.npmjs.com/files/package.json)
-    # rbenv                   # ruby version from rbenv (https://github.com/rbenv/rbenv)
-    # rvm                     # ruby version from rvm (https://rvm.io)
-    # fvm                     # flutter version management (https://github.com/leoafarias/fvm)
-    # luaenv                  # lua version from luaenv (https://github.com/cehoffman/luaenv)
-    # jenv                    # java version from jenv (https://github.com/jenv/jenv)
-    # plenv                   # perl version from plenv (https://github.com/tokuhirom/plenv)
-    # phpenv                  # php version from phpenv (https://github.com/phpenv/phpenv)
-    # scalaenv                # scala version from scalaenv (https://github.com/scalaenv/scalaenv)
-    # haskell_stack           # haskell version from stack (https://haskellstack.org/)
-    # kubecontext             # current kubernetes context (https://kubernetes.io/)
-    # terraform               # terraform workspace (https://www.terraform.io)
-    # aws                     # aws profile (https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-profiles.html)
-    # aws_eb_env              # aws elastic beanstalk environment (https://aws.amazon.com/elasticbeanstalk/)
-    # azure                   # azure account name (https://docs.microsoft.com/en-us/cli/azure)
-    # gcloud                  # google cloud cli account and project (https://cloud.google.com/)
-    # google_app_cred         # google application credentials (https://cloud.google.com/docs/authentication/production)
-    # context                 # user@hostname
-    # nordvpn                 # nordvpn connection status, linux only (https://nordvpn.com/)
-    # ranger                  # ranger shell (https://github.com/ranger/ranger)
-    # nnn                     # nnn shell (https://github.com/jarun/nnn)
-    # vim_shell               # vim shell indicator (:sh)
-    # midnight_commander      # midnight commander shell (https://midnight-commander.org/)
-    # nix_shell               # nix shell (https://nixos.org/nixos/nix-pills/developing-with-nix-shell.html)
-    vi_mode                 # vi mode (you don't need this if you've enabled prompt_char)
-    # vpn_ip                # virtual private network indicator
-    # load                  # CPU load
-    # disk_usage            # disk usage
-    # ram                   # free RAM
-    # swap                  # used swap
-    # todo                    # todo items (https://github.com/todotxt/todo.txt-cli)
-    # timewarrior             # timewarrior tracking status (https://timewarrior.net/)
-    # taskwarrior             # taskwarrior task count (https://taskwarrior.org/)
-    # time                    # current time
-    # ip                    # ip address and bandwidth usage for a specified network interface
-    # public_ip             # public IP address
-    # proxy                 # system-wide http/https/ftp proxy
-    # battery               # internal battery
-    # wifi                  # wifi speed
-    # example               # example user-defined segment (see prompt_example function below)
+    status command_execution_time pyenv node_version rust_version vi_mode newline
+    status command_execution_time pyenv node_version rust_version vi_mode
   )

   # Defines character set used by powerlevel10k. It's best to let `p10k configure` set it for you.
@@ -1610,6 +1549,15 @@ ZSH_THEME="powerlevel10k/powerlevel10k"
   # Custom prefix.
   # typeset -g POWERLEVEL9K_TIME_PREFIX='at '

+  function p10k-on-pre-prompt() {
+    emulate -L zsh -o extended_glob
+    if [[ -n ./(../)#(.git)(#qN/) ]]; then
+      p10k display '1'=show '2/left/(os_icon|dir)'=hide '2/right'=hide
+    else
+      p10k display '1'=hide '2/left/(os_icon|dir)'=show '2/right'=show
+    fi
+  }
+
   # Example of a user-defined prompt segment. Function prompt_example will be called on every
   # prompt if `example` prompt segment is added to POWERLEVEL9K_LEFT_PROMPT_ELEMENTS or
   # POWERLEVEL9K_RIGHT_PROMPT_ELEMENTS. It displays an icon and yellow text on red background
MrDogeBro commented 3 years ago

Thank you for your help. This is working so that's great. I had played around with using the display command before but hadn't gotten it to work so thanks for your help in doing that.

mtalexan commented 3 years ago

I was also interested in doing this, but had a tough time figuring out why this answer works as it does. The p10k display documentation only provides a little help in this regard, so I wanted to document the reasoning for posterity.

The critical block of code relies on an understanding of the p10k display command, which allows you to hide and show segments or whole lines (among other things). The "tricks" here are that newline isn't a segment that can be shown or hidden, and if an entire line is hidden it won't show in the prompt as a blank line.

The solution therefore defines 2 lines for the right and left prompt. The second line is what is desired when everything's on a single line. A first line is then defined that contains what should be on the first line when we have it split across multiple lines. We then identify the items on the single-line prompt (the second line in our config) that are also in the first line of the 2-line prompt. When toggle between two states we are hiding the first prompt-line and showing everything from the second-prompt line for the condition where we have everything on a single line, and switch to showing both prompt lines but hiding the specific segments in the second-prompt line that are now on the first prompt line when we want two lines in our prompt.

EDIT: grammar