mirror of
				https://gitlab.com/ceda_ei/wish
				synced 2025-11-03 22:50:06 +01:00 
			
		
		
		
	Compare commits
	
		
			42 Commits
		
	
	
		
			d9e86e4421
			...
			master
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 07e406d3f1 | |||
| 58aefa063b | |||
| 7cb8857e5e | |||
| 869a754ede | |||
| 61ade4610c | |||
| 4b9c2b6982 | |||
| cc5eefb197 | |||
| de9e43365f | |||
| 11ad2e081f | |||
| 1db62a7be8 | |||
| e05f37b5b9 | |||
| 9e55279faf | |||
| afd6dc6668 | |||
| e01b29d4a0 | |||
| 186675ae4e | |||
| c53939cdfe | |||
| 9a2d831432 | |||
| aabc6ebfd6 | |||
| 76b9bd3ad1 | |||
| 20fb08f202 | |||
| 48ff98764d | |||
| 110217642e | |||
| 364463658a | |||
| 343e394d40 | |||
| b1fe80cef3 | |||
| fe18fd52db | |||
| 30ebb302b8 | |||
| 919b102a43 | |||
| 136567e08e | |||
| 97fe2dbcc6 | |||
| 3f156fdd35 | |||
| 5828900a92 | |||
| f8254ba89a | |||
| b389774a50 | |||
| eb7f3a6aa3 | |||
| c3fbe4f699 | |||
| 079533b686 | |||
| 4bed328fa2 | |||
| 886ec3bfaf | |||
| ffe7975dfa | |||
| ab5df51c2a | |||
| 2c6c83b826 | 
							
								
								
									
										3
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,3 @@
 | 
			
		||||
__pycache__/
 | 
			
		||||
*.pyc
 | 
			
		||||
config.gie
 | 
			
		||||
							
								
								
									
										100
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										100
									
								
								README.md
									
									
									
									
									
								
							@@ -1,24 +1,110 @@
 | 
			
		||||
# Wish
 | 
			
		||||
 | 
			
		||||
A customizable bash prompt.
 | 
			
		||||
A customizable, extensible, themable bash prompt.
 | 
			
		||||
 | 
			
		||||

 | 
			
		||||
 | 
			
		||||
## Features
 | 
			
		||||
 | 
			
		||||
+ **Extensible**: Parts can be added using simple plugins.
 | 
			
		||||
+ **Themable**: Choose from an existing theme or create your own.
 | 
			
		||||
+ **Customizable**: The prompt can be customized via a simple config file.
 | 
			
		||||
+ **Right Prompt**: Allows for two prompts — one on left, one on right.
 | 
			
		||||
+ **Auto newline**: Automatically adds a newline if the last output doesn't end with one.
 | 
			
		||||
+ **Powerline support**: Supports powerline symbols in both prompts.
 | 
			
		||||
 | 
			
		||||
# Installation
 | 
			
		||||
 | 
			
		||||
## One step Installation
 | 
			
		||||
 | 
			
		||||
`curl https://gitlab.com/ceda_ei/wish/raw/master/install.sh | bash`
 | 
			
		||||
```sh
 | 
			
		||||
curl https://gitlab.com/ceda_ei/wish/raw/master/install.sh | bash
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
## Manual Installation
 | 
			
		||||
 | 
			
		||||
+ `cd ~/.config/`
 | 
			
		||||
+ `git clone https://gitlab.com/ceda_ei/wish.git`
 | 
			
		||||
+ Add the following lines to ~/.bashrc
 | 
			
		||||
+ `cp wish/config.default.gie wish/config.gie`
 | 
			
		||||
 | 
			
		||||
# Customization
 | 
			
		||||
 | 
			
		||||
Customization of wish is done using a gINIe file (format specific to wish)
 | 
			
		||||
which is an extended INI config file. The default location for config file is
 | 
			
		||||
`~/.config/wish/config.gie`. The default config file is automatically copied
 | 
			
		||||
over. The location can be customized using `WISH_CONFIG_FILE` variable.
 | 
			
		||||
Multiple config files can be supplied as an array to `WISH_CONFIG_FILE`.
 | 
			
		||||
 | 
			
		||||
Comments start with a `#` or `;` and always exist on a line of their own.
 | 
			
		||||
 | 
			
		||||
Key value pairs are in the form of `key = value`. Keys cannot have whitespaces
 | 
			
		||||
or `=` in them. Values can have any character as part of them. Surrounding
 | 
			
		||||
spaces in values are stripped away. To keep surrounding spaces as a part of
 | 
			
		||||
the value. Although, keys are case-sensitive in gINIe, wish treats them case-
 | 
			
		||||
insensitively.
 | 
			
		||||
 | 
			
		||||
Block names are enclosed in `[]` (e.g. `[core]`). Block names are case
 | 
			
		||||
sensitive. All key value pairs after a block starts and before the next block
 | 
			
		||||
begins are considered a part of that block. All key value pairs must be in a
 | 
			
		||||
block.
 | 
			
		||||
 | 
			
		||||
Available Blocks:
 | 
			
		||||
 | 
			
		||||
+ `core`: Core block configures Wish itself. Available keys are:
 | 
			
		||||
    - `auto_newline`: Automatically add a newline if last line of output
 | 
			
		||||
      doesn't end in newline. (0 to disable, 1 to enable)
 | 
			
		||||
    - `theme`: Wish theme.
 | 
			
		||||
    - `powerline`: Enable / Disable powerline. (0 to disable, 1 to enable)
 | 
			
		||||
+ `plugin`: Adds a plugin to the section the block is added to. All config for
 | 
			
		||||
  that plugin goes there. Check wiki for details on available keys for
 | 
			
		||||
  plugins. The key "name" defines the plugin to use. Plugin blocks
 | 
			
		||||
  outside a section are ignored.
 | 
			
		||||
 | 
			
		||||
Section names are enclosed in `||` (e.g. `|left|`). All blocks after a section
 | 
			
		||||
starts and before the next section begins are considered a part of that
 | 
			
		||||
section.  Blocks don't necessarily need to be in a section.
 | 
			
		||||
 | 
			
		||||
Available sections are `left`, `right` for left prompt and right prompt
 | 
			
		||||
respectively.
 | 
			
		||||
 | 
			
		||||
Sample config file
 | 
			
		||||
 | 
			
		||||
```bash
 | 
			
		||||
WISH_PLUGINS=(exit_code_smiley bg_jobs date path newline vcs)
 | 
			
		||||
WISH_THEME=plain
 | 
			
		||||
source ~/.config/wish/wish.sh
 | 
			
		||||
```
 | 
			
		||||
[core]
 | 
			
		||||
auto_newline = 1
 | 
			
		||||
powerline = 1
 | 
			
		||||
theme = rgb_gradient
 | 
			
		||||
 | 
			
		||||
|left|
 | 
			
		||||
[plugin]
 | 
			
		||||
name = path_powerline
 | 
			
		||||
max_perc = 50
 | 
			
		||||
 | 
			
		||||
[plugin]
 | 
			
		||||
name = python_venv
 | 
			
		||||
 | 
			
		||||
[plugin]
 | 
			
		||||
name = newline
 | 
			
		||||
 | 
			
		||||
[plugin]
 | 
			
		||||
name = custom_text
 | 
			
		||||
text = ' λ '
 | 
			
		||||
 | 
			
		||||
[plugin]
 | 
			
		||||
name = space
 | 
			
		||||
 | 
			
		||||
|right|
 | 
			
		||||
[plugin]
 | 
			
		||||
name = date
 | 
			
		||||
format = %a %b %H:%M
 | 
			
		||||
 | 
			
		||||
[plugin]
 | 
			
		||||
name = hostname
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
Which results in the following prompt
 | 
			
		||||
 | 
			
		||||

 | 
			
		||||
 | 
			
		||||
# Wiki
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										59
									
								
								config.default.gie
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										59
									
								
								config.default.gie
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,59 @@
 | 
			
		||||
# vim: set ft=dosini:
 | 
			
		||||
#
 | 
			
		||||
# Comments start with a # or ; and always exist on a line of their own.
 | 
			
		||||
#
 | 
			
		||||
# Key value pairs are in the form of key = value. Keys cannot have whitespaces
 | 
			
		||||
# or = in them. Values can have any character as part of them. Surrounding
 | 
			
		||||
# spaces in values are stripped away. To keep surrounding spaces as a part of
 | 
			
		||||
