mirror of
				https://gitlab.com/ceda_ei/wish
				synced 2025-10-27 21:50:04 +01:00 
			
		
		
		
	Compare commits
	
		
			23 Commits
		
	
	
		
			079533b686
			...
			config-fil
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 9e55279faf | |||
| afd6dc6668 | |||
| e01b29d4a0 | |||
| 186675ae4e | |||
| 9a2d831432 | |||
| aabc6ebfd6 | |||
| 76b9bd3ad1 | |||
| 20fb08f202 | |||
| 110217642e | |||
| 364463658a | |||
| 343e394d40 | |||
| b1fe80cef3 | |||
| fe18fd52db | |||
| 30ebb302b8 | |||
| 919b102a43 | |||
| 136567e08e | |||
| 97fe2dbcc6 | |||
| 3f156fdd35 | |||
| 5828900a92 | |||
| f8254ba89a | |||
| b389774a50 | |||
| eb7f3a6aa3 | |||
| c3fbe4f699 | 
							
								
								
									
										3
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,3 @@ | ||||
| __pycache__/ | ||||
| *.pyc | ||||
| config.gie | ||||
							
								
								
									
										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 | ||||
|   | ||||
| @@ -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" | ||||
| } | ||||
|   | ||||
| @@ -10,10 +10,45 @@ 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 | ||||
| 	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 " | ||||
|   | ||||
| @@ -5,7 +5,19 @@ 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 | ||||
| 	[[ $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++)) | ||||
|   | ||||
| @@ -5,7 +5,19 @@ 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 | ||||
| 	[[ $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++)) | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| WISH_DEFAULT_BG=-1 | ||||
| WISH_DEFAULT_FG=-1 | ||||
| WISH_POWERLINE=0 | ||||
| for i in ${WISH_PLUGINS[@]}; do | ||||
| for i in ${WISH_PLUGINS[@]} ${WISH_RIGHT_PLUGINS[@]}; do | ||||
| 	eval WISH_${i^^}_BG=-1 | ||||
| 	eval WISH_${i^^}_FG=-1 | ||||
| done | ||||
|   | ||||
| @@ -5,7 +5,19 @@ 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 | ||||
| 	[[ $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++)) | ||||
|   | ||||
							
								
								
									
										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() | ||||
							
								
								
									
										140
									
								
								wish.sh
									
									
									
									
									
								
							
							
						
						
									
										140
									
								
								wish.sh
									
									
									
									
									
								
							| @@ -1,14 +1,44 @@ | ||||
| #!/usr/bin/env bash | ||||
|  | ||||
| # 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() { | ||||
| 	# 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 | ||||
| 	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 | ||||
| 	# 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[@]}; do | ||||
| 	for plugin in ${WISH_PLUGINS_SOURCE[@]}; do | ||||
| 		for path in "$XDG_CONFIG_HOME" "/usr/share" "$HOME/.config"; do | ||||
| 			source "$path/wish/plugins/$plugin.sh" &> /dev/null && break | ||||
| 		done | ||||
| 		[[ $? -ne 0 ]] && echo "Plugin $i not found." >&2 | ||||
| 		[[ $? -ne 0 ]] && echo "Plugin $plugin not found." >&2 | ||||
| 	done | ||||
|  | ||||
| 	# Source theme | ||||
| @@ -30,7 +60,7 @@ function wish_init() { | ||||
| 	done | ||||
|  | ||||
| 	# Call plugins to set colors | ||||
| 	for plugin in ${WISH_PLUGINS[@]}; do | ||||
| 	for plugin in ${WISH_PLUGINS[@]} ${WISH_RIGHT_PLUGINS[@]}; do | ||||
| 		eval wish_$(echo $plugin)_set_colors $prev | ||||
| 	done | ||||
| } | ||||
| @@ -59,7 +89,41 @@ function color_to_escape_code() { | ||||
| 		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: | ||||
| @@ -76,23 +140,60 @@ function wish_append() { | ||||
| 	local 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 | ||||
| 	# Set newline | ||||
| 	if [[ $WISH_AUTONEWLINE != 0 ]]; then | ||||
| 		echo -ne "\033[6n" ; read -s -d ';'; read -s -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 | ||||
| 		if [[ -v WISH_POWERLINE ]] && [[ $WISH_POWERLINE != 0 ]]; then | ||||
| @@ -112,11 +213,32 @@ function wish_main() { | ||||
| 				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}  | ||||
| 				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}  | ||||
| 				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 | ||||
| 	PS1=$PS1"\[\e7" | ||||
| 	PS1="$PS1$(wish_print_right_prompt)" | ||||
| 	PS1="$PS1\e8\]$WISH_LEFT_PS1\[\033[0;5;0m\]" | ||||
| } | ||||
|  | ||||
| wish_init | ||||
|   | ||||
		Reference in New Issue
	
	Block a user