aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitmodules3
-rw-r--r--.travis.yml27
-rw-r--r--CHANGELOG.md29
-rw-r--r--README.md20
-rw-r--r--TESTS.md14
-rw-r--r--functions/icons.zsh4
-rw-r--r--functions/utilities.zsh60
-rw-r--r--functions/vcs.zsh31
-rwxr-xr-xpowerlevel9k.zsh-theme190
m---------shunit20
-rwxr-xr-xtest/functions/colors.spec42
-rwxr-xr-xtest/functions/utilities.spec109
-rwxr-xr-xtest/powerlevel9k.spec95
-rwxr-xr-xtest/segments/dir.spec118
-rwxr-xr-xtest/segments/go_version.spec40
-rwxr-xr-xtest/segments/rust_version.spec40
16 files changed, 719 insertions, 103 deletions
diff --git a/.gitmodules b/.gitmodules
new file mode 100644
index 00000000..743b8e91
--- /dev/null
+++ b/.gitmodules
@@ -0,0 +1,3 @@
+[submodule "shunit2"]
+ path = shunit2
+ url = https://github.com/kward/shunit2.git
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 00000000..71aff690
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,27 @@
+sudo: true
+dist: trusty
+language: sh
+addons:
+ apt:
+ packages:
+ - build-essential
+
+before_script:
+ # Show the git version being used to test.
+ - "git --version"
+ # Show the zsh version being used to test.
+ - "zsh --version"
+
+install:
+ - "sudo apt-get update -qq"
+ - "sudo apt-get install zsh"
+ - "sudo chsh -s $(which zsh)"
+
+script:
+ - test/powerlevel9k.spec
+ - test/functions/utilities.spec
+ - test/functions/colors.spec
+ - test/segments/dir.spec
+ - test/segments/rust_version.spec
+ - test/segments/go_version.spec
+
diff --git a/CHANGELOG.md b/CHANGELOG.md
index ce0fe494..728f3578 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,9 +1,34 @@
-## v0.4.0
+## v0.4.0 (next)
-### New segment `aws_eb_env` added
+### `aws_eb_env` added
This segment displays the current Elastic Beanstalk environment.
+### `ram` changes
+
+The `ram` segment was split up into `ram` and `swap`. The `POWERLEVEL9K_RAM_ELEMENTS`
+variable is void.
+
+## v0.3.2
+
+### `vcs` changes
+
+A new state `UNTRACKED` was added to the `vcs` segment. So we now
+have 3 states for repositories: `UNTRACKED`, `MODIFIED`, and the
+default state. The `UNTRACKED` state is active when there are files
+in the repository directory which have not been added to the repo
+(the same as when the `+` icon appears). The default color for the
+`UNTRACKED` state is now yellow, and the default color for the
+`MODIFIED` state is now read, but those colors can be changed by
+setting these variables, for example:
+
+```zsh
+POWERLEVEL9K_VCS_MODIFIED_FOREGROUND='black'
+POWERLEVEL9K_VCS_MODIFIED_BACKGROUND='white'
+POWERLEVEL9K_VCS_UNTRACKED_FOREGROUND='green'
+POWERLEVEL9K_VCS_UNTRACKED_BACKGROUND='blue'
+```
+
## v0.3.1
### `dir` changes
diff --git a/README.md b/README.md
index acce6ced..f9e48b05 100644
--- a/README.md
+++ b/README.md
@@ -1,5 +1,6 @@
## powerlevel9k Theme for ZSH
+[![Build Status](https://travis-ci.org/bhilburn/powerlevel9k.svg?branch=next)](https://travis-ci.org/bhilburn/powerlevel9k)
[![Join the chat at https://gitter.im/bhilburn/powerlevel9k](https://badges.gitter.im/bhilburn/powerlevel9k.svg)](https://gitter.im/bhilburn/powerlevel9k?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
Powerlevel9k is a theme for ZSH which uses [Powerline
@@ -98,12 +99,13 @@ The segments that are currently available are:
* **nvm** - Show the version of Node that is currently active, if it differs from the version used by NVM
* **os_icon** - Display a nice little icon, depending on your operating system.
* **php_version** - Show the current PHP version.
-* [ram](#ram) - Show free RAM and used Swap.
+* **ram** - Show free RAM
* [rbenv](#rbenv) - Ruby environment information (if one is active).
* **root_indicator** - An indicator if the user is root.
* [rspec_stats](#rspec_stats) - Show a ratio of test classes vs code classes for RSpec.
* **rust_version** - Display the current rust version.
* [status](#status) - The return code of the previous command.
+* **swap** - Prints the current swap size.
* [symphony2_tests](#symphony2_tests) - Show a ratio of test classes vs code classes for Symfony2.
* **symphony2_version** - Show the current Symfony2 version, if you are in a Symfony2-Project dir.
* [time](#time) - System time.
@@ -245,6 +247,15 @@ specify the correct network interface by setting:
|----------|---------------|-------------|
|`POWERLEVEL9K_IP_INTERFACE`|None|The NIC for which you wish to display the IP address. Example: `eth0`.|
+##### rbenv
+
+This segment shows the version of Ruby being used when using `rbenv` to change your current Ruby stack.
+
+It figures out the version being used by taking the output of the `rbenv version-name` command.
+
+* If `rbenv` is not in $PATH, nothing will be shown.
+* If the current Ruby version is the same as the global Ruby version, nothing will be shown.
+
##### rspec_stats
See [Unit Test Ratios](#unit-test-ratios), below.
@@ -257,12 +268,6 @@ This segment shows the return code of the last command.
|----------|---------------|-------------|
|`POWERLEVEL9K_STATUS_VERBOSE`|`true`|Set to false if you wish to hide this segment when the last command completed successfully.|
-##### ram
-
-| Variable | Default Value | Description |
-|----------|---------------|-------------|
-|`POWERLEVEL9K_RAM_ELEMENTS`|Both|Specify `ram_free` or `swap_used` to only show one or the other rather than both.|
-
##### symphony2_tests
See [Unit Test Ratios](#unit-test-ratios), below.
@@ -294,6 +299,7 @@ customization is provided via:
|`POWERLEVEL9K_HIDE_BRANCH_ICON`|`false`|Set to `true` to hide the branch icon from the segment.|
|`POWERLEVEL9K_SHOW_CHANGESET`|`false`|Set to `true` to display the hash / changeset in the segment.|
|`POWERLEVEL9K_CHANGESET_HASH_LENGTH`|`12`|How many characters of the hash / changeset to display in the segment.|
+|`POWERLEVEL9K_VCS_SHOW_SUBMODULE_DIRTY`|`true`|Set to `false` to not reflect submodule status in the top-level repository prompt.|
**vcs Symbols**
diff --git a/TESTS.md b/TESTS.md
new file mode 100644
index 00000000..d4e663dc
--- /dev/null
+++ b/TESTS.md
@@ -0,0 +1,14 @@
+# Structure
+
+The Unit-Tests do not follow exactly the file structure of Powerlevel9k itself.
+
+## Basic Tests
+
+Basic Tests belong in `test/powerlevel9k.spec` if they test basic functionality of
+Powerlevel9k itself. Basic functions from the `functions` directory have their
+Tests in separate files under `test/functions`.
+
+## Segment Tests
+
+These Tests tend to be more complex in setup than the basic tests. To avoid ending
+up in a huge single file, there is one file per segment in `test/segments`.
diff --git a/functions/icons.zsh b/functions/icons.zsh
index 1eaef3d6..e7dc3bfa 100644
--- a/functions/icons.zsh
+++ b/functions/icons.zsh
@@ -49,7 +49,7 @@ case $POWERLEVEL9K_MODE in
FOLDER_ICON $'\UE818' # 
NETWORK_ICON $'\UE1AD' # 
LOAD_ICON $'\UE190 ' # 
- #RAM_ICON $'\UE87D' # 
+ SWAP_ICON $'\UE87D' # 
RAM_ICON $'\UE1E2 ' # 
VCS_UNTRACKED_ICON $'\UE16C' # 
VCS_UNSTAGED_ICON $'\UE17C' # 
@@ -103,6 +103,7 @@ case $POWERLEVEL9K_MODE in
FOLDER_ICON $'\UF115' # 
NETWORK_ICON $'\UF09E' # 
LOAD_ICON $'\UF080 ' # 
+ SWAP_ICON $'\UF0E4' # 
RAM_ICON $'\UF0E4' # 
VCS_UNTRACKED_ICON $'\UF059' # 
VCS_UNSTAGED_ICON $'\UF06A' # 
@@ -152,6 +153,7 @@ case $POWERLEVEL9K_MODE in
FOLDER_ICON ''
NETWORK_ICON 'IP'
LOAD_ICON 'L'
+ SWAP_ICON 'SWP'
RAM_ICON 'RAM'
VCS_UNTRACKED_ICON '?'
VCS_UNSTAGED_ICON $'\u25CF' # ●
diff --git a/functions/utilities.zsh b/functions/utilities.zsh
index f855caf5..5ca5b431 100644
--- a/functions/utilities.zsh
+++ b/functions/utilities.zsh
@@ -27,6 +27,9 @@ function set_default() {
}
# Converts large memory values into a human-readable unit (e.g., bytes --> GB)
+# Takes two arguments:
+# * $size - The number which should be prettified
+# * $base - The base of the number (default Bytes)
printSizeHumanReadable() {
typeset -F 2 size
size="$1"+0.00001
@@ -60,10 +63,10 @@ printSizeHumanReadable() {
# worthy. The callback function has access to
# the inner variable $item.
function getRelevantItem() {
- setopt shwordsplit # We need to split the words in $interfaces
-
- local list callback
- list=$1
+ local -a list
+ local callback
+ # Explicitly split the elements by whitespace.
+ list=(${=1})
callback=$2
for item in $list; do
@@ -134,3 +137,52 @@ print_deprecation_warning() {
fi
done
}
+
+# A helper function to determine if a segment should be
+# joined or promoted to a full one.
+# Takes three arguments:
+# * $1: The array index of the current segment
+# * $2: The array index of the last printed segment
+# * $3: The array of segments of the left or right prompt
+function segmentShouldBeJoined() {
+ local current_index=$1
+ local last_segment_index=$2
+ # Explicitly split the elements by whitespace.
+ local -a elements
+ elements=(${=3})
+
+ local current_segment=${elements[$current_index]}
+ local joined=false
+ if [[ ${current_segment[-7,-1]} == '_joined' ]]; then
+ joined=true
+ # promote segment to a full one, if the predecessing full segment
+ # was conditional. So this can only be the case for segments that
+ # are not our direct predecessor.
+ if (( $(($current_index - $last_segment_index)) > 1)); then
+ # Now we have to examine every previous segment, until we reach
+ # the last printed one (found by its index). This is relevant if
+ # all previous segments are joined. Then we want to join our
+ # segment as well.
+ local examined_index=$((current_index - 1))
+ while (( $examined_index > $last_segment_index )); do
+ local previous_segment=${elements[$examined_index]}
+ # If one of the examined segments is not joined, then we know
+ # that the current segment should not be joined, as the target
+ # segment is the wrong one.
+ if [[ ${previous_segment[-7,-1]} != '_joined' ]]; then
+ joined=false
+ break
+ fi
+ examined_index=$((examined_index - 1))
+ done
+ fi
+ fi
+
+ # Return 1 means error; return 0 means no error. So we have
+ # to invert $joined
+ if [[ "$joined" == "true" ]]; then
+ return 0
+ else
+ return 1
+ fi
+}
diff --git a/functions/vcs.zsh b/functions/vcs.zsh
index 4a0a7ead..9baccd24 100644
--- a/functions/vcs.zsh
+++ b/functions/vcs.zsh
@@ -6,10 +6,22 @@
# https://github.com/bhilburn/powerlevel9k
################################################################
+set_default POWERLEVEL9K_VCS_SHOW_SUBMODULE_DIRTY true
function +vi-git-untracked() {
+ # TODO: check git >= 1.7.2 - see function git_compare_version()
+ local FLAGS
+ FLAGS=('--porcelain')
+
+ if [[ "$POWERLEVEL9K_VCS_SHOW_SUBMODULE_DIRTY" == "false" ]]; then
+ FLAGS+='--ignore-submodules=dirty'
+ fi
+
if [[ $(git rev-parse --is-inside-work-tree 2> /dev/null) == 'true' && \
- -n $(git ls-files --others --exclude-standard | sed q) ]]; then
- hook_com[unstaged]+=" %F{$POWERLEVEL9K_VCS_FOREGROUND}$(print_icon 'VCS_UNTRACKED_ICON')%f"
+ -n $(git status ${FLAGS} | grep -E '^??' 2> /dev/null | tail -n1) ]]; then
+ hook_com[unstaged]+=" $(print_icon 'VCS_UNTRACKED_ICON')"
+ VCS_WORKDIR_HALF_DIRTY=true
+ else
+ VCS_WORKDIR_HALF_DIRTY=false
fi
}
@@ -22,12 +34,12 @@ function +vi-git-aheadbehind() {
# for git prior to 1.7
# ahead=$(git rev-list origin/${branch_name}..HEAD | wc -l)
ahead=$(git rev-list "${branch_name}"@{upstream}..HEAD 2>/dev/null | wc -l)
- (( ahead )) && gitstatus+=( " %F{$POWERLEVEL9K_VCS_FOREGROUND}$(print_icon 'VCS_OUTGOING_CHANGES_ICON')${ahead// /}%f" )
+ (( ahead )) && gitstatus+=( " $(print_icon 'VCS_OUTGOING_CHANGES_ICON')${ahead// /}" )
# for git prior to 1.7
# behind=$(git rev-list HEAD..origin/${branch_name} | wc -l)
behind=$(git rev-list HEAD.."${branch_name}"@{upstream} 2>/dev/null | wc -l)
- (( behind )) && gitstatus+=( " %F{$POWERLEVEL9K_VCS_FOREGROUND}$(print_icon 'VCS_INCOMING_CHANGES_ICON')${behind// /}%f" )
+ (( behind )) && gitstatus+=( " $(print_icon 'VCS_INCOMING_CHANGES_ICON')${behind// /}" )
hook_com[misc]+=${(j::)gitstatus}
}
@@ -39,12 +51,12 @@ function +vi-git-remotebranch() {
remote=${$(git rev-parse --verify HEAD@{upstream} --symbolic-full-name 2>/dev/null)/refs\/(remotes|heads)\/}
branch_name=$(git symbolic-ref --short HEAD 2>/dev/null)
- hook_com[branch]="%F{$POWERLEVEL9K_VCS_FOREGROUND}$(print_icon 'VCS_BRANCH_ICON')${hook_com[branch]}%f"
+ hook_com[branch]="$(print_icon 'VCS_BRANCH_ICON')${hook_com[branch]}"
# Always show the remote
#if [[ -n ${remote} ]] ; then
# Only show the remote if it differs from the local
if [[ -n ${remote} ]] && [[ "${remote#*/}" != "${branch_name}" ]] ; then
- hook_com[branch]+="%F{$POWERLEVEL9K_VCS_FOREGROUND}$(print_icon 'VCS_REMOTE_BRANCH_ICON')%f%F{$POWERLEVEL9K_VCS_FOREGROUND}${remote// /}%f"
+ hook_com[branch]+="$(print_icon 'VCS_REMOTE_BRANCH_ICON')${remote// /}"
fi
}
@@ -52,7 +64,7 @@ function +vi-git-tagname() {
local tag
tag=$(git describe --tags --exact-match HEAD 2>/dev/null)
- [[ -n "${tag}" ]] && hook_com[branch]="%F{$POWERLEVEL9K_VCS_FOREGROUND}$(print_icon 'VCS_TAG_ICON')${tag}%f"
+ [[ -n "${tag}" ]] && hook_com[branch]="$(print_icon 'VCS_TAG_ICON')${tag}"
}
# Show count of stashed changes
@@ -62,13 +74,13 @@ function +vi-git-stash() {
if [[ -s $(git rev-parse --git-dir)/refs/stash ]] ; then
stashes=$(git stash list 2>/dev/null | wc -l)
- hook_com[misc]+=" %F{$POWERLEVEL9K_VCS_FOREGROUND}$(print_icon 'VCS_STASH_ICON')${stashes// /}%f"
+ hook_com[misc]+=" $(print_icon 'VCS_STASH_ICON')${stashes// /}"
fi
}
function +vi-hg-bookmarks() {
if [[ -n "${hgbmarks[@]}" ]]; then
- hook_com[hg-bookmark-string]=" %F{$POWERLEVEL9K_VCS_FOREGROUND}$(print_icon 'VCS_BOOKMARK_ICON')${hgbmarks[@]}%f"
+ hook_com[hg-bookmark-string]=" $(print_icon 'VCS_BOOKMARK_ICON')${hgbmarks[@]}"
# To signal that we want to use the sting we just generated, set the special
# variable `ret' to something other than the default zero:
@@ -90,4 +102,3 @@ function +vi-vcs-detect-changes() {
VCS_WORKDIR_DIRTY=false
fi
}
-
diff --git a/powerlevel9k.zsh-theme b/powerlevel9k.zsh-theme
index 4ac6f3b0..38651fe9 100755
--- a/powerlevel9k.zsh-theme
+++ b/powerlevel9k.zsh-theme
@@ -92,16 +92,11 @@ source $script_location/functions/vcs.zsh
if [[ "$POWERLEVEL9K_COLOR_SCHEME" == "light" ]]; then
DEFAULT_COLOR=white
DEFAULT_COLOR_INVERTED=black
- DEFAULT_COLOR_DARK="252"
else
DEFAULT_COLOR=black
DEFAULT_COLOR_INVERTED=white
- DEFAULT_COLOR_DARK="236"
fi
-set_default POWERLEVEL9K_VCS_FOREGROUND "$DEFAULT_COLOR"
-set_default POWERLEVEL9K_VCS_DARK_FOREGROUND "$DEFAULT_COLOR_DARK"
-
################################################################
# Prompt Segment Constructors
#
@@ -123,14 +118,20 @@ CURRENT_BG='NONE'
# Takes four arguments:
# * $1: Name of the function that was orginally invoked (mandatory).
# Necessary, to make the dynamic color-overwrite mechanism work.
-# * $2: A flag if the segment should be joined with the previous one.
+# * $2: The array index of the current segment
# * $3: Background color
# * $4: Foreground color
# * $5: The segment content
# * $6: An identifying icon (must be a key of the icons array)
# The latter three can be omitted,
+set_default last_left_element_index 1
set_default POWERLEVEL9K_WHITESPACE_BETWEEN_LEFT_SEGMENTS " "
left_prompt_segment() {
+ local current_index=$2
+ # Check if the segment should be joined with the previous one
+ local joined
+ segmentShouldBeJoined $current_index $last_left_element_index "$POWERLEVEL9K_LEFT_PROMPT_ELEMENTS" && joined=true || joined=false
+
# Overwrite given background-color by user defined variable for this segment.
local BACKGROUND_USER_VARIABLE=POWERLEVEL9K_${(U)1#prompt_}_BACKGROUND
local BG_COLOR_MODIFIER=${(P)BACKGROUND_USER_VARIABLE}
@@ -145,7 +146,6 @@ left_prompt_segment() {
[[ -n "$3" ]] && bg="%K{$3}" || bg="%k"
[[ -n "$4" ]] && fg="%F{$4}" || fg="%f"
- local joined=$2
if [[ $CURRENT_BG != 'NONE' ]] && ! isSameColor "$3" "$CURRENT_BG"; then
echo -n "$bg%F{$CURRENT_BG}"
if [[ $joined == false ]]; then
@@ -188,6 +188,7 @@ left_prompt_segment() {
echo -n "${POWERLEVEL9K_WHITESPACE_BETWEEN_LEFT_SEGMENTS}"
CURRENT_BG=$3
+ last_left_element_index=$current_index
}
# End the left prompt, closes the final segment.
@@ -207,14 +208,21 @@ CURRENT_RIGHT_BG='NONE'
# Takes four arguments:
# * $1: Name of the function that was orginally invoked (mandatory).
# Necessary, to make the dynamic color-overwrite mechanism work.
-# * $2: A flag if the segment should be joined with the previous one.
+# * $2: The array index of the current segment
# * $3: Background color
# * $4: Foreground color
# * $5: The segment content
# * $6: An identifying icon (must be a key of the icons array)
# No ending for the right prompt segment is needed (unlike the left prompt, above).
+set_default last_right_element_index 1
set_default POWERLEVEL9K_WHITESPACE_BETWEEN_RIGHT_SEGMENTS " "
right_prompt_segment() {
+ local current_index=$2
+
+ # Check if the segment should be joined with the previous one
+ local joined
+ segmentShouldBeJoined $current_index $last_right_element_index "$POWERLEVEL9K_RIGHT_PROMPT_ELEMENTS" && joined=true || joined=false
+
# Overwrite given background-color by user defined variable for this segment.
local BACKGROUND_USER_VARIABLE=POWERLEVEL9K_${(U)1#prompt_}_BACKGROUND
local BG_COLOR_MODIFIER=${(P)BACKGROUND_USER_VARIABLE}
@@ -229,7 +237,6 @@ right_prompt_segment() {
[[ -n "$3" ]] && bg="%K{$3}" || bg="%k"
[[ -n "$4" ]] && fg="%F{$4}" || fg="%f"
- local joined=$2
# If CURRENT_RIGHT_BG is "NONE", we are the first right segment.
if [[ $joined == false ]] || [[ "$CURRENT_RIGHT_BG" == "NONE" ]]; then
if isSameColor "$CURRENT_RIGHT_BG" "$3"; then
@@ -269,6 +276,7 @@ right_prompt_segment() {
echo -n "${visual_identifier}${POWERLEVEL9K_WHITESPACE_BETWEEN_RIGHT_SEGMENTS}%f"
CURRENT_RIGHT_BG=$3
+ last_right_element_index=$current_index
}
################################################################
@@ -283,8 +291,8 @@ CURRENT_BG='NONE'
# AWS Profile
prompt_aws() {
local aws_profile="$AWS_DEFAULT_PROFILE"
- if [[ -n "$aws_profile" ]];
- then
+
+ if [[ -n "$aws_profile" ]]; then
"$1_prompt_segment" "$0" "$2" red white "$aws_profile" 'AWS_ICON'
fi
}
@@ -398,7 +406,9 @@ prompt_battery() {
fi
# Draw the prompt_segment
- [[ -n $bat_percent ]] && "$1_prompt_segment" "${0}_${current_state}" "$2" "$DEFAULT_COLOR" "${battery_states[$current_state]}" "$message" 'BATTERY_ICON'
+ if [[ -n $bat_percent ]]; then
+ "$1_prompt_segment" "${0}_${current_state}" "$2" "$DEFAULT_COLOR" "${battery_states[$current_state]}" "$message" 'BATTERY_ICON'
+ fi
}
# Context: user@hostname (who am I and where am I)
@@ -427,7 +437,7 @@ prompt_dir() {
local current_path='%~'
if [[ -n "$POWERLEVEL9K_SHORTEN_DIR_LENGTH" ]]; then
- set_default POWERLEVEL9K_SHORTEN_DELIMITER ".."
+ set_default POWERLEVEL9K_SHORTEN_DELIMITER $'\U2026'
case "$POWERLEVEL9K_SHORTEN_STRATEGY" in
truncate_middle)
@@ -456,7 +466,7 @@ prompt_dir() {
# GO prompt
prompt_go_version() {
local go_version
- go_version=$(go version 2>&1 | sed -E "s/.*(go[0-9.]*).*/\1/")
+ go_version=$(go version 2>/dev/null | sed -E "s/.*(go[0-9.]*).*/\1/")
if [[ -n "$go_version" ]]; then
"$1_prompt_segment" "$0" "$2" "green" "255" "$go_version"
@@ -583,52 +593,32 @@ prompt_php_version() {
# Show free RAM and used Swap
prompt_ram() {
- defined POWERLEVEL9K_RAM_ELEMENTS || POWERLEVEL9K_RAM_ELEMENTS=(ram_free swap_used)
-
- local rendition base
- for element in "${POWERLEVEL9K_RAM_ELEMENTS[@]}"; do
- case $element in
- ram_free)
- if [[ "$OS" == "OSX" ]]; then
- ramfree=$(vm_stat | grep "Pages free" | grep -o -E '[0-9]+')
- # Convert pages into Bytes
- ramfree=$(( ramfree * 4096 ))
- base=''
- else
- ramfree=$(grep -o -E "MemFree:\s+[0-9]+" /proc/meminfo | grep -o "[0-9]*")
- base=K
- fi
-
- rendition+="$(printSizeHumanReadable "$ramfree" $base) "
- ;;
- swap_used)
- if [[ "$OS" == "OSX" ]]; then
- raw_swap_used=$(sysctl vm.swapusage | grep -o "used\s*=\s*[0-9,.A-Z]*" | grep -o "[0-9,.A-Z]*$")
- typeset -F 2 swap_used
- swap_used=${$(echo $raw_swap_used | grep -o "[0-9,.]*")//,/.}
- # Replace comma
- swap_used=${swap_used//,/.}
-
- base=$(echo "$raw_swap_used" | grep -o "[A-Z]*$")
- else
- swap_total=$(grep -o -E "SwapTotal:\s+[0-9]+" /proc/meminfo | grep -o "[0-9]*")
- swap_free=$(grep -o -E "SwapFree:\s+[0-9]+" /proc/meminfo | grep -o "[0-9]*")
- swap_used=$(( swap_total - swap_free ))
- base=K
- fi
-
- rendition+="$(printSizeHumanReadable "$swap_used" $base) "
- ;;
- esac
- done
+ local base=''
+ local ramfree=0
+ if [[ "$OS" == "OSX" ]]; then
+ ramfree=$(vm_stat | grep "Pages free" | grep -o -E '[0-9]+')
+ # Convert pages into Bytes
+ ramfree=$(( ramfree * 4096 ))
+ else
+ ramfree=$(grep -o -E "MemFree:\s+[0-9]+" /proc/meminfo | grep -o "[0-9]*")
+ base='K'
+ fi
- "$1_prompt_segment" "$0" "$2" "yellow" "$DEFAULT_COLOR" "${rendition% }" 'RAM_ICON'
+ "$1_prompt_segment" "$0" "$2" "yellow" "$DEFAULT_COLOR" "$(printSizeHumanReadable "$ramfree" $base)" 'RAM_ICON'
}
# rbenv information
prompt_rbenv() {
- if [[ -n "$RBENV_VERSION" ]]; then
- "$1_prompt_segment" "$0" "$2" "red" "$DEFAULT_COLOR" "$RBENV_VERSION" 'RUBY_ICON'
+ if which rbenv 2>/dev/null >&2; then
+ local rbenv_version_name="$(rbenv version-name)"
+ local rbenv_global="$(rbenv global)"
+
+ # Don't show anything if the current Ruby is the same as the global Ruby.
+ if [[ $rbenv_version_name == $rbenv_global ]]; then
+ return
+ fi
+
+ "$1_prompt_segment" "$0" "$2" "red" "$DEFAULT_COLOR" "$rbenv_version_name" 'RUBY_ICON'
fi
}
@@ -687,6 +677,30 @@ prompt_status() {
fi
}
+prompt_swap() {
+ local swap_used=0
+ local base=''
+
+ if [[ "$OS" == "OSX" ]]; then
+ local raw_swap_used
+ raw_swap_used=$(sysctl vm.swapusage | grep -o "used\s*=\s*[0-9,.A-Z]*" | grep -o "[0-9,.A-Z]*$")
+
+ typeset -F 2 swap_used
+ swap_used=${$(echo $raw_swap_used | grep -o "[0-9,.]*")//,/.}
+ # Replace comma
+ swap_used=${swap_used//,/.}
+
+ base=$(echo "$raw_swap_used" | grep -o "[A-Z]*$")
+ else
+ swap_total=$(grep -o -E "SwapTotal:\s+[0-9]+" /proc/meminfo | grep -o "[0-9]*")
+ swap_free=$(grep -o -E "SwapFree:\s+[0-9]+" /proc/meminfo | grep -o "[0-9]*")
+ swap_used=$(( swap_total - swap_free ))
+ base='K'
+ fi
+
+ "$1_prompt_segment" "$0" "$2" "yellow" "$DEFAULT_COLOR" "$(printSizeHumanReadable "$swap_used" $base)" 'SWAP_ICON'
+}
+
# Symfony2-PHPUnit test ratio
prompt_symfony2_tests() {
if [[ (-d src && -d app && -f app/AppKernel.php) ]]; then
@@ -748,6 +762,17 @@ prompt_vcs() {
autoload -Uz vcs_info
VCS_WORKDIR_DIRTY=false
+ VCS_WORKDIR_HALF_DIRTY=false
+
+ # The vcs segment can have three different states - defaults to ''.
+ local current_state=""
+ typeset -AH vcs_states
+ vcs_states=(
+ '' 'green'
+ 'modified' 'red'
+ 'untracked' 'yellow'
+ )
+
VCS_CHANGESET_PREFIX=''
if [[ "$POWERLEVEL9K_SHOW_CHANGESET" == true ]]; then
# Default: Just display the first 12 characters of our changeset-ID.
@@ -756,22 +781,24 @@ prompt_vcs() {
VCS_CHANGESET_HASH_LENGTH="$POWERLEVEL9K_CHANGESET_HASH_LENGTH"
fi
- VCS_CHANGESET_PREFIX="%F{$POWERLEVEL9K_VCS_DARK_FOREGROUND}$(print_icon 'VCS_COMMIT_ICON')%0.$VCS_CHANGESET_HASH_LENGTH""i%f "
+ VCS_CHANGESET_PREFIX="$(print_icon 'VCS_COMMIT_ICON')%0.$VCS_CHANGESET_HASH_LENGTH""i "
fi
zstyle ':vcs_info:*' enable git hg
zstyle ':vcs_info:*' check-for-changes true
- VCS_DEFAULT_FORMAT="$VCS_CHANGESET_PREFIX%F{$POWERLEVEL9K_VCS_FOREGROUND}%b%c%u%m%f"
+ VCS_DEFAULT_FORMAT="$VCS_CHANGESET_PREFIX%b%c%u%m"
zstyle ':vcs_info:*' formats "$VCS_DEFAULT_FORMAT"
zstyle ':vcs_info:*' actionformats "%b %F{red}| %a%f"
- zstyle ':vcs_info:*' stagedstr " %F{$POWERLEVEL9K_VCS_FOREGROUND}$(print_icon 'VCS_STAGED_ICON')%f"
- zstyle ':vcs_info:*' unstagedstr " %F{$POWERLEVEL9K_VCS_FOREGROUND}$(print_icon 'VCS_UNSTAGED_ICON')%f"
+ zstyle ':vcs_info:*' stagedstr " $(print_icon 'VCS_STAGED_ICON')"
+ zstyle ':vcs_info:*' unstagedstr " $(print_icon 'VCS_UNSTAGED_ICON')"
- zstyle ':vcs_info:git*+set-message:*' hooks vcs-detect-changes git-untracked git-aheadbehind git-stash git-remotebranch git-tagname
- zstyle ':vcs_info:hg*+set-message:*' hooks vcs-detect-changes
+ defined POWERLEVEL9K_VCS_GIT_HOOKS || POWERLEVEL9K_VCS_GIT_HOOKS=(vcs-detect-changes git-untracked git-aheadbehind git-stash git-remotebranch git-tagname)
+ zstyle ':vcs_info:git*+set-message:*' hooks $POWERLEVEL9K_VCS_GIT_HOOKS
+ defined POWERLEVEL9K_VCS_HG_HOOKS || POWERLEVEL9K_VCS_HG_HOOKS=(vcs-detect-changes)
+ zstyle ':vcs_info:hg*+set-message:*' hooks $POWERLEVEL9K_VCS_HG_HOOKS
# For Hg, only show the branch name
zstyle ':vcs_info:hg*:*' branchformat "$(print_icon 'VCS_BRANCH_ICON')%b"
@@ -792,10 +819,15 @@ prompt_vcs() {
if [[ "$VCS_WORKDIR_DIRTY" == true ]]; then
# $vcs_visual_identifier gets set in +vi-vcs-detect-changes in functions/vcs.zsh,
# as we have there access to vcs_info internal hooks.
- "$1_prompt_segment" "$0_MODIFIED" "$2" "yellow" "$DEFAULT_COLOR" "$vcs_prompt" "$vcs_visual_identifier"
+ current_state='modified'
else
- "$1_prompt_segment" "$0" "$2" "green" "$DEFAULT_COLOR" "$vcs_prompt" "$vcs_visual_identifier"
+ if [[ "$VCS_WORKDIR_HALF_DIRTY" == true ]]; then
+ current_state='untracked'
+ else
+ current_state=''
+ fi
fi
+ "$1_prompt_segment" "${0}_${(U)current_state}" "$2" "${vcs_states[$current_state]}" "$DEFAULT_COLOR" "$vcs_prompt" "$vcs_visual_identifier"
fi
}
@@ -831,20 +863,20 @@ prompt_virtualenv() {
build_left_prompt() {
defined POWERLEVEL9K_LEFT_PROMPT_ELEMENTS || POWERLEVEL9K_LEFT_PROMPT_ELEMENTS=(context dir rbenv vcs)
+ local index=1
for element in "${POWERLEVEL9K_LEFT_PROMPT_ELEMENTS[@]}"; do
- # Check if the segment should be joined with the previous one
- local joined=false
- if [[ ${element[-7,-1]} == '_joined' ]]; then
- element="${element[0,-8]}"
- joined=true
- fi
+ # Remove joined information in direct calls
+ element=${element%_joined}
+
# Check if it is a custom command, otherwise interpet it as
# a prompt.
if [[ $element[0,7] =~ "custom_" ]]; then
- "prompt_custom" "left" "$joined" $element[8,-1]
+ "prompt_custom" "left" "$index" $element[8,-1]
else
- "prompt_$element" "left" "$joined"
+ "prompt_$element" "left" "$index"
fi
+
+ index=$((index + 1))
done
left_prompt_end
@@ -854,20 +886,20 @@ build_left_prompt() {
build_right_prompt() {
defined POWERLEVEL9K_RIGHT_PROMPT_ELEMENTS || POWERLEVEL9K_RIGHT_PROMPT_ELEMENTS=(status root_indicator background_jobs history time)
+ local index=1
for element in "${POWERLEVEL9K_RIGHT_PROMPT_ELEMENTS[@]}"; do
- # Check if the segment should be joined with the previous one
- local joined=false
- if [[ ${element[-7,-1]} == '_joined' ]]; then
- element="${element[0,-8]}"
- joined=true
- fi
+ # Remove joined information in direct calls
+ element=${element%_joined}
+
# Check if it is a custom command, otherwise interpet it as
# a prompt.
if [[ $element[0,7] =~ "custom_" ]]; then
- "prompt_custom" "right" "$joined" $element[8,-1]
+ "prompt_custom" "right" "$index" $element[8,-1]
else
- "prompt_$element" "right" "$joined"
+ "prompt_$element" "right" "$index"
fi
+
+ index=$((index + 1))
done
}
diff --git a/shunit2 b/shunit2
new file mode 160000
+Subproject 60dd60bcd1573befe38465010263ab242e55811
diff --git a/test/functions/colors.spec b/test/functions/colors.spec
new file mode 100755
index 00000000..61a40087
--- /dev/null
+++ b/test/functions/colors.spec
@@ -0,0 +1,42 @@
+#!/usr/bin/env zsh
+#vim:ft=zsh ts=2 sw=2 sts=2 et fenc=utf-8
+
+# Required for shunit2 to run correctly
+setopt shwordsplit
+SHUNIT_PARENT=$0
+
+function setUp() {
+ # Load Powerlevel9k
+ source functions/colors.zsh
+}
+
+function testGetColorCodeWithAnsiForegroundColor() {
+ assertEquals '002' "$(getColorCode 'green')"
+}
+
+function testGetColorCodeWithAnsiBackgroundColor() {
+ assertEquals '002' "$(getColorCode 'bg-green')"
+}
+
+function testGetColorCodeWithNumericalColor() {
+ assertEquals '002' "$(getColorCode '002')"
+}
+
+function testIsSameColorComparesAnsiForegroundAndNumericalColorCorrectly() {
+ assertTrue "isSameColor 'green' '002'"
+}
+
+function testIsSameColorComparesAnsiBackgroundAndNumericalColorCorrectly() {
+ assertTrue "isSameColor 'bg-green' '002'"
+}
+
+function testIsSameColorComparesNumericalBackgroundAndNumericalColorCorrectly() {
+ assertTrue "isSameColor '010' '2'"
+}
+
+function testIsSameColorDoesNotYieldNotEqualColorsTruthy() {
+ assertFalse "isSameColor 'green' '003'"
+}
+
+
+source shunit2/source/2.1/src/shunit2
diff --git a/test/functions/utilities.spec b/test/functions/utilities.spec
new file mode 100755
index 00000000..a9bd67e3
--- /dev/null
+++ b/test/functions/utilities.spec
@@ -0,0 +1,109 @@
+#!/usr/bin/env zsh
+#vim:ft=zsh ts=2 sw=2 sts=2 et fenc=utf-8
+
+# Required for shunit2 to run correctly
+setopt shwordsplit
+SHUNIT_PARENT=$0
+
+function setUp() {
+ # Load Powerlevel9k
+ source functions/icons.zsh
+ source functions/utilities.zsh
+}
+
+function testDefinedFindsDefinedVariable() {
+ my_var='X'
+
+ assertTrue "defined 'my_var'"
+ unset my_var
+}
+
+function testDefinedDoesNotFindUndefinedVariable() {
+ assertFalse "defined 'my_var'"
+}
+
+function testSetDefaultSetsVariable() {
+ set_default 'my_var' 'x'
+
+ assertEquals 'x' "$my_var"
+ unset my_var
+}
+
+function testPrintSizeHumanReadableWithBigNumber() {
+ # Interesting: Currently we can't support numbers bigger than that.
+ assertEquals '0.87E' "$(printSizeHumanReadable 1000000000000000000)"
+}
+
+function testPrintSizeHumanReadableWithExabytesAsBase() {
+ assertEquals '9.77Z' "$(printSizeHumanReadable 10000 'E')"
+}
+
+function testGetRelevantItem() {
+ typeset -a list
+ list=(a b c)
+ local callback='[[ "$item" == "b" ]] && echo "found"'
+
+ local result=$(getRelevantItem "$list" "$callback")
+ assertEquals 'found' "$result"
+
+ unset list
+}
+
+function testGetRelevantItemDoesNotReturnNotFoundItems() {
+ typeset -a list
+ list=(a b c)
+ local callback='[[ "$item" == "d" ]] && echo "found"'
+
+ local result=$(getRelevantItem "$list" "$callback")
+ assertEquals '' ''
+
+ unset list
+}
+
+function testSegmentShouldBeJoinedIfDirectPredecessingSegmentIsJoined() {
+ typeset -a segments
+ segments=(a b_joined c_joined)
+ # Look at the third segment
+ local current_index=3
+ local last_element_index=2
+
+ local joined
+ segmentShouldBeJoined $current_index $last_element_index "$segments" && joined=true || joined=false
+ assertTrue "$joined"
+
+ unset segments
+}
+
+function testSegmentShouldBeJoinedIfPredecessingSegmentIsJoinedTransitivley() {
+ typeset -a segments
+ segments=(a b_joined c_joined)
+ # Look at the third segment
+ local current_index=3
+ # The last printed segment was the first one,
+ # the second segmend was conditional.
+ local last_element_index=1
+
+ local joined
+ segmentShouldBeJoined $current_index $last_element_index "$segments" && joined=true || joined=false
+ assertTrue "$joined"
+
+ unset segments
+}
+
+function testSegmentShouldNotBeJoinedIfPredecessingSegmentIsNotJoinedButConditional() {
+ typeset -a segments
+ segments=(a b_joined c d_joined)
+ # Look at the fourth segment
+ local current_index=4
+ # The last printed segment was the first one,
+ # the second segmend was conditional.
+ local last_element_index=1
+
+ local joined
+ segmentShouldBeJoined $current_index $last_element_index "$segments" && joined=true || joined=false
+ assertFalse "$joined"
+
+ unset segments
+}
+
+source shunit2/source/2.1/src/shunit2
diff --git a/test/powerlevel9k.spec b/test/powerlevel9k.spec
new file mode 100755
index 00000000..1aab2c5f
--- /dev/null
+++ b/test/powerlevel9k.spec
@@ -0,0 +1,95 @@
+#!/usr/bin/env zsh
+#vim:ft=zsh ts=2 sw=2 sts=2 et fenc=utf-8
+
+# Required for shunit2 to run correctly
+setopt shwordsplit
+SHUNIT_PARENT=$0
+
+function setUp() {
+ export TERM="xterm-256color"
+ # Load Powerlevel9k
+ source powerlevel9k.zsh-theme
+ source functions/*
+}
+
+function testJoinedSegments() {
+ POWERLEVEL9K_LEFT_PROMPT_ELEMENTS=(dir dir_joined)
+
+ assertEquals "%K{blue} %F{black}%~ %K{blue}%F{black}%F{black}%~ %k%F{blue}%f " "$(build_left_prompt)"
+
+ unset POWERLEVEL9K_LEFT_PROMPT_ELEMENTS
+}
+
+function testTransitiveJoinedSegments() {
+ POWERLEVEL9K_LEFT_PROMPT_ELEMENTS=(dir root_indicator_joined dir_joined)
+
+ assertEquals "%K{blue} %F{black}%~ %K{blue}%F{black}%F{black}%~ %k%F{blue}%f " "$(build_left_prompt)"
+
+ unset POWERLEVEL9K_LEFT_PROMPT_ELEMENTS
+}
+
+function testJoiningWithConditionalSegment() {
+ POWERLEVEL9K_LEFT_PROMPT_ELEMENTS=(dir background_jobs dir_joined)
+
+ assertEquals "%K{blue} %F{black}%~ %K{blue}%F{black} %F{black}%~ %k%F{blue}%f " "$(build_left_prompt)"
+
+ unset POWERLEVEL9K_LEFT_PROMPT_ELEMENTS
+}
+
+function testDynamicColoringOfSegmentsWork() {
+ POWERLEVEL9K_LEFT_PROMPT_ELEMENTS=(dir)
+ POWERLEVEL9K_DIR_HOME_SUBFOLDER_BACKGROUND='red'
+
+ assertEquals "%K{red} %F{black}%~ %k%F{red}%f " "$(build_left_prompt)"
+
+ unset POWERLEVEL9K_LEFT_PROMPT_ELEMENTS
+ unset POWERLEVEL9K_DIR_HOME_SUBFOLDER_BACKGROUND
+}
+
+function testDynamicColoringOfVisualIdentifiersWork() {
+ POWERLEVEL9K_LEFT_PROMPT_ELEMENTS=(dir)
+ POWERLEVEL9K_MODE='awesome-patched'
+ POWERLEVEL9K_DIR_HOME_SUBFOLDER_VISUAL_IDENTIFIER_COLOR='green'
+
+ # Re-Source the icons, as the POWERLEVEL9K_MODE is directly
+ # evaluated there.
+ source functions/icons.zsh
+
+ assertEquals "%K{blue} %F{green%}%f %F{black}%~ %k%F{blue}%f " "$(build_left_prompt)"
+
+ unset POWERLEVEL9K_LEFT_PROMPT_ELEMENTS
+ unset POWERLEVEL9K_MODE
+ unset POWERLEVEL9K_DIR_HOME_SUBFOLDER_VISUAL_IDENTIFIER_COLOR
+}
+
+function testColoringOfVisualIdentifiersDoesNotOverwriteColoringOfSegment() {
+ POWERLEVEL9K_LEFT_PROMPT_ELEMENTS=(dir)
+ POWERLEVEL9K_MODE='awesome-patched'
+ POWERLEVEL9K_DIR_HOME_SUBFOLDER_VISUAL_IDENTIFIER_COLOR='green'
+ POWERLEVEL9K_DIR_HOME_SUBFOLDER_FOREGROUND='red'
+ POWERLEVEL9K_DIR_HOME_SUBFOLDER_BACKGROUND='yellow'
+
+ # Re-Source the icons, as the POWERLEVEL9K_MODE is directly
+ # evaluated there.
+ source functions/icons.zsh
+
+ assertEquals "%K{yellow} %F{green%}%f %F{red}%~ %k%F{yellow}%f " "$(build_left_prompt)"
+
+ unset POWERLEVEL9K_LEFT_PROMPT_ELEMENTS
+ unset POWERLEVEL9K_MODE
+ unset POWERLEVEL9K_DIR_HOME_SUBFOLDER_VISUAL_IDENTIFIER_COLOR
+ unset POWERLEVEL9K_DIR_HOME_SUBFOLDER_FOREGROUND
+ unset POWERLEVEL9K_DIR_HOME_SUBFOLDER_BACKGROUND
+}
+
+function testOverwritingIconsWork() {
+ POWERLEVEL9K_LEFT_PROMPT_ELEMENTS=(dir)
+ POWERLEVEL9K_HOME_SUB_ICON='icon-here'
+
+ assertEquals "%K{blue} %F{black%}icon-here%f %F{black}%~ %k%F{blue}%f " "$(build_left_prompt)"
+
+ unset POWERLEVEL9K_LEFT_PROMPT_ELEMENTS
+ unset POWERLEVEL9K_DIR_HOME_SUB_ICON
+}
+
+source shunit2/source/2.1/src/shunit2
diff --git a/test/segments/dir.spec b/test/segments/dir.spec
new file mode 100755
index 00000000..035addea
--- /dev/null
+++ b/test/segments/dir.spec
@@ -0,0 +1,118 @@
+#!/usr/bin/env zsh
+#vim:ft=zsh ts=2 sw=2 sts=2 et fenc=utf-8
+
+# Required for shunit2 to run correctly
+setopt shwordsplit
+SHUNIT_PARENT=$0
+
+function setUp() {
+ export TERM="xterm-256color"
+ # Load Powerlevel9k
+ source powerlevel9k.zsh-theme
+}
+
+function testTruncateFoldersWorks() {
+ POWERLEVEL9K_LEFT_PROMPT_ELEMENTS=(dir)
+ POWERLEVEL9K_SHORTEN_DIR_LENGTH=2
+ POWERLEVEL9K_SHORTEN_STRATEGY='truncate_folders'
+
+ FOLDER=/tmp/powerlevel9k-test/1/12/123/1234/12345/123456/1234567/12345678/123456789
+ mkdir -p $FOLDER
+ cd $FOLDER
+
+ assertEquals "%K{blue} %F{black}%3(c:…/:)%2c %k%F{blue}%f " "$(build_left_prompt)"
+
+ cd -
+ rm -fr /tmp/powerlevel9k-test
+
+ unset FOLDER
+ unset POWERLEVEL9K_LEFT_PROMPT_ELEMENTS
+ unset POWERLEVEL9K_SHORTEN_DIR_LENGTH
+ unset POWERLEVEL9K_SHORTEN_STRATEGY
+}
+
+function testTruncateMiddleWorks() {
+ POWERLEVEL9K_LEFT_PROMPT_ELEMENTS=(dir)
+ POWERLEVEL9K_SHORTEN_DIR_LENGTH=2
+ POWERLEVEL9K_SHORTEN_STRATEGY='truncate_middle'
+
+ FOLDER=/tmp/powerlevel9k-test/1/12/123/1234/12345/123456/1234567/12345678/123456789
+ mkdir -p $FOLDER
+ cd $FOLDER
+
+ assertEquals "%K{blue} %F{black}/tmp/po…st/1/12/123/1234/12…45/12…56/12…67/12…78/123456789 %k%F{blue}%f " "$(build_left_prompt)"
+
+ cd -
+ rm -fr /tmp/powerlevel9k-test
+
+ unset FOLDER
+ unset POWERLEVEL9K_LEFT_PROMPT_ELEMENTS
+ unset POWERLEVEL9K_SHORTEN_DIR_LENGTH
+ unset POWERLEVEL9K_SHORTEN_STRATEGY
+}
+
+function testTruncationFromRightWorks() {
+ POWERLEVEL9K_LEFT_PROMPT_ELEMENTS=(dir)
+ POWERLEVEL9K_SHORTEN_DIR_LENGTH=2
+ POWERLEVEL9K_SHORTEN_STRATEGY='truncate_from_right'
+
+ FOLDER=/tmp/powerlevel9k-test/1/12/123/1234/12345/123456/1234567/12345678/123456789
+ mkdir -p $FOLDER
+ cd $FOLDER
+
+ assertEquals "%K{blue} %F{black}/tm…/po…/1/12/12…/12…/12…/12…/12…/12…/123456789 %k%F{blue}%f " "$(build_left_prompt)"
+
+ cd -
+ rm -fr /tmp/powerlevel9k-test
+
+ unset FOLDER
+ unset POWERLEVEL9K_LEFT_PROMPT_ELEMENTS
+ unset POWERLEVEL9K_SHORTEN_DIR_LENGTH
+ unset POWERLEVEL9K_SHORTEN_STRATEGY
+}
+
+function testHomeFolderDetectionWorks() {
+ POWERLEVEL9K_LEFT_PROMPT_ELEMENTS=(dir)
+ POWERLEVEL9K_HOME_ICON='home-icon'
+
+ cd ~
+ assertEquals "%K{blue} %F{black%}home-icon%f %F{black}%~ %k%F{blue}%f " "$(build_left_prompt)"
+
+ cd -
+ unset POWERLEVEL9K_LEFT_PROMPT_ELEMENTS
+ unset POWERLEVEL9K_HOME_ICON
+}
+
+function testHomeSubfolderDetectionWorks() {
+ POWERLEVEL9K_LEFT_PROMPT_ELEMENTS=(dir)
+ POWERLEVEL9K_HOME_SUB_ICON='sub-icon'
+
+ FOLDER=~/powerlevel9k-test
+ mkdir $FOLDER
+ cd $FOLDER
+ assertEquals "%K{blue} %F{black%}sub-icon%f %F{black}%~ %k%F{blue}%f " "$(build_left_prompt)"
+
+ cd -
+ rm -fr $FOLDER
+ unset FOLDER
+ unset POWERLEVEL9K_LEFT_PROMPT_ELEMENTS
+ unset POWERLEVEL9K_HOME_SUB_ICON
+}
+
+function testOtherFolderDetectionWorks() {
+ POWERLEVEL9K_LEFT_PROMPT_ELEMENTS=(dir)
+ POWERLEVEL9K_FOLDER_ICON='folder-icon'
+
+ FOLDER=/tmp/powerlevel9k-test
+ mkdir $FOLDER
+ cd $FOLDER
+ assertEquals "%K{blue} %F{black%}folder-icon%f %F{black}%~ %k%F{blue}%f " "$(build_left_prompt)"
+
+ cd -
+ rm -fr $FOLDER
+ unset FOLDER
+ unset POWERLEVEL9K_LEFT_PROMPT_ELEMENTS
+ unset POWERLEVEL9K_FOLDER_ICON
+}
+
+source shunit2/source/2.1/src/shunit2
diff --git a/test/segments/go_version.spec b/test/segments/go_version.spec
new file mode 100755
index 00000000..aa9f625d
--- /dev/null
+++ b/test/segments/go_version.spec
@@ -0,0 +1,40 @@
+#!/usr/bin/env zsh
+#vim:ft=zsh ts=2 sw=2 sts=2 et fenc=utf-8
+
+# Required for shunit2 to run correctly
+setopt shwordsplit
+SHUNIT_PARENT=$0
+
+function setUp() {
+ export TERM="xterm-256color"
+ # Load Powerlevel9k
+ source powerlevel9k.zsh-theme
+}
+
+function mockGo() {
+ echo 'go version go1.5.3 darwin/amd64'
+}
+
+function testGo() {
+ alias go=mockGo
+ POWERLEVEL9K_LEFT_PROMPT_ELEMENTS=(go_version)
+
+ assertEquals "%K{green} %F{255}go1.5.3 %k%F{green}%f " "$(build_left_prompt)"
+
+ unset POWERLEVEL9K_LEFT_PROMPT_ELEMENTS
+ unalias go
+}
+
+function testGoSegmentPrintsNothingIfGoIsNotAvailable() {
+ alias go=noGo
+ POWERLEVEL9K_CUSTOM_WORLD='echo world'
+ POWERLEVEL9K_LEFT_PROMPT_ELEMENTS=(custom_world go_version)
+
+ assertEquals "%K{white} %F{black}world %k%F{white}%f " "$(build_left_prompt)"
+
+ unset POWERLEVEL9K_LEFT_PROMPT_ELEMENTS
+ unset POWERLEVEL9K_CUSTOM_WORLD
+ unalias go
+}
+
+source shunit2/source/2.1/src/shunit2
diff --git a/test/segments/rust_version.spec b/test/segments/rust_version.spec
new file mode 100755
index 00000000..49b06bcf
--- /dev/null
+++ b/test/segments/rust_version.spec
@@ -0,0 +1,40 @@
+#!/usr/bin/env zsh
+#vim:ft=zsh ts=2 sw=2 sts=2 et fenc=utf-8
+
+# Required for shunit2 to run correctly
+setopt shwordsplit
+SHUNIT_PARENT=$0
+
+function setUp() {
+ export TERM="xterm-256color"
+ # Load Powerlevel9k
+ source powerlevel9k.zsh-theme
+}
+
+function mockRust() {
+ echo 'rustc 0.4.1a-alpha'
+}
+
+function testRust() {
+ alias rustc=mockRust
+ POWERLEVEL9K_LEFT_PROMPT_ELEMENTS=(rust_version)
+
+ assertEquals "%K{208} %F{black}Rust 0.4.1a-alpha %k%F{208}%f " "$(build_left_prompt)"
+
+ unset POWERLEVEL9K_LEFT_PROMPT_ELEMENTS
+ unalias rustc
+}
+
+function testRustPrintsNothingIfRustIsNotAvailable() {
+ alias rustc=noRust
+ POWERLEVEL9K_CUSTOM_WORLD='echo world'
+ POWERLEVEL9K_LEFT_PROMPT_ELEMENTS=(custom_world rust_version)
+
+ assertEquals "%K{white} %F{black}world %k%F{white}%f " "$(build_left_prompt)"
+
+ unset POWERLEVEL9K_LEFT_PROMPT_ELEMENTS
+ unset POWERLEVEL9K_CUSTOM_WORLD
+ unalias rustc
+}
+
+source shunit2/source/2.1/src/shunit2