# the value. Although, keys are case-sensitive in gINIe, wish treats them case-
 | 
			
		||||
# insensitively.
 | 
			
		||||
#
 | 
			
		||||
# Block names are enclosed in [] (e.g. [core]). Block names are case sensitive.
 | 
			
		||||
# All key value pairs after a block starts and before the next block begins are
 | 
			
		||||
# considered a part of that block. All key value pairs must be in a block.
 | 
			
		||||
#
 | 
			
		||||
# Available Blocks:
 | 
			
		||||
#
 | 
			
		||||
#   core: Core block configures Wish itself. Available keys are:
 | 
			
		||||
#        - auto_newline: Automatically add a newline if last line of output
 | 
			
		||||
#          doesn't end in newline. (0 to disable, 1 to enable)
 | 
			
		||||
#        - theme: Wish theme.
 | 
			
		||||
#        - powerline: Enable / Disable powerline. (0 to disable, 1 to enable)
 | 
			
		||||
#
 | 
			
		||||
#   plugin: Adds a plugin to the section the block is added to. All config for
 | 
			
		||||
#           that plugin goes there. The key "name" defines the plugin to use.
 | 
			
		||||
#           Plugin blocks outside a section are ignored.
 | 
			
		||||
#
 | 
			
		||||
# Section names are enclosed in || (e.g. |left|). All blocks after a section
 | 
			
		||||
# starts and before the next section begins are considered a part of that
 | 
			
		||||
# section. Blocks don't necessarily need to be in a section.
 | 
			
		||||
#
 | 
			
		||||
# Available sections are left, right for left prompt and right prompt
 | 
			
		||||
# respectively.
 | 
			
		||||
 | 
			
		||||
[core]
 | 
			
		||||
auto_newline = 1
 | 
			
		||||
powerline = 1
 | 
			
		||||
theme = plain
 | 
			
		||||
 | 
			
		||||
|left|
 | 
			
		||||
[plugin]
 | 
			
		||||
name = exit_code_smiley
 | 
			
		||||
 | 
			
		||||
[plugin]
 | 
			
		||||
name = bg_jobs
 | 
			
		||||
 | 
			
		||||
[plugin]
 | 
			
		||||
name = date
 | 
			
		||||
format = %d %b %H:%M
 | 
			
		||||
 | 
			
		||||
[plugin]
 | 
			
		||||
name = path
 | 
			
		||||
 | 
			
		||||
[plugin]
 | 
			
		||||
name = newline
 | 
			
		||||
 | 
			
		||||
[plugin]
 | 
			
		||||
name = vcs
 | 
			
		||||
 | 
			
		||||
|right|
 | 
			
		||||
							
								
								
									
										135
									
								
								ginie.py
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										135
									
								
								ginie.py
									
									
									
									
									
										Executable file
									
								
							@@ -0,0 +1,135 @@
 | 
			
		||||
#!/usr/bin/env python3
 | 
			
		||||
"gINIe Parser for Wish"
 | 
			
		||||
 | 
			
		||||
import re
 | 
			
		||||
import sys
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class GinieParseError(ValueError):
 | 
			
		||||
    "Exception Class for errors in"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def loads(string):
 | 
			
		||||
    """
 | 
			
		||||
    Deserialize `string` (a `str` instance containing a gINIe document)
 | 
			
		||||
    into a Python list.
 | 
			
		||||
 | 
			
		||||
    Return Value: List of `block` and `section` dicts
 | 
			
		||||
 | 
			
		||||
    `block` dicts are of form
 | 
			
		||||
    {
 | 
			
		||||
        'type': 'block',
 | 
			
		||||
        'name': 'name_of_block_as_in_config',
 | 
			
		||||
        'config': {}
 | 
			
		||||
    }
 | 
			
		||||
    where `name` and `config` keys are based on the gINIe document.
 | 
			
		||||
 | 
			
		||||
    `section` dicts are of form
 | 
			
		||||
 | 
			
		||||
    {
 | 
			
		||||
        'type': 'block',
 | 
			
		||||
        'name': 'name_of_block_as_in_config',
 | 
			
		||||
        'blocks': []
 | 
			
		||||
    }
 | 
			
		||||
    where `name` and `blocks` keys are based on the gINIe document and blocks
 | 
			
		||||
    is a list of block dicts found in the section.
 | 
			
		||||
    """
 | 
			
		||||
    config = []
 | 
			
		||||
    section_re = re.compile(r"^\|(?P<section>.+)\|$")
 | 
			
		||||
    block_re = re.compile(r"^\[(?P<block>[^\]]*)\]$")
 | 
			
		||||
    line_re = re.compile(r"^\s*(?P<key>[^\s=]+)(\s*)=\s*?(?P<value>.*)$")
 | 
			
		||||
    empty_re = re.compile(r"^\s*$")
 | 
			
		||||
    comment_re = re.compile(r"^\s*(#|;)")
 | 
			
		||||
    current_block = None
 | 
			
		||||
    current_section = None
 | 
			
		||||
    for idx, line in enumerate(string.splitlines()):
 | 
			
		||||
        idx += 1  # Since line numbers begin with 1
 | 
			
		||||
        # Skip comments and empty lines
 | 
			
		||||
        if empty_re.match(line) or comment_re.match(line):
 | 
			
		||||
            continue
 | 
			
		||||
 | 
			
		||||
        # Section parsing
 | 
			
		||||
        if line.startswith("|"):
 | 
			
		||||
            match = section_re.match(line)
 | 
			
		||||
            if match is None:
 | 
			
		||||
                err = "Invalid line {}".format(idx)
 | 
			
		||||
                raise GinieParseError(err)
 | 
			
		||||
            current_section = {
 | 
			
		||||
                "type": "section",
 | 
			
		||||
                "name": match.group("section"),
 | 
			
		||||
                "blocks": []
 | 
			
		||||
            }
 | 
			
		||||
            config.append(current_section)
 | 
			
		||||
            continue
 | 
			
		||||
 | 
			
		||||
        # Block Parsing
 | 
			
		||||
        if line.startswith("["):
 | 
			
		||||
            match = block_re.match(line)
 | 
			
		||||
            if match is None:
 | 
			
		||||
                err = "Invalid block name on line {}".format(idx)
 | 
			
		||||
                raise GinieParseError(err)
 | 
			
		||||
            current_block = {
 | 
			
		||||
                "type": "block",
 | 
			
		||||
                "name": match.group("block"),
 | 
			
		||||
                "config": {}
 | 
			
		||||
            }
 | 
			
		||||
            if current_section is None:
 | 
			
		||||
                config.append(current_block)
 | 
			
		||||
            else:
 | 
			
		||||
                current_section["blocks"].append(current_block)
 | 
			
		||||
            continue
 | 
			
		||||
 | 
			
		||||
        # If it is neither a comment, nor a section, nor a block, it has to be
 | 
			
		||||
        # a key, value pair.
 | 
			
		||||
        if current_block is None:
 | 
			
		||||
            raise GinieParseError("Found lines outside a block")
 | 
			
		||||
 | 
			
		||||
        match = line_re.match(line)
 | 
			
		||||
        if match is None:
 | 
			
		||||
            raise GinieParseError("Invalid line {}: {}".format(idx, line))
 | 
			
		||||
 | 
			
		||||
        value = match.group('value').strip()
 | 
			
		||||
        if value:
 | 
			
		||||
            if value[0] == value[-1] == "'" or value[0] == value[-1] == '"':
 | 
			
		||||
                value = value[1:-1]
 | 
			
		||||
        current_block["config"][match.group('key').strip()] = value
 | 
			
		||||
 | 
			
		||||
    return config
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def load(file):
 | 
			
		||||
    """
 | 
			
		||||
    Deserialize `file` (a file-like object containing a gINIe document)
 | 
			
		||||
    into a Python list.
 | 
			
		||||
 | 
			
		||||
    Return Value: List of `block` and `section` dicts
 | 
			
		||||
 | 
			
		||||
    `block` dicts are of form
 | 
			
		||||
    {
 | 
			
		||||
        'type': 'block',
 | 
			
		||||
        'name': 'name_of_block_as_in_config',
 | 
			
		||||
        'config': {}
 | 
			
		||||
    }
 | 
			
		||||
    where `name` and `config` keys are based on the gINIe document.
 | 
			
		||||
 | 
			
		||||
    `section` dicts are of form
 | 
			
		||||
 | 
			
		||||
    {
 | 
			
		||||
        'type': 'block',
 | 
			
		||||
        'name': 'name_of_block_as_in_config',
 | 
			
		||||
        'blocks': []
 | 
			
		||||
    }
 | 
			
		||||
    where `name` and `blocks` keys are based on the gINIe document and blocks
 | 
			
		||||
    is a list of block dicts found in the section.
 | 
			
		||||
    """
 | 
			
		||||
    return loads(file.read())
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
if __name__ == "__main__":
 | 
			
		||||
    if len(sys.argv) == 1:
 | 
			
		||||
        print("Usage: {} file.gie|-".format(sys.argv[0]))
 | 
			
		||||
    elif sys.argv[1] == '-':
 | 
			
		||||
        print(load(sys.stdin))
 | 
			
		||||
    else:
 | 
			
		||||
        with open(sys.argv[1]) as source:
 | 
			
		||||
            print(load(source))
 | 
			
		||||
