diff --git a/doc_src/conf.py b/doc_src/conf.py index b5aeb5e95301..55f9c7cfd023 100644 --- a/doc_src/conf.py +++ b/doc_src/conf.py @@ -187,6 +187,7 @@ def get_command_description(path, name): ("interactive", "fish-interactive", "", [author], 1), ("relnotes", "fish-releasenotes", "", [author], 1), ("completions", "fish-completions", "", [author], 1), + ("prompt", "fish-prompt-tutorial", "", [author], 1), ( "fish_for_bash_users", "fish-for-bash-users", diff --git a/doc_src/index.rst b/doc_src/index.rst index 91d97f277aaf..9ffe76c52c60 100644 --- a/doc_src/index.rst +++ b/doc_src/index.rst @@ -171,6 +171,7 @@ Other help pages fish_for_bash_users tutorial completions + prompt design relnotes contributing diff --git a/doc_src/prompt.rst b/doc_src/prompt.rst new file mode 100644 index 000000000000..76757dfa9c42 --- /dev/null +++ b/doc_src/prompt.rst @@ -0,0 +1,172 @@ +Writing your own prompt +======================= + +.. only:: builder_man + + .. warning:: + This document uses formatting to show what a prompt would look like. If you are viewing this in the man page, + you probably want to switch to looking at the html version instead. Run ``help custom-prompt`` to view it in a web browser. + +Fish ships a number of prompts that you can view with the :doc:`fish_config ` command, and many users have shared their prompts online. + +However, you can also write your own, or adjust an existing prompt. This is a good way to get used to fish's :doc:`scripting language `. + +Unlike other shells, fish's prompt is built by running a function - :doc:`fish_prompt `. Or, more specifically, three functions: + +- :doc:`fish_prompt `, which is the main prompt function +- :doc:`fish_right_prompt `, which is shown on the right side of the terminal. +- :doc:`fish_mode_prompt `, which is shown if :ref:`vi-mode ` is used. + +These functions are run, and whatever they print is displayed as the prompt (minus one trailing newline). + +Here, we will just be writing a simple fish_prompt. + +Our first prompt +---------------- + +Let's look at a very simple example:: + + function fish_prompt + echo $PWD '>' + end + +This prints the current working directory (:envvar:`PWD`) and a ``>`` symbol to show where the prompt ends. The ``>`` is :ref:`quoted ` because otherwise it would signify a :ref:`redirection `. + +Because we've used :doc:`echo `, it adds spaces between the two so it ends up looking like (assuming ``_`` is your cursor): + +.. role:: white +.. parsed-literal:: + :class: highlight + + :white:`/home/tutorial >`\ _ + +Formatting +---------- + +``echo`` adds spaces between its arguments. If you don't want those, you can use :doc:`string join ` like this:: + + function fish_prompt + string join '' -- $PWD '>' + end + +The ``--`` indicates to ``string`` that no options can come after it, in case we extend this with something that can start with a ``-``. + +There are other ways to remove the space, including ``echo -s`` and :doc:`printf `. + +Adding colo(u)r +--------------- + +This prompt is functional, but a bit boring. We could add some color. + +Fortunately, fish offers the :doc:`set_color ` command, so you can do:: + + echo (set_color red)foo + +``set_color`` can also handle RGB colors like ``set_color 23b455``, and other formatting options including bold and italics. + +So, taking our previous prompt and adding some color:: + + function fish_prompt + string join '' -- (set_color green) $PWD (set_color normal) '>' + end + +A "normal" color tells the terminal to go back to its normal formatting options. + +What ``set_color`` does internally is to print an escape sequence that tells the terminal to change color. So if you see something like:: + + echo \e\[31mfoo + +that could just be ``set_color red``. + +Shortening the working directory +-------------------------------- + +This is fine, but our :envvar:`PWD` can be a bit long, and we are typically only interested in the last few directories. We can shorten this with the :doc:`prompt_pwd ` helper that will give us a shortened working directory:: + + function fish_prompt + string join '' -- (set_color green) (prompt_pwd) (set_color normal) '>' + end + +``prompt_pwd`` takes options to control how much to shorten. For instance, if we want to display the last two directories, we'd use ``prompt_pwd --full-length-dirs 2``:: + + function fish_prompt + string join '' -- (set_color green) (prompt_pwd --full-length-dirs 2) (set_color normal) '>' + end + +With a current directory of "/home/tutorial/Music/Lena Raine/Oneknowing", this would print + +.. role:: green +.. parsed-literal:: + :class: highlight + + :green:`~/M/Lena Raine/Oneknowing`>_ + +Status +------ + +One important bit of information that every command returns is the :ref:`status `. This is a whole number from 0 to 255, and usually it is used as an error code - 0 if the command returned successfully, or a number from 1 to 255 if not. + +It's useful to display this in your prompt, but showing it when it's 0 seems kind of wasteful. + +First of all, since every command (except for :doc:`set `) changes the status, you need to store it for later use as the first thing in your prompt. Use a :ref:`local variable ` so it will be confined to your prompt function:: + + set -l last_status $status + +And after that, you can set a string if it not zero:: + + # Prompt status only if it's not 0 + set -l stat + if test $last_status -ne 0 + set stat (set_color red)"[$last_status]"(set_color normal) + end + +And to print it, we add it to our ``string join``:: + + string join '' -- (set_color green) (prompt_pwd) (set_color normal) $stat '>' + +If ``$last_status`` was 0, ``$stat`` is empty, and so it will simply disappear. + +So our entire prompt is now:: + + function fish_prompt + set -l last_status $status + # Prompt status only if it's not 0 + set -l stat + if test $last_status -ne 0 + set stat (set_color red)"[$last_status]"(set_color normal) + end + + string join '' -- (set_color green) (prompt_pwd) (set_color normal) $stat '>' + end + +And it looks like: + +.. role:: green +.. role:: red +.. parsed-literal:: + :class: highlight + + :green:`~/M/L/Oneknowing`\ :red:`[1]`>_ + +after we run ``false`` (which returns 1). + +Where to go from here? +---------------------- + +We have now built a simple but working and usable prompt, but of course more can be done. + +- Fish offers more helper functions: + - ``prompt_login`` to describe the user/hostname/container or ``prompt_hostname`` to describe just the host + - ``fish_is_root_user`` to help with changing the symbol for root. + - ``fish_vcs_prompt`` to show version control information (or ``fish_git_prompt`` / ``fish_hg_prompt`` / ``fish_svn_prompt`` to limit it to specific systems) +- You can add a right prompt by changing :doc:`fish_right_prompt ` or a vi-mode prompt by changing :doc:`fish_mode_prompt `. +- Some prompts have interesting or advanced features + - Add the time when the prompt was printed + - Show various integrations like python's venv + - Color the parts differently. + +You can look at fish's sample prompts for inspiration. Open up :doc:`fish_config `, find one you like and pick it. For example:: + + fish_config prompt show # <- shows all the sample prompts + fish_config prompt choose disco # <- this picks the "disco" prompt for this session + funced fish_prompt # <- opens fish_prompt in your editor, and reloads it once the editor exits diff --git a/doc_src/python_docs_theme/static/pydoctheme.css b/doc_src/python_docs_theme/static/pydoctheme.css index 3835ddd84841..59308c249e10 100644 --- a/doc_src/python_docs_theme/static/pydoctheme.css +++ b/doc_src/python_docs_theme/static/pydoctheme.css @@ -607,6 +607,7 @@ div.documentwrapper { .gray { color: #777 } .purple { color: #551a8b; font-weight: bold; } .red { color: #FF0000; } +.green { color: #00FF00; } /* Color based on the Name.Function (.nf) class from pygments.css. */ .command { color: #005fd7 } diff --git a/share/functions/help.fish b/share/functions/help.fish index 4990d9062f1d..4c99d34f6a0a 100644 --- a/share/functions/help.fish +++ b/share/functions/help.fish @@ -149,6 +149,8 @@ function help --description 'Show help for the fish shell' set fish_help_page faq.html case fish-for-bash-users set fish_help_page fish_for_bash_users.html + case custom-prompt + set fish_help_page prompt.html case $faqpages set fish_help_page "faq.html#$fish_help_item" case $for_bash_pages