@@ -1,7 +1,7 @@
 | 
			
		||||
#!/usr/bin/env bash
 | 
			
		||||
 | 
			
		||||
if hash git; then
 | 
			
		||||
	git clone https://gitlab.com/ceda_ei/wish.git $HOME/.config/wish.git
 | 
			
		||||
	git clone https://gitlab.com/ceda_ei/Wish.git $HOME/.config/wish
 | 
			
		||||
else
 | 
			
		||||
	curl https://gitlab.com/ceda_ei/wish/-/archive/master/wish-master.tar -o /tmp/wish.tar
 | 
			
		||||
	mkdir $HOME/.config 2> /dev/null
 | 
			
		||||
@@ -10,12 +10,11 @@ else
 | 
			
		||||
	mv wish-master/ wish/
 | 
			
		||||
	mv wish/ $HOME/.config/
 | 
			
		||||
fi
 | 
			
		||||
cp $HOME/.config/wish/config.default.gie $HOME/.config/wish/config.gie
 | 
			
		||||
 | 
			
		||||
cat >> ~/.bashrc <<EOF
 | 
			
		||||
 | 
			
		||||
# Wish
 | 
			
		||||
 | 
			
		||||
WISH_PLUGINS=(exit_code_smiley bg_jobs date path newline vcs)
 | 
			
		||||
WISH_THEME=plain
 | 
			
		||||
source ~/.config/wish/wish.sh
 | 
			
		||||
WISH_CONFIG_FILE="$HOME/.config/wish/config.gie"
 | 
			
		||||
source $HOME/.config/wish/wish.sh
 | 
			
		||||
EOF
 | 
			
		||||
 
 | 
			
		||||
@@ -16,12 +16,17 @@ function wish_battery_set_colors() {
 | 
			
		||||
 | 
			
		||||
function wish_battery_main() {
 | 
			
		||||
	local path=/sys/class/power_supply/$WISH_BATTERY_ID
 | 
			
		||||
	local battery=$(($(cat $path/charge_now) * 100 / $(cat $path/charge_full)))%
 | 
			
		||||
	if [[ $(cat $path/status) == "Charging" ]] ||
 | 
			
		||||
		[[ $(cat $path/status) == "Full" ]]; then
 | 
			
		||||
		battery="$WISH_BATTERY_CHARGING $battery"
 | 
			
		||||
	local battery
 | 
			
		||||
	if [[ -f $path/charge_now ]]; then
 | 
			
		||||
		battery=$(($(cat $path/charge_now) * 100 / $(cat $path/charge_full)))%
 | 
			
		||||
		if [[ $(cat $path/status) == "Charging" ]] ||
 | 
			
		||||
			[[ $(cat $path/status) == "Full" ]]; then
 | 
			
		||||
			battery="$WISH_BATTERY_CHARGING $battery"
 | 
			
		||||
		else
 | 
			
		||||
			battery="$WISH_BATTERY_DISCHARGING $battery"
 | 
			
		||||
		fi
 | 
			
		||||
	else
 | 
			
		||||
		battery="$WISH_BATTERY_DISCHARGING $battery"
 | 
			
		||||
		battery="$WISH_BATTERY_ID not found"
 | 
			
		||||
	fi
 | 
			
		||||
	wish_append $WISH_BATTERY_BG $WISH_BATTERY_FG " $battery "
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -9,10 +9,10 @@ function wish_custom_text_end() {
 | 
			
		||||
function wish_custom_text_set_colors() {
 | 
			
		||||
	WISH_CUSTOM_TEXT_FG=${WISH_CUSTOM_TEXT_FG:-$WISH_DEFAULT_FG}
 | 
			
		||||
	WISH_CUSTOM_TEXT_BG=${WISH_CUSTOM_TEXT_BG:-$WISH_DEFAULT_BG}
 | 
			
		||||
	local default_text='To set custom text here, add WISH_CUSTOM_TEXT="your text" in ~/.bashrc'
 | 
			
		||||
	WISH_CUSTOM_TEXT=${WISH_CUSTOM_TEXT:-$default_text}
 | 
			
		||||
	local default_text='To set custom text here, add text="your text" in your config'
 | 
			
		||||
	WISH_CUSTOM_TEXT_TEXT=${WISH_CUSTOM_TEXT_TEXT:-$default_text}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function wish_custom_text_main() {
 | 
			
		||||
	wish_append $WISH_CUSTOM_TEXT_BG $WISH_CUSTOM_TEXT_FG "$WISH_CUSTOM_TEXT"
 | 
			
		||||
	wish_append $WISH_CUSTOM_TEXT_BG $WISH_CUSTOM_TEXT_FG "$WISH_CUSTOM_TEXT_TEXT"
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										59
									
								
								plugins/path_powerline.sh
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										59
									
								
								plugins/path_powerline.sh
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,59 @@
 | 
			
		||||
function wish_path_powerline_start() {
 | 
			
		||||
	return 0
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function wish_path_powerline_end() {
 | 
			
		||||
	return 0
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function wish_path_powerline_set_colors() {
 | 
			
		||||
	WISH_PATH_POWERLINE_FG=${WISH_PATH_POWERLINE_FG:-$WISH_DEFAULT_FG}
 | 
			
		||||
	WISH_PATH_POWERLINE_BG=${WISH_PATH_POWERLINE_BG:-$WISH_DEFAULT_BG}
 | 
			
		||||
	WISH_PATH_POWERLINE_NO_WRITE_SUFFIX=${WISH_PATH_POWERLINE_NO_WRITE_SUFFIX:- }
 | 
			
		||||
	WISH_PATH_POWERLINE_MAX_PERC=${WISH_PATH_POWERLINE_MAX_PERC:-0}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function wish_path_lensum() {
 | 
			
		||||
	sum=0
 | 
			
		||||
	for i in $*; do
 | 
			
		||||
		sum=$(($sum + ${#i}))
 | 
			
		||||
	done
 | 
			
		||||
	echo $sum
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function wish_path_powerline_shrink() {
 | 
			
		||||
	local IFS='/'
 | 
			
		||||
	local path=( $1 )
 | 
			
		||||
	local max=$(( $2 - 3 * ${#path[@]} ))
 | 
			
		||||
	for ((i=0; i <$((${#path[@]} - 1)); i++)); do
 | 
			
		||||
		path[$i]=${path[$i]:0:1}
 | 
			
		||||
		if [[ $(wish_path_lensum ${path[@]}) -lt $max ]]; then
 | 
			
		||||
			local short_path=""
 | 
			
		||||
			for i in ${path[@]}; do
 | 
			
		||||
				short_path+="$i/"
 | 
			
		||||
			done
 | 
			
		||||
			echo "${short_path%/}"
 | 
			
		||||
			return
 | 
			
		||||
		fi
 | 
			
		||||
	done
 | 
			
		||||
	local short_path=""
 | 
			
		||||
	for i in ${path[@]}; do
 | 
			
		||||
		short_path+="$i/"
 | 
			
		||||
	done
 | 
			
		||||
	echo "${short_path%/}"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function wish_path_powerline_main() {
 | 
			
		||||
	local path="${PWD/#$HOME/\~}"
 | 
			
		||||
	if [[ $WISH_PATH_POWERLINE_MAX_PERC -ne 0 && ${#path} -ge $WISH_PATH_POWERLINE_MAX_LEN ]] ; then
 | 
			
		||||
		local max=$(($WISH_PATH_POWERLINE_MAX_PERC * $(wish_remaining_chars) / 100))
 | 
			
		||||
		local path=$(wish_path_powerline_shrink "$path" "$max")
 | 
			
		||||
	fi
 | 
			
		||||
	local path="${path//\//  }"
 | 
			
		||||
	if [[ -w $PWD ]]; then
 | 
			
		||||
		local path=" $path "
 | 
			
		||||
	else
 | 
			
		||||
		local path=" $path$WISH_PATH_POWERLINE_NO_WRITE_SUFFIX "
 | 
			
		||||
	fi
 | 
			
		||||
	wish_append $WISH_PATH_POWERLINE_BG $WISH_PATH_POWERLINE_FG "$path"
 | 
			
		||||
}
 | 
			
		||||
@@ -13,7 +13,7 @@ function wish_python_venv_set_colors() {
 | 
			
		||||
 | 
			
		||||
function wish_python_venv_main() {
 | 
			
		||||
	if [[ -v VIRTUAL_ENV ]]; then
 | 
			
		||||
		local venv=$(echo $VIRTUAL_ENV | sed 's|.*/||')
 | 
			
		||||
		local venv=$(echo $VIRTUAL_ENV | sed ';s|/.venv$||;s|.*/||')
 | 
			
		||||
		wish_append $WISH_PYTHON_VENV_BG $WISH_PYTHON_VENV_FG " $venv "
 | 
			
		||||
	else
 | 
			
		||||
		wish_append $WISH_PYTHON_VENV_BG $WISH_PYTHON_VENV_FG ""
 | 
			
		||||
 
 | 
			
		||||
@@ -10,7 +10,7 @@ function wish_vcs_set_colors() {
 | 
			
		||||
	WISH_VCS_FG=${WISH_VCS_FG:-$WISH_DEFAULT_FG}
 | 
			
		||||
	WISH_VCS_BG=${WISH_VCS_BG:-$WISH_DEFAULT_BG}
 | 
			
		||||
	WISH_VCS_GIT_SYMBOL=${WISH_VCS_GIT:-}
 | 
			
		||||
	WISH_VCS_DEFAULT=${WISH_VCS_DEFAULT:-$}
 | 
			
		||||
	[[ -v WISH_VCS_DEFAULT ]] || WISH_VCS_DEFAULT="$"
 | 
			
		||||
	WISH_VCS_GIT_UNTRACKED_SYMBOL=${WISH_VCS_GIT_UNTRACKED_SYMBOL:-●}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -32,7 +32,7 @@ function wish_vcs_main() {
 | 
			
		||||
		fi
 | 
			
		||||
		wish_append $WISH_VCS_BG $WISH_VCS_FG "$git"
 | 
			
		||||
	else
 | 
			
		||||
		wish_append $WISH_VCS_BG $WISH_VCS_FG " $WISH_VCS_DEFAULT "
 | 
			
		||||
		wish_append $WISH_VCS_BG $WISH_VCS_FG "$WISH_VCS_DEFAULT"
 | 
			
		||||
	fi
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -5,9 +5,21 @@ local gradient=(226 118 37 66 60 237 233)
 | 
			
		||||
local fg_gradient=(16 16 16 16 16 15 15)
 | 
			
		||||
local j=0
 | 
			
		||||
for i in ${WISH_PLUGINS[@]}; do
 | 
			
		||||
	[[ $i == "newline" ]] && j=0 && continue
 | 
			
		||||
	eval WISH_$(echo $i | tr '[:lower:]' '[:upper:]')_BG=${gradient[$j]}
 | 
			
		||||
	eval WISH_$(echo $i | tr '[:lower:]' '[:upper:]')_FG=${fg_gradient[$j]}
 | 
			
		||||
	[[ $i =~ newline$ ]] && j=0 && continue
 | 
			
		||||
	eval WISH_${i^^}_BG=${gradient[$j]}
 | 
			
		||||
	eval WISH_${i^^}_FG=${fg_gradient[$j]}
 | 
			
		||||
	((j++))
 | 
			
		||||
	if [[ $j -eq ${#gradient[@]} ]]; then
 | 
			
		||||
		j=0
 | 
			
		||||
	fi
 | 
			
		||||
done
 | 
			
		||||
 | 
			
		||||
j=0
 | 
			
		||||
for ((idx=$((${#WISH_RIGHT_PLUGINS[@]} - 1)); idx >= 0; idx--)); do
 | 
			
		||||
	i=${WISH_RIGHT_PLUGINS[$idx]}
 | 
			
		||||
	[[ $i =~ newline$ ]] && j=0 && continue
 | 
			
		||||
	eval WISH_${i^^}_BG=${gradient[$j]}
 | 
			
		||||
	eval WISH_${i^^}_FG=${fg_gradient[$j]}
 | 
			
		||||
	((j++))
 | 
			
		||||
	if [[ $j -eq ${#gradient[@]} ]]; then
 | 
			
		||||
		j=0
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										32
									
								
								themes/icy_candy.sh
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								themes/icy_candy.sh
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,32 @@
 | 
			
		||||
#!/usr/bin/env bash
 | 
			
		||||
 | 
			
		||||
function wish_icy_candy_theme {
 | 
			
		||||
	local i
 | 
			
		||||
	local l_gradient=(f5a9b8 f6b7c3 f8c5cf fad4db fbe2e7 fdf0f3 ffffff)
 | 
			
		||||
	local r_gradient=(5bcefa 76d6fa 91defb ade6fc c8eefd e3f6fe ffffff)
 | 
			
		||||
	local fg_gradient=(000000 000000 000000 000000 000000 000000 000000)
 | 
			
		||||
	local j=0
 | 
			
		||||
	for i in "${WISH_PLUGINS[@]}"; do
 | 
			
		||||
		[[ $i =~ newline$ ]] && j=0 && continue
 | 
			
		||||
		eval "WISH_${i^^}_FG=${fg_gradient[$j]}"
 | 
			
		||||
		eval "WISH_${i^^}_BG=${l_gradient[$j]}"
 | 
			
		||||
		((j++))
 | 
			
		||||
		if [[ $j -eq ${#l_gradient[@]} ]]; then
 | 
			
		||||
			j=0
 | 
			
		||||
		fi
 | 
			
		||||
	done
 | 
			
		||||
 | 
			
		||||
	j=0
 | 
			
		||||
	for ((idx=$((${#WISH_RIGHT_PLUGINS[@]} - 1)); idx >= 0; idx--)); do
 | 
			
		||||
		i=${WISH_RIGHT_PLUGINS[$idx]}
 | 
			
		||||
		[[ $i =~ newline$ ]] && j=0 && continue
 | 
			
		||||
		eval "WISH_${i^^}_BG=${r_gradient[$j]}"
 | 
			
		||||
		eval "WISH_${i^^}_FG=${fg_gradient[$j]}"
 | 
			
		||||
		((j++))
 | 
			
		||||
		if [[ $j -eq ${#r_gradient[@]} ]]; then
 | 
			
		||||
			j=0
 | 
			
		||||
		fi
 | 
			
		||||
	done
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
wish_icy_candy_theme
 | 
			
		||||
@@ -5,9 +5,21 @@ local i
 | 
			
		||||
local gradient=(e7c547 c0e551 82e35a 62e177 6bdfb3 73d4dd 7aa6da)
 | 
			
		||||
local j=0
 | 
			
		||||
for i in ${WISH_PLUGINS[@]}; do
 | 
			
		||||
	[[ $i == "newline" ]] && j=0 && continue
 | 
			
		||||
	eval WISH_$(echo $i | tr '[:lower:]' '[:upper:]')_BG=-1
 | 
			
		||||
	eval WISH_$(echo $i | tr '[:lower:]' '[:upper:]')_FG=${gradient[$j]}
 | 
			
		||||
	[[ $i =~ newline$ ]] && j=0 && continue
 | 
			
		||||
	eval WISH_${i^^}_BG=-1
 | 
			
		||||
	eval WISH_${i^^}_FG=${gradient[$j]}
 | 
			
		||||
	((j++))
 | 
			
		||||
	if [[ $j -eq ${#gradient[@]} ]]; then
 | 
			
		||||
		j=0
 | 
			
		||||
	fi
 | 
			
		||||
done
 | 
			
		||||
 | 
			
		||||
j=0
 | 
			
		||||
for ((idx=$((${#WISH_RIGHT_PLUGINS[@]} - 1)); idx >= 0; idx--)); do
 | 
			
		||||
	i=${WISH_RIGHT_PLUGINS[$idx]}
 | 
			
		||||
	[[ $i =~ newline$ ]] && j=0 && continue
 | 
			
		||||
	eval WISH_${i^^}_BG=-1
 | 
			
		||||
	eval WISH_${i^^}_FG=${gradient[$j]}
 | 
			
		||||
	((j++))
 | 
			
		||||
	if [[ $j -eq ${#gradient[@]} ]]; then
 | 
			
		||||
		j=0
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										31
									
								
								themes/luminus.sh
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								themes/luminus.sh
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,31 @@
 | 
			
		||||
#!/usr/bin/env bash
 | 
			
		||||
 | 
			
		||||
function wish_luminous_theme {
 | 
			
		||||
	local i
 | 
			
		||||
	local gradient=(ef7126 f7894c fea16f ffb892 ffd0b5 ffe7da ffffff)
 | 
			
		||||
	local fg_gradient=(000000 000000 000000 000000 000000 000000 000000)
 | 
			
		||||
	local j=0
 | 
			
		||||
	for i in "${WISH_PLUGINS[@]}"; do
 | 
			
		||||
		[[ $i =~ newline$ ]] && j=0 && continue
 | 
			
		||||
		eval "WISH_${i^^}_FG=${fg_gradient[$j]}"
 | 
			
		||||
		eval "WISH_${i^^}_BG=${gradient[$j]}"
 | 
			
		||||
		((j++))
 | 
			
		||||
		if [[ $j -eq ${#gradient[@]} ]]; then
 | 
			
		||||
			j=0
 | 
			
		||||
		fi
 | 
			
		||||
	done
 | 
			
		||||
 | 
			
		||||
	j=0
 | 
			
		||||
	for ((idx=$((${#WISH_RIGHT_PLUGINS[@]} - 1)); idx >= 0; idx--)); do
 | 
			
		||||
		i=${WISH_RIGHT_PLUGINS[$idx]}
 | 
			
		||||
		[[ $i =~ newline$ ]] && j=0 && continue
 | 
			
		||||
		eval "WISH_${i^^}_BG=${gradient[$j]}"
 | 
			
		||||
		eval "WISH_${i^^}_FG=${fg_gradient[$j]}"
 | 
			
		||||
		((j++))
 | 
			
		||||
		if [[ $j -eq ${#gradient[@]} ]]; then
 | 
			
		||||
			j=0
 | 
			
		||||
		fi
 | 
			
		||||
	done
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
wish_luminous_theme
 | 
			
		||||
@@ -1,7 +1,7 @@
 | 
			
		||||
WISH_DEFAULT_BG=-1
 | 
			
		||||
WISH_DEFAULT_FG=-1
 | 
			
		||||
WISH_POWERLINE=0
 | 
			
		||||
for i in ${WISH_PLUGINS[@]}; do
 | 
			
		||||
	eval WISH_$(echo $i | tr '[:lower:]' '[:upper:]')_BG=-1
 | 
			
		||||
	eval WISH_$(echo $i | tr '[:lower:]' '[:upper:]')_FG=-1
 | 
			
		||||
for i in ${WISH_PLUGINS[@]} ${WISH_RIGHT_PLUGINS[@]}; do
 | 
			
		||||
	eval WISH_${i^^}_BG=-1
 | 
			
		||||
	eval WISH_${i^^}_FG=-1
 | 
			
		||||
done
 | 
			
		||||
 
 | 
			
		||||
@@ -5,9 +5,21 @@ local gradient=(ffff5f 7ad767 66b097 5e7388 534d61 3a3338 121212)
 | 
			
		||||
local fg_gradient=(000000 000000 000000 000000 000000 ffffff ffffff)
 | 
			
		||||
local j=0
 | 
			
		||||
for i in ${WISH_PLUGINS[@]}; do
 | 
			
		||||
	[[ $i == "newline" ]] && j=0 && continue
 | 
			
		||||
	eval WISH_$(echo $i | tr '[:lower:]' '[:upper:]')_BG=${gradient[$j]}
 | 
			
		||||
	eval WISH_$(echo $i | tr '[:lower:]' '[:upper:]')_FG=${fg_gradient[$j]}
 | 
			
		||||
	[[ $i =~ newline$ ]] && j=0 && continue
 | 
			
		||||
	eval WISH_${i^^}_BG=${gradient[$j]}
 | 
			
		||||
	eval WISH_${i^^}_FG=${fg_gradient[$j]}
 | 
			
		||||
	((j++))
 | 
			
		||||
	if [[ $j -eq ${#gradient[@]} ]]; then
 | 
			
		||||
		j=0
 | 
			
		||||
	fi
 | 
			
		||||
done
 | 
			
		||||
 | 
			
		||||
j=0
 | 
			
		||||
for ((idx=$((${#WISH_RIGHT_PLUGINS[@]} - 1)); idx >= 0; idx--)); do
 | 
			
		||||
	i=${WISH_RIGHT_PLUGINS[$idx]}
 | 
			
		||||
	[[ $i =~ newline$ ]] && j=0 && continue
 | 
			
		||||
	eval WISH_${i^^}_BG=${gradient[$j]}
 | 
			
		||||
	eval WISH_${i^^}_FG=${fg_gradient[$j]}
 | 
			
		||||
	((j++))
 | 
			
		||||
	if [[ $j -eq ${#gradient[@]} ]]; then
 | 
			
		||||
		j=0
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										140
									
								
								wish.py
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										140
									
								
								wish.py
									
									
									
									
									
										Executable file
									
								
							@@ -0,0 +1,140 @@
 | 
			
		||||
#!/usr/bin/env python3
 | 
			
		||||
"""
 | 
			
		||||
Generate function wrappers from config for wish.
 | 
			
		||||
 | 
			
		||||
wish.py works by writing plugins which are isolated from the global plugins.
 | 
			
		||||
It assigns all the config to relevant variables inside a wrapper. e.g.
 | 
			
		||||
 | 
			
		||||
If the config file is
 | 
			
		||||
 | 
			
		||||
```
 | 
			
		||||
|left|
 | 
			
		||||
[plugin]
 | 
			
		||||
name = date
 | 
			
		||||
format = %F
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
wish.py creates a wrapper around date as 0_date where 0 is the index of plugin.
 | 
			
		||||
Inside the wrapper, in each function, it sets WISH_DATE_FORMAT="%F" and
 | 
			
		||||
WISH_DATE_BG=$WISH_0_DATE_BG (same for FG), so the plugin sees its config as
 | 
			
		||||
defined in the config file. After calling the plugin's relevant function, it
 | 
			
		||||
sets WISH_0_DATE_BG=$WISH_DATE_BG (same for FG) in case, the plugin has changed
 | 
			
		||||
it). This allows multiple instances of the same plugin to coexist with
 | 
			
		||||
different config and different themes.
 | 
			
		||||
"""
 | 
			
		||||
 | 
			
		||||
from os.path import isfile
 | 
			
		||||
import shlex
 | 
			
		||||
import sys
 | 
			
		||||
 | 
			
		||||
import ginie
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def parse_core(core):
 | 
			
		||||
    "Parses a core block"
 | 
			
		||||
    config = core["config"]
 | 
			
		||||
    for key in core["config"]:
 | 
			
		||||
        print("WISH_{}={}".format(key.upper(), shlex.quote(config[key])))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def parse_plugin(plugin, plugin_idx):
 | 
			
		||||
    "Parses a plugin and writes a wrapper around it"
 | 
			
		||||
    config = plugin["config"]
 | 
			
		||||
    try:
 | 
			
		||||
        plugin_name = config["name"].strip().lower()
 | 
			
		||||
        config["name"] = plugin_name
 | 
			
		||||
    except KeyError:
 | 
			
		||||
        return False
 | 
			
		||||
 | 
			
		||||
    keys_from_source = ("BG", "FG")
 | 
			
		||||
    for j in ("start", "end", "set_colors", "main"):
 | 
			
		||||
        print("function wish_{}_{}_{}()".format(plugin_idx, plugin_name, j))
 | 
			
		||||
        print("{")
 | 
			
		||||
        for key in keys_from_source:
 | 
			
		||||
            print("\tlocal WISH_{0}_{2}=$WISH_{1}_{0}_{2}".format(
 | 
			
		||||
                plugin_name.upper(),
 | 
			
		||||
                plugin_idx,
 | 
			
		||||
                key.upper()
 | 
			
		||||
            ))
 | 
			
		||||
        for key in config:
 | 
			
		||||
            if key == "name":
 | 
			
		||||
                continue
 | 
			
		||||
            print("\tlocal WISH_{}_{}={}".format(plugin_name.upper(),
 | 
			
		||||
                                                 key.upper(),
 | 
			
		||||
                                                 shlex.quote(config[key])))
 | 
			
		||||
        print("\twish_{}_{} $*".format(plugin_name, j))
 | 
			
		||||
        print("\tlocal err=$?")
 | 
			
		||||
        for key in keys_from_source:
 | 
			
		||||
            print("\tWISH_{1}_{0}_{2}=$WISH_{0}_{2}".format(
 | 
			
		||||
                plugin_name.upper(),
 | 
			
		||||
                plugin_idx,
 | 
			
		||||
                key.upper()
 | 
			
		||||
            ))
 | 
			
		||||
        print("\treturn $err")
 | 
			
		||||
        print("}")
 | 
			
		||||
    return True
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def print_plugin_list(name, array, always=False):
 | 
			
		||||
    "Prints a list of plugins as a bash array"
 | 
			
		||||
    if array or always:
 | 
			
		||||
        print("{}=(".format(name))
 | 
			
		||||
        for plugin in array:
 | 
			
		||||
            print("\t" + plugin)
 | 
			
		||||
        print(")")
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def main():
 | 
			
		||||
    "Parse a config file passed as first argument"
 | 
			
		||||
    config_file = []
 | 
			
		||||
    for file_name in sys.argv[1:]:
 | 
			
		||||
        if isfile(file_name):
 | 
			
		||||
            with open(file_name) as file:
 | 
			
		||||
                config_file += ginie.load(file)
 | 
			
		||||
        else:
 | 
			
		||||
            print("echo Invalid config file: {}".format(
 | 
			
		||||
                shlex.quote(file_name)))
 | 
			
		||||
 | 
			
		||||
    plugin_idx = 0
 | 
			
		||||
    plugins_to_source = []
 | 
			
		||||
    left_plugins = []
 | 
			
		||||
    right_plugins = []
 | 
			
		||||
    for i in config_file:
 | 
			
		||||
        kind = i["type"]
 | 
			
		||||
        name = i["name"]
 | 
			
		||||
        # Parse core blocks outside a section.
 | 
			
		||||
        # No other blocks outside a section need to be parsed for now.
 | 
			
		||||
        if kind == "block" and name == "core":
 | 
			
		||||
            parse_core(i)
 | 
			
		||||
        elif kind == "section":
 | 
			
		||||
            # All sections other than left and right are skipped.
 | 
			
		||||
            if name not in ("left", "right"):
 | 
			
		||||
                continue
 | 
			
		||||
            for block in i["blocks"]:
 | 
			
		||||
                if block["name"] == "core":
 | 
			
		||||
                    parse_core(block)
 | 
			
		||||
                elif block["name"] == "plugin" and parse_plugin(block,
 | 
			
		||||
                                                                plugin_idx):
 | 
			
		||||
                    plugin_name = "{}_{}".format(plugin_idx,
 | 
			
		||||
                                                 block["config"]["name"])
 | 
			
		||||
                    if name == "left":
 | 
			
		||||
                        left_plugins.append(plugin_name)
 | 
			
		||||
                    else:
 | 
			
		||||
                        right_plugins.append(plugin_name)
 | 
			
		||||
                    plugins_to_source.append(block["config"]["name"])
 | 
			
		||||
                    plugin_idx += 1
 | 
			
		||||
 | 
			
		||||
    print_plugin_list("WISH_PLUGINS", left_plugins)
 | 
			
		||||
    print_plugin_list("WISH_RIGHT_PLUGINS", right_plugins)
 | 
			
		||||
    print_plugin_list("WISH_PLUGINS_SOURCE", plugins_to_source)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# Python 2 patch
 | 
			
		||||
# TODO: Write a better patch for Python 2
 | 
			
		||||
try:
 | 
			
		||||
    shlex.quote
 | 
			
		||||
except AttributeError:
 | 
			
		||||
    shlex.quote = lambda x: x
 | 
			
		||||
 | 
			
		||||
if __name__ == "__main__":
 | 
			
		||||
    main()
 | 
			
		||||
							
								
								
									
										267
									
								
								wish.sh
									
									
									
									
									
								
							
							
						
						
									
										267
									
								
								wish.sh
									
									
									
									
									
								
							@@ -1,107 +1,256 @@
 | 
			
		||||
#!/usr/bin/env bash
 | 
			
		||||
# shellcheck disable=SC1090
 | 
			
		||||
 | 
			
		||||
# INTERNAL USE ONLY! Do not use this in plugins.
 | 
			
		||||
function wish_print_right_prompt() {
 | 
			
		||||
	local idx=0
 | 
			
		||||
	for i in "${WISH_RPL[@]}"; do
 | 
			
		||||
		echo "\e[$((COLUMNS - i + 1))G${WISH_RIGHT_PS1[idx]}"
 | 
			
		||||
		((idx++))
 | 
			
		||||
	done
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function wish_init() {
 | 
			
		||||
	# Source all plugins
 | 
			
		||||
	local i
 | 
			
		||||
	local j
 | 
			
		||||
	for i in ${WISH_PLUGINS[@]}; do
 | 
			
		||||
		for j in "$XDG_CONFIG_HOME" "/usr/share" "$HOME/.config"; do
 | 
			
		||||
			source "$j/wish/plugins/$i.sh" &> /dev/null && break
 | 
			
		||||
	# Find default config file if WISH_CONFIG_FILE is unset
 | 
			
		||||
	if [[ ! -v WISH_CONFIG_FILE ]]; then
 | 
			
		||||
		for path in "$XDG_CONFIG_HOME" "/usr/share" "$HOME/.config"; do
 | 
			
		||||
			if [[ -f "$path/wish/config.gie" ]]; then
 | 
			
		||||
				WISH_CONFIG_FILE="$path/wish/config.gie"
 | 
			
		||||
				break
 | 
			
		||||
			fi
 | 
			
		||||
		done
 | 
			
		||||
		[[ $? -ne 0 ]] && echo "Plugin $i not found." >&2
 | 
			
		||||
	fi
 | 
			
		||||
	# Source config files
 | 
			
		||||
	for path in "$XDG_CONFIG_HOME" "/usr/share" "$HOME/.config"; do
 | 
			
		||||
		if [[ -f "$path/wish/wish.py" ]]; then
 | 
			
		||||
			source <("$path/wish/wish.py" "${WISH_CONFIG_FILE[@]}")
 | 
			
		||||
			break
 | 
			
		||||
		fi
 | 
			
		||||
	done
 | 
			
		||||
 | 
			
		||||
	# Set defaults for core if not found
 | 
			
		||||
	: "${WISH_POWERLINE_LEFT:=}"
 | 
			
		||||
	: "${WISH_POWERLINE_RIGHT=}"
 | 
			
		||||
	# Source all plugins
 | 
			
		||||
	# If WISH_CONFIG_FILE is not set, then assume that the user hasn't updated
 | 
			
		||||
	# to a config file yet. Set WISH_PLUGINS_SOURCE=WISH_PLUGINS.
 | 
			
		||||
	if [[ ! -v WISH_CONFIG_FILE ]]; then
 | 
			
		||||
		WISH_PLUGINS_SOURCE=("${WISH_PLUGINS[@]}" "${WISH_RIGHT_PLUGINS[@]}")
 | 
			
		||||
	fi
 | 
			
		||||
	local plugin
 | 
			
		||||
	local path
 | 
			
		||||
	for plugin in "${WISH_PLUGINS_SOURCE[@]}"; do
 | 
			
		||||
		if ! for path in "$XDG_CONFIG_HOME" "/usr/share" "$HOME/.config"; do
 | 
			
		||||
			source "$path/wish/plugins/$plugin.sh" &> /dev/null && break
 | 
			
		||||
		done; then
 | 
			
		||||
			echo "Plugin $plugin not found." >&2
 | 
			
		||||
		fi
 | 
			
		||||
	done
 | 
			
		||||
 | 
			
		||||
	# Source theme
 | 
			
		||||
	WISH_THEME=${WISH_THEME:-plain}
 | 
			
		||||
	for i in "$XDG_CONFIG_HOME" "/usr/share" "$HOME/.config"; do
 | 
			
		||||
		source "$i/wish/themes/$WISH_THEME.sh" &> /dev/null && break
 | 
			
		||||
	while :; do
 | 
			
		||||
		if for theme in "$XDG_CONFIG_HOME" "/usr/share" "$HOME/.config"; do
 | 
			
		||||
			source "$theme/wish/themes/$WISH_THEME.sh" &> /dev/null && break
 | 
			
		||||
		done; then
 | 
			
		||||
			break
 | 
			
		||||
		else
 | 
			
		||||
			echo "Theme $WISH_THEME not found. Using theme plain." >&2
 | 
			
		||||
			if [[ $WISH_THEME == "plain" ]]; then
 | 
			
		||||
				break
 | 
			
		||||
			else
 | 
			
		||||
				WISH_THEME=plain
 | 
			
		||||
			fi
 | 
			
		||||
		fi
 | 
			
		||||
	done
 | 
			
		||||
 | 
			
		||||
	[[ $? -ne 0 ]] && echo "Theme $WISH_THEME not found." >&2
 | 
			
		||||
 | 
			
		||||
	# Call plugins to set colors
 | 
			
		||||
	for i in ${WISH_PLUGINS[@]}; do
 | 
			
		||||
		eval wish_$(echo $i)_set_colors $prev
 | 
			
		||||
	for plugin in "${WISH_PLUGINS[@]}" "${WISH_RIGHT_PLUGINS[@]}"; do
 | 
			
		||||
		"wish_${plugin}_set_colors" "$prev"
 | 
			
		||||
	done
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
# Usage: color_to_escape_code [3|4] color
 | 
			
		||||
#
 | 
			
		||||
# Parameters:
 | 
			
		||||
# - [3|4]: Use 3 if escape code is for foreground, 4 for background
 | 
			
		||||
# - color: -1 to reset, 0-255 for terminal color codes. 6 digit hexadecimal
 | 
			
		||||
# value for true color.
 | 
			
		||||
#
 | 
			
		||||
# Return value: Prints escape code that sets the fg/bg as requested.
 | 
			
		||||
function color_to_escape_code() {
 | 
			
		||||
	local choice=$1
 | 
			
		||||
	local color=$2
 | 
			
		||||
	if [[ $color == -1 ]]; then
 | 
			
		||||
		echo "\[\033[0;5;0m\]"
 | 
			
		||||
	else
 | 
			
		||||
		if [[ ${#fg_code} -eq 6 ]]; then
 | 
			
		||||
			local r=$(( 16#${color:0:2} ))
 | 
			
		||||
			local g=$(( 16#${color:2:2} ))
 | 
			
		||||
			local b=$(( 16#${color:4:2} ))
 | 
			
		||||
			echo "\[\033[${choice}8;2;$r;$g;${b}m\]"
 | 
			
		||||
		else
 | 
			
		||||
			echo "\[\033[${choice}8;5;${fg_code}m\]"
 | 
			
		||||
		fi
 | 
			
		||||
	fi
 | 
			
		||||
}
 | 
			
		||||
# INTERNAL USE ONLY! Do not use this in plugins.
 | 
			
		||||
# Usage: wish_append_left escape_codes text
 | 
			
		||||
function wish_append_left() {
 | 
			
		||||
	local text="$2"
 | 
			
		||||
	local colors="$1"
 | 
			
		||||
	local prompt_text="${text@P}"
 | 
			
		||||
	if [[ $text == "\n" ]]; then
 | 
			
		||||
		((WISH_LPLINE++))
 | 
			
		||||
		WISH_LPL=("${WISH_LPL[@]}" 0)
 | 
			
		||||
		WISH_LEFT_PS1="$WISH_LEFT_PS1$colors$text"
 | 
			
		||||
	else
 | 
			
		||||
		if [[ $((${WISH_LPL[$WISH_LPLINE]} + ${#prompt_text})) -lt $COLUMNS ]]; then
 | 
			
		||||
			WISH_LEFT_PS1="$WISH_LEFT_PS1$colors$text"
 | 
			
		||||
			WISH_LPL[$WISH_LPLINE]=$((${WISH_LPL[$WISH_LPLINE]} + ${#prompt_text}))
 | 
			
		||||
		fi
 | 
			
		||||
	fi
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
# INTERNAL USE ONLY! Do not use this in plugins.
 | 
			
		||||
# Usage: wish_append_right escape_codes text
 | 
			
		||||
function wish_append_right() {
 | 
			
		||||
	local text="$2"
 | 
			
		||||
	local colors="$1"
 | 
			
		||||
	local prompt_text="${text@P}"
 | 
			
		||||
	if [[ $text == "\n" ]]; then
 | 
			
		||||
		((WISH_RPLINE++))
 | 
			
		||||
		WISH_RIGHT_PS1=("${WISH_RIGHT_PS1[@]}" "")
 | 
			
		||||
		WISH_RPL=("${WISH_RPL[@]}" 0)
 | 
			
		||||
	elif [[ $((${WISH_LPL[$WISH_RPLINE]} + ${WISH_RPL[$WISH_RPLINE]} + ${#prompt_text})) -lt $COLUMNS ]]; then
 | 
			
		||||
		WISH_RIGHT_PS1[$WISH_RPLINE]="${WISH_RIGHT_PS1[$WISH_RPLINE]}$colors$text"
 | 
			
		||||
		WISH_RPL[$WISH_RPLINE]=$((${WISH_RPL[$WISH_RPLINE]} + ${#prompt_text}))
 | 
			
		||||
	fi
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
# Public API
 | 
			
		||||
# Usage: wish_append bg fg text
 | 
			
		||||
#
 | 
			
		||||
# Parameters:
 | 
			
		||||
# - fg, bg: -1 to reset, 0-255 for terminal color codes. 6 digit hexadecimal
 | 
			
		||||
# value for true color.
 | 
			
		||||
# - text: Text of the plugin
 | 
			
		||||
#
 | 
			
		||||
# Return value: None
 | 
			
		||||
function wish_append() {
 | 
			
		||||
	local bg_code=$1
 | 
			
		||||
	local fg_code=$2
 | 
			
		||||
	local text=$3
 | 
			
		||||
	if [[ $fg_code == -1 ]]; then
 | 
			
		||||
		local fg="\[\033[0;5;0m\]"
 | 
			
		||||
	else
 | 
			
		||||
		if [[ ${#fg_code} -eq 6 ]]; then
 | 
			
		||||
			local color=($(echo $fg_code | grep -o .))
 | 
			
		||||
			local r=$(( 16#${color[0]}${color[1]} ))
 | 
			
		||||
			local g=$(( 16#${color[2]}${color[3]} ))
 | 
			
		||||
			local b=$(( 16#${color[4]}${color[5]} ))
 | 
			
		||||
			local fg="\[\033[38;2;$r;$g;${b}m\]"
 | 
			
		||||
		else
 | 
			
		||||
			local fg="\[\033[38;5;${fg_code}m\]"
 | 
			
		||||
		fi
 | 
			
		||||
	fi
 | 
			
		||||
	if [[ $bg_code == -1 ]]; then
 | 
			
		||||
		local bg="\[\033[0;5;0m\]"
 | 
			
		||||
	else
 | 
			
		||||
		if [[ ${#bg_code} -eq 6 ]]; then
 | 
			
		||||
			local color=($(echo $bg_code | grep -o .))
 | 
			
		||||
			local r=$(( 16#${color[0]}${color[1]} ))
 | 
			
		||||
			local g=$(( 16#${color[2]}${color[3]} ))
 | 
			
		||||
			local b=$(( 16#${color[4]}${color[5]} ))
 | 
			
		||||
			local bg="\[\033[48;2;$r;$g;${b}m\]"
 | 
			
		||||
		else
 | 
			
		||||
			local bg="\[\033[48;5;${bg_code}m\]"
 | 
			
		||||
		fi
 | 
			
		||||
	fi
 | 
			
		||||
	local fg
 | 
			
		||||
	local bg
 | 
			
		||||
	fg=$(color_to_escape_code 3 "$fg_code")
 | 
			
		||||
	bg=$(color_to_escape_code 4 "$bg_code")
 | 
			
		||||
 | 
			
		||||
	if [[ $fg_code == -1 ]]; then
 | 
			
		||||
		PS1="$PS1$fg${bg}$text"
 | 
			
		||||
		case $WISH_STATE in
 | 
			
		||||
			0)
 | 
			
		||||
				wish_append_left "$fg$bg" "$text"
 | 
			
		||||
				;;
 | 
			
		||||
			1)
 | 
			
		||||
				wish_append_right "$fg$bg" "$text"
 | 
			
		||||
				;;
 | 
			
		||||
		esac
 | 
			
		||||
	else
 | 
			
		||||
		PS1="$PS1$bg${fg}$text"
 | 
			
		||||
		case $WISH_STATE in
 | 
			
		||||
			0)
 | 
			
		||||
				wish_append_left "$bg$fg" "$text"
 | 
			
		||||
				;;
 | 
			
		||||
			1)
 | 
			
		||||
				wish_append_right "$bg$fg" "$text"
 | 
			
		||||
				;;
 | 
			
		||||
		esac
 | 
			
		||||
	fi
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
# Public API
 | 
			
		||||
# Usage: wish_remaining_chars
 | 
			
		||||
# Parameters: None
 | 
			
		||||
# Return Value: Capture stdout to get the remaining characters available in the
 | 
			
		||||
# line.
 | 
			
		||||
wish_remaining_chars() {
 | 
			
		||||
	if [[ $WISH_STATE -eq 0 ]]; then
 | 
			
		||||
		echo "$(( COLUMNS - ${WISH_LPL[$WISH_LPLINE]} ))"
 | 
			
		||||
	else
 | 
			
		||||
		echo "$(( COLUMNS - ${WISH_LPL[$WISH_RPLINE]} - ${WISH_RPL[$WISH_RPLINE]} ))"
 | 
			
		||||
	fi
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function wish_main() {
 | 
			
		||||
	local prev=$?
 | 
			
		||||
	# Set local IFS to avoid being affected by shell's IFS
 | 
			
		||||
	local IFS=$' \n'
 | 
			
		||||
	PS1=""
 | 
			
		||||
	WISH_LEFT_PS1=""
 | 
			
		||||
	WISH_RIGHT_PS1=("")
 | 
			
		||||
	WISH_LPL=(0)
 | 
			
		||||
	WISH_RPL=(0)
 | 
			
		||||
	WISH_RPLINE=0
 | 
			
		||||
	WISH_LPLINE=0
 | 
			
		||||
	local i
 | 
			
		||||
	if [[ $WISH_AUTONEWLINE != 0 ]]; then
 | 
			
		||||
		echo -ne "\033[6n" ; read -s -d ';'; read -s -d R WISH_CURSOR_POSITION
 | 
			
		||||
	# Set newline
 | 
			
		||||
	if [[ $WISH_AUTO_NEWLINE != 0 ]]; then
 | 
			
		||||
		echo -ne "\033[6n"
 | 
			
		||||
		read -rs -d ';'
 | 
			
		||||
		# shellcheck disable=SC2034
 | 
			
		||||
		read -rs -d R WISH_CURSOR_POSITION
 | 
			
		||||
		if [[ $WISH_CURSOR_POSITION != "1" ]]; then
 | 
			
		||||
			PS1="\n"
 | 
			
		||||
		fi
 | 
			
		||||
	fi
 | 
			
		||||
	# Generate left prompt.
 | 
			
		||||
	WISH_STATE=0  # 0 = left prompt, 1 = right prompt
 | 
			
		||||
	for i in $(seq 0 $((${#WISH_PLUGINS[@]} - 1))); do
 | 
			
		||||
		wish_${WISH_PLUGINS[i]}_main $prev
 | 
			
		||||
		"wish_${WISH_PLUGINS[i]}_main" "$prev"
 | 
			
		||||
		if [[ -v WISH_POWERLINE ]] && [[ $WISH_POWERLINE != 0 ]]; then
 | 
			
		||||
			if wish_${WISH_PLUGINS[$i]}_end $prev; then
 | 
			
		||||
			if "wish_${WISH_PLUGINS[$i]}_end" $prev; then
 | 
			
		||||
				if [[ $i -lt $((${#WISH_PLUGINS[@]} - 1)) ]]; then
 | 
			
		||||
					if wish_${WISH_PLUGINS[$(($i + 1))]}_start $prev; then
 | 
			
		||||
					if "wish_${WISH_PLUGINS[$((i + 1))]}_start" "$prev"; then
 | 
			
		||||
						local plugin=${WISH_PLUGINS[$i]}
 | 
			
		||||
						local next_plugin=${WISH_PLUGINS[$(($i+1))]}
 | 
			
		||||
						local fg=$(eval echo \$WISH_$(echo $plugin |
 | 
			
		||||
							tr '[:lower:]' '[:upper:]')_BG)
 | 
			
		||||
						local bg=$(eval echo \$WISH_$(echo $next_plugin |
 | 
			
		||||
							tr '[:lower:]' '[:upper:]')_BG)
 | 
			
		||||
						wish_append $bg $fg 
 | 
			
		||||
						local next_plugin=${WISH_PLUGINS[$((i + 1))]}
 | 
			
		||||
						local fg_name="WISH_${plugin^^}_BG"
 | 
			
		||||
						local bg_name="WISH_${next_plugin^^}_BG"
 | 
			
		||||
						wish_append "${!bg_name}" "${!fg_name}" "${WISH_POWERLINE_LEFT}"
 | 
			
		||||
					fi
 | 
			
		||||
				else
 | 
			
		||||
					local plugin=${WISH_PLUGINS[$i]}
 | 
			
		||||
					local fg=$(eval echo \$WISH_$(echo $plugin |
 | 
			
		||||
						tr '[:lower:]' '[:upper:]')_BG)
 | 
			
		||||
					wish_append -1 $fg 
 | 
			
		||||
					local fg_name="WISH_${plugin^^}_BG"
 | 
			
		||||
					wish_append -1 "${!fg_name}" "${WISH_POWERLINE_LEFT}"
 | 
			
		||||
				fi
 | 
			
		||||
			fi
 | 
			
		||||
		fi
 | 
			
		||||
 | 
			
		||||
		if [[ $i -eq $((${#WISH_PLUGINS[@]} - 1)) ]]; then
 | 
			
		||||
			PS1="$PS1\[\033[0;5;0m\]"
 | 
			
		||||
		fi
 | 
			
		||||
	done
 | 
			
		||||
	# Generate Right prompt.
 | 
			
		||||
	WISH_STATE=1
 | 
			
		||||
	for i in $(seq 0 $((${#WISH_RIGHT_PLUGINS[@]} - 1))); do
 | 
			
		||||
		if [[ -v WISH_POWERLINE ]] && [[ $WISH_POWERLINE != 0 ]]; then
 | 
			
		||||
			if "wish_${WISH_RIGHT_PLUGINS[$i]}_end" "$prev"; then
 | 
			
		||||
				if [[ $i == 0 ]]; then
 | 
			
		||||
					local plugin=${WISH_RIGHT_PLUGINS[$i]}
 | 
			
		||||
					local fg_name="WISH_${plugin^^}_BG"
 | 
			
		||||
					wish_append -1 "${!fg_name}" "${WISH_POWERLINE_RIGHT}"
 | 
			
		||||
				elif "wish_${WISH_RIGHT_PLUGINS[$((i - 1))]}_start" $prev; then
 | 
			
		||||
					local plugin=${WISH_RIGHT_PLUGINS[$i]}
 | 
			
		||||
					local prev_plugin=${WISH_RIGHT_PLUGINS[$((i - 1))]}
 | 
			
		||||
					local fg_name="WISH_${plugin^^}_BG"
 | 
			
		||||
					local bg_name="WISH_${prev_plugin^^}_BG"
 | 
			
		||||
					wish_append "${!bg_name}" "${!fg_name}" "${WISH_POWERLINE_RIGHT}"
 | 
			
		||||
				fi
 | 
			
		||||
			fi
 | 
			
		||||
		fi
 | 
			
		||||
		"wish_${WISH_RIGHT_PLUGINS[$i]}_main" "$prev"
 | 
			
		||||
	done
 | 
			
		||||
	# Save cursor position, print right prompt, restore cursor position,
 | 
			
		||||
	# print left prompt, reset terminal
 | 
			
		||||
	# shellcheck disable=SC2025
 | 
			
		||||
	PS1=$PS1"\[\e7"
 | 
			
		||||
	PS1="$PS1$(wish_print_right_prompt)"
 | 
			
		||||
	# shellcheck disable=SC2025
 | 
			
		||||
	PS1="$PS1\e8\]$WISH_LEFT_PS1\[\033[0;5;0m\]"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
wish_init
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user