mirror of
https://github.com/b-ryan/powerline-shell.git
synced 2026-09-10 15:36:21 -04:00
Compare commits
111 commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4b19aa47f1 | ||
|
|
f091bdc61c | ||
|
|
0c9ccee860 | ||
|
|
0055f7c2b7 | ||
|
|
5763a35cc0 | ||
|
|
db35d233d1 | ||
|
|
70edbd062d | ||
|
|
7adadf1e04 | ||
|
|
4b681d8318 | ||
|
|
3433b92e86 | ||
|
|
56f78ca049 | ||
|
|
33d1ae1ae9 | ||
|
|
fd0b3a8ec4 | ||
|
|
256888344a | ||
|
|
a9b8c9bb39 | ||
|
|
7332357af6 | ||
|
|
09fd45d6fc | ||
|
|
feb9c8550e | ||
|
|
067202f71a | ||
|
|
e8a86cf8ff | ||
|
|
9d15bf7040 | ||
|
|
d095a2f3d5 | ||
|
|
54f7b90052 | ||
|
|
0ea47cc115 | ||
|
|
3d46c135dc | ||
|
|
7935d7ad11 | ||
|
|
3cf55e7b60 | ||
|
|
af919e1772 | ||
|
|
3b95178400 | ||
|
|
ee5776f10c | ||
|
|
36486483eb | ||
|
|
c2932e7e8f | ||
|
|
b53337c215 | ||
|
|
73b01d6597 | ||
|
|
c64da3dde4 | ||
|
|
08c07fa1f1 | ||
|
|
bbb7354068 | ||
|
|
5563655d82 | ||
|
|
b2797c77cd | ||
|
|
ac3be5f7b3 | ||
|
|
86fd04c7a8 | ||
|
|
668a964291 | ||
|
|
6eff2101be | ||
|
|
4e74b9a12a | ||
|
|
c9a1ea7f9f | ||
|
|
31bd259e9d | ||
|
|
8b9c0f2b80 | ||
|
|
8ff0806ac8 | ||
|
|
e828f264be | ||
|
|
095dc37dd0 | ||
|
|
e163b7aaeb | ||
|
|
15654cb79a | ||
|
|
404d3fff56 | ||
|
|
15a6172a2c | ||
|
|
7f72c1b031 | ||
|
|
709c5ba215 | ||
|
|
fc62b0f888 | ||
|
|
ae33f7e7cf | ||
|
|
d0dec6ce64 | ||
|
|
a209e6b12d | ||
|
|
755ba297aa | ||
|
|
cf6a804fd4 | ||
|
|
599f145208 | ||
|
|
da8d923f86 | ||
|
|
6ff4b50376 | ||
|
|
f6c7eaa10a | ||
|
|
9a9ce2ac79 | ||
|
|
389080f5bf | ||
|
|
b07c8ef4cb | ||
|
|
a494cd4a45 | ||
|
|
27574cc79b | ||
|
|
3ba8376175 | ||
|
|
47ca2df524 | ||
|
|
84a6b215c1 | ||
|
|
f0caebd26f | ||
|
|
9703379d58 | ||
|
|
b7dc34572c | ||
|
|
a9050d0f61 | ||
|
|
c413236ee6 | ||
|
|
235d3a8fda | ||
|
|
81653f4c0c | ||
|
|
0bca50bb18 | ||
|
|
15c4aee277 | ||
|
|
87b176037f | ||
|
|
e7964d1682 | ||
|
|
3c3062e3ce | ||
|
|
4b26d19907 | ||
|
|
f0293999c7 | ||
|
|
bcaa7e6e4d | ||
|
|
5db48c3014 | ||
|
|
a1b536b85b | ||
|
|
ad27ed4ccc | ||
|
|
4d4241fba0 | ||
|
|
ef5b837aef | ||
|
|
bbaacc1a3c | ||
|
|
8e2b00e7ff | ||
|
|
f8649ee985 | ||
|
|
235e02b831 | ||
|
|
88e3d6bcf8 | ||
|
|
d80fc8af82 | ||
|
|
e6c730c7ba | ||
|
|
8d33e5542e | ||
|
|
eb0f462717 | ||
|
|
006be7777f | ||
|
|
dee6ef0ded | ||
|
|
7c7e900bf0 | ||
|
|
21cfded8aa | ||
|
|
538bd54fc7 | ||
|
|
b76f20d6bd | ||
|
|
4942ad51e5 | ||
|
|
ef9c8f3e33 |
66
CHANGELOG.md
66
CHANGELOG.md
|
|
@ -1,5 +1,71 @@
|
|||
# Changes
|
||||
|
||||
2018-09-15 (version 0.7.0)
|
||||
|
||||
* New generic `stdout` and `env` segments
|
||||
|
||||
2018-06-20 (version 0.6.0)
|
||||
|
||||
* Support for custom themes
|
||||
* New option for the `time` segment to specify format of the displayed time
|
||||
([@dundalek](https://github.com/b-ryan/powerline-shell/pull/383))
|
||||
|
||||
2018-04-22 (version 0.5.4)
|
||||
|
||||
* Reverted fix for
|
||||
([#249](https://github.com/b-ryan/powerline-shell/issues/249)) because it
|
||||
caused issues on Mac.
|
||||
|
||||
2018-04-21 (version 0.5.3)
|
||||
|
||||
* New theme! (gruvbox)
|
||||
([@monicaycli](https://github.com/b-ryan/powerline-shell/pull/388))
|
||||
|
||||
2018-04-21 (version 0.5.2)
|
||||
|
||||
* Fix hostname colorize bug
|
||||
([@comagnaw](https://github.com/b-ryan/powerline-shell/issues/353))
|
||||
* Fix issue with prompt bleeding behavior
|
||||
([@bytebeast](https://github.com/b-ryan/powerline-shell/issues/249))
|
||||
* Better error message when config file cannot be decoded (Closes
|
||||
[#371](https://github.com/b-ryan/powerline-shell/issues/371))
|
||||
|
||||
2018-04-13 (version 0.5.1)
|
||||
|
||||
* Fix Python 3 compatibility of `git_stash` segment
|
||||
|
||||
2018-04-10 (version 0.5.0)
|
||||
|
||||
* Patch environment for VCS subprocesses rather than generating a new one
|
||||
* Fix `cwd` segment so it respects `max_depth` configuration
|
||||
* Fix Ruby segment for Python 3 compatibility
|
||||
([@Blue-Dog-Archolite](https://github.com/b-ryan/powerline-shell/pull/366))
|
||||
* Configuration is now expected to be at
|
||||
`~/.config/powerline-shell/config.json` ([@emansije and
|
||||
@kc9jud](https://github.com/b-ryan/powerline-shell/pull/334))
|
||||
* New `git_stash` segment
|
||||
([@apinkney97](https://github.com/b-ryan/powerline-shell/pull/379))
|
||||
|
||||
2018-02-19 (version 0.4.9)
|
||||
|
||||
* Fix root user segment
|
||||
([@TiGR](https://github.com/b-ryan/powerline-shell/pull/362))
|
||||
* Fixes and enhancements for SVN segment
|
||||
([@emansije](https://github.com/b-ryan/powerline-shell/pull/349))
|
||||
|
||||
2018-01-29 (version 0.4.8)
|
||||
|
||||
* Bring back the ability to create custom themes
|
||||
([@b-ryan](https://github.com/b-ryan/powerline-shell/pull/352))
|
||||
* Add the ability to customize the `time` segment in themes
|
||||
([@gaurav-nelson](https://github.com/b-ryan/powerline-shell/pull/338))
|
||||
|
||||
2018-01-15 (version 0.4.7)
|
||||
|
||||
* VCS segments (git, hg, etc.) can now show a symbol identifying what VPS the
|
||||
current directory uses
|
||||
([@emansije](https://github.com/b-ryan/powerline-shell/pull/298))
|
||||
|
||||
2018-01-11 (version 0.4.6)
|
||||
|
||||
* Fix bug in SVN segment
|
||||
|
|
|
|||
32
Dockerfile
32
Dockerfile
|
|
@ -1,6 +1,6 @@
|
|||
FROM aa8y/core:python2
|
||||
FROM python:2-alpine
|
||||
|
||||
MAINTAINER github.com/banga/powerline-shell
|
||||
MAINTAINER github.com/b-ryan/powerline-shell
|
||||
|
||||
USER root
|
||||
RUN apk add --no-cache --update \
|
||||
|
|
@ -9,25 +9,23 @@ RUN apk add --no-cache --update \
|
|||
git \
|
||||
mercurial \
|
||||
php5 \
|
||||
subversion && \
|
||||
subversion \
|
||||
&& \
|
||||
rm -rf /var/cache/apk/*
|
||||
|
||||
# Cache the dev requirements. Directory is set in the base image.
|
||||
WORKDIR $APP_DIR
|
||||
RUN mkdir /code
|
||||
WORKDIR /code
|
||||
COPY requirements-dev.txt .
|
||||
RUN pip install -r requirements-dev.txt && \
|
||||
rm -rf requirements-dev.txt
|
||||
rm requirements-dev.txt
|
||||
|
||||
# 'USER' is set in the base image. It points to a non-root user called 'docker'.
|
||||
USER $USER
|
||||
RUN bzr whoami "$USERNAME <$USER@example.com>" && \
|
||||
git config --global user.email "$USER@example.com" && \
|
||||
git config --global user.name "$USERNAME"
|
||||
RUN bzr whoami "root <root@example.com>" && \
|
||||
git config --global user.email "root@example.com" && \
|
||||
git config --global user.name "root"
|
||||
|
||||
COPY . ./
|
||||
USER root
|
||||
RUN ./setup.py install && \
|
||||
chown -R $USER:$USER .
|
||||
# COPY . ./
|
||||
# RUN ./setup.py install
|
||||
|
||||
USER $USER
|
||||
ENTRYPOINT ["/bin/bash"]
|
||||
ENV USER root
|
||||
|
||||
CMD ["nosetests"]
|
||||
|
|
|
|||
182
README.md
182
README.md
|
|
@ -1,9 +1,8 @@
|
|||
# A Powerline style prompt for your shell
|
||||
|
||||
A [Powerline](https://github.com/Lokaltog/vim-powerline) like prompt for Bash,
|
||||
ZSH, Fish, and tcsh:
|
||||
A beautiful and useful prompt generator for Bash, ZSH, Fish, and tcsh:
|
||||
|
||||

|
||||

|
||||
|
||||
- Shows some important details about the git/svn/hg/fossil branch (see below)
|
||||
- Changes color if the last command exited with a failure code
|
||||
|
|
@ -11,6 +10,10 @@ ZSH, Fish, and tcsh:
|
|||
- Shows the current Python [virtualenv](http://www.virtualenv.org/) environment
|
||||
- It's easy to customize and extend. See below for details.
|
||||
|
||||
The generated prompts are designed to resemble
|
||||
[powerline](https://github.com/powerline/powerline), but otherwise this project
|
||||
has no relation to powerline.
|
||||
|
||||
<!-- START doctoc generated TOC please keep comment here to allow auto update -->
|
||||
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
|
||||
**Table of Contents** *generated with [DocToc](https://github.com/thlorenz/doctoc)*
|
||||
|
|
@ -20,9 +23,11 @@ ZSH, Fish, and tcsh:
|
|||
- [Bash](#bash)
|
||||
- [ZSH](#zsh)
|
||||
- [Fish](#fish)
|
||||
- [tcsh](#tcsh)
|
||||
- [Customization](#customization)
|
||||
- [Config File](#config-file)
|
||||
- [Adding, Removing and Re-arranging segments](#adding-removing-and-re-arranging-segments)
|
||||
- [Generic Segments](#generic-segments)
|
||||
- [Segment Separator](#segment-separator)
|
||||
- [Themes](#themes)
|
||||
- [Segment Configuration](#segment-configuration)
|
||||
|
|
@ -42,24 +47,26 @@ quick look into the state of your repo:
|
|||
of commits is shown along with `⇡` or `⇣` indicating whether a git push
|
||||
or pull is pending.
|
||||
|
||||
In addition, git has a few extra symbols:
|
||||
If files are modified or in conflict, the situation is summarized with the
|
||||
following symbols:
|
||||
|
||||
- `✎` -- a file has been modified, but not staged for commit
|
||||
- `✔` -- a file is staged for commit
|
||||
- `✎` -- a file has been modified (but not staged for commit, in git)
|
||||
- `✔` -- a file is staged for commit (git) or added for tracking
|
||||
- `✼` -- a file has conflicts
|
||||
|
||||
FIXME
|
||||
|
||||
- A `+` appears when untracked files are present (except for git, which uses
|
||||
`?` instead)
|
||||
- `?` -- a file is untracked
|
||||
|
||||
Each of these will have a number next to it if more than one file matches.
|
||||
|
||||
The segment can start with a symbol representing the version control system in
|
||||
use. To show that symbol, the configuration file must have a variable `vcs`
|
||||
with an option `show_symbol` set to `true` (see
|
||||
[Segment Configuration](#segment-configuration)).
|
||||
|
||||
## Setup
|
||||
|
||||
This script uses ANSI color codes to display colors in a terminal. These are
|
||||
notoriously non-portable, so may not work for you out of the box, but try
|
||||
setting your $TERM to `xterm-256color`, because that works for me.
|
||||
setting your $TERM to `xterm-256color`.
|
||||
|
||||
- Patch the font you use for your terminal: see
|
||||
[powerline-fonts](https://github.com/Lokaltog/powerline-fonts)
|
||||
|
|
@ -84,7 +91,7 @@ install for just your user, if you'd like. But you may need to fiddle with your
|
|||
- Or, install from the git repository:
|
||||
|
||||
```
|
||||
git clone https://github.com/banga/powerline-shell
|
||||
git clone https://github.com/b-ryan/powerline-shell
|
||||
cd powerline-shell
|
||||
python setup.py install
|
||||
```
|
||||
|
|
@ -93,18 +100,23 @@ python setup.py install
|
|||
|
||||
### Bash
|
||||
|
||||
Add the following to your `.bashrc` (or `.profile` on Mac):
|
||||
Add the following to your `.bashrc` file:
|
||||
|
||||
```
|
||||
function _update_ps1() {
|
||||
PS1="$(powerline-shell $?)"
|
||||
PS1=$(powerline-shell $?)
|
||||
}
|
||||
|
||||
if [ "$TERM" != "linux" ]; then
|
||||
if [[ $TERM != linux && ! $PROMPT_COMMAND =~ _update_ps1 ]]; then
|
||||
PROMPT_COMMAND="_update_ps1; $PROMPT_COMMAND"
|
||||
fi
|
||||
```
|
||||
|
||||
**Note:** On macOS, you must add this to one of `.bash_profile`, `.bash_login`,
|
||||
or `.profile`. macOS will execute the files in the aforementioned order and
|
||||
will stop execution at the first file it finds. For more information on the
|
||||
order of precedence, see the section **INVOCATION** in `man bash`.
|
||||
|
||||
### ZSH
|
||||
|
||||
Add the following to your `.zshrc`:
|
||||
|
|
@ -123,7 +135,7 @@ function install_powerline_precmd() {
|
|||
precmd_functions+=(powerline_precmd)
|
||||
}
|
||||
|
||||
if [ "$TERM" != "linux" ]; then
|
||||
if [ "$TERM" != "linux" -a -x "$(command -v powerline-shell)" ]; then
|
||||
install_powerline_precmd
|
||||
fi
|
||||
```
|
||||
|
|
@ -151,53 +163,74 @@ alias precmd 'set prompt="`powerline-shell --shell tcsh $?`"'
|
|||
### Config File
|
||||
|
||||
Powerline-shell is customizable through the use of a config file. This file is
|
||||
expected to be located at `~/.powerline-shell.json`. You can generate the
|
||||
default config at this location using:
|
||||
expected to be located at `~/.config/powerline-shell/config.json`. You can
|
||||
generate the default config at this location using:
|
||||
|
||||
```
|
||||
powerline-shell --generate-config > ~/.powerline-shell.json
|
||||
mkdir -p ~/.config/powerline-shell && \
|
||||
powerline-shell --generate-config > ~/.config/powerline-shell/config.json
|
||||
```
|
||||
|
||||
(You can see an example config file
|
||||
[here](https://github.com/b-ryan/dotfiles/blob/master/home/powerline-shell.json))
|
||||
(As an example, my config file is located here:
|
||||
[here](https://github.com/b-ryan/dotfiles/blob/master/home/config/powerline-shell/config.json))
|
||||
|
||||
### Adding, Removing and Re-arranging segments
|
||||
|
||||
Once you have generated your config file, you can now start adding or removing
|
||||
"segments" - the building blocks of your shell. The list of segments available
|
||||
are:
|
||||
can be seen
|
||||
[here](https://github.com/b-ryan/powerline-shell/tree/master/powerline_shell/segments).
|
||||
|
||||
- `aws_profile` - Show which AWS profile is in use. See the
|
||||
[AWS](http://docs.aws.amazon.com/cli/latest/userguide/cli-multiple-profiles.html)
|
||||
documentation.
|
||||
- `battery` - See percentage of battery charged and an icon when the battery is
|
||||
charging.
|
||||
- `bzr` - Details about the current Bazaar repo.
|
||||
- `cwd` - Shows your current working directory. See [Segment
|
||||
Configuration](#segment-configuration) for some options.
|
||||
- `exit_code` - When the previous command ends in a non-zero status, shows the
|
||||
value of the exit status in red.
|
||||
- `fossil` - Details about the current Fossil repo.
|
||||
- `git` - Details about the current Git repo.
|
||||
- `hg` - Details about the current Mercurial repo.
|
||||
- `hostname` - Current machine's hostname.
|
||||
- `jobs` - Number of background jobs currently running.
|
||||
- `newline` - Inserts a newline into the prompt.
|
||||
- `node_version` - `node --version`
|
||||
- `npm_version` - `npm --version`
|
||||
- `php_version` - Version of php on the machine.
|
||||
- `rbenv` - `rbenv local`
|
||||
- `read_only` - Shows a lock icon if the current directory is read-only.
|
||||
- `root` - Shows a `#` if logged in as root, `$` otherwise.
|
||||
- `ruby_version` - `ruby --version`
|
||||
- `set_term_title` - If able, sets the title of your terminal to include some
|
||||
useful info.
|
||||
- `ssh` - If logged into over SSH, shows a network icon.
|
||||
- `svn` - Details about the current SVN repo.
|
||||
- `time` - Shows the current time.
|
||||
- `uptime` - Uptime of the current machine.
|
||||
- `username` - Name of the logged-in user.
|
||||
- `virtual_env` - Shows the name of the current virtual env or conda env.
|
||||
You can also create custom segments. Start by copying an existing segment like
|
||||
[this](https://github.com/b-ryan/powerline-shell/blob/master/powerline_shell/segments/aws_profile.py).
|
||||
Make sure to change any relative imports to absolute imports. Ie. change things
|
||||
like:
|
||||
|
||||
```python
|
||||
from ..utils import BasicSegment
|
||||
```
|
||||
|
||||
to
|
||||
|
||||
```python
|
||||
from powerline_shell.utils import BasicSegment
|
||||
```
|
||||
|
||||
Then change the `add_to_powerline` function to do what you want. You can then
|
||||
use this segment in your configuration by putting the path to your segment in
|
||||
the segments section, like:
|
||||
|
||||
```json
|
||||
"segments": [
|
||||
"~/path/to/segment.py"
|
||||
]
|
||||
```
|
||||
|
||||
### Generic Segments
|
||||
|
||||
There are two special segments available. `stdout` accepts an arbitrary command
|
||||
and the output of the command will be put into your prompt. `env` takes an
|
||||
environment variable and the value of the variable will be set in your prompt.
|
||||
For example, your config could look like this:
|
||||
|
||||
```
|
||||
{
|
||||
"segments": [
|
||||
"cwd",
|
||||
"git",
|
||||
{
|
||||
"type": "stdout",
|
||||
"command": ["echo", "hi"],
|
||||
"fg_color": 22,
|
||||
"bg_color": 161
|
||||
},
|
||||
{
|
||||
"type": "env",
|
||||
"var": "DOCKER_MACHINE_NAME"
|
||||
},
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### Segment Separator
|
||||
|
||||
|
|
@ -216,9 +249,20 @@ file. The available modes are:
|
|||
The `powerline_shell/themes` directory stores themes for your prompt, which are
|
||||
basically color values used by segments. The `default.py` defines a default
|
||||
theme which can be used standalone, and every other theme falls back to it if
|
||||
they miss colors for any segments. Create new themes by copying any other
|
||||
existing theme and changing the values. To use a theme, set the `theme`
|
||||
variable in `~/.powerline-shell.json` to the name of your theme.
|
||||
they miss colors for any segments.
|
||||
|
||||
If you want to create a custom theme, start by copying one of the existing
|
||||
themes, like the
|
||||
[basic](https://github.com/b-ryan/powerline-shell/blob/master/powerline_shell/themes/basic.py).
|
||||
and update your `~/.config/powerline-shell/config.json`, setting the `"theme"`
|
||||
to the path of the file. For example your configuration might have:
|
||||
|
||||
```
|
||||
"theme": "~/mythemes/my-great-theme.py"
|
||||
```
|
||||
|
||||
You can then modify the color codes to your liking. Theme colors are specified
|
||||
using [Xterm-256 color codes](https://jonasjacek.github.io/colors/).
|
||||
|
||||
A script for testing color combinations is provided at `colortest.py`. Note
|
||||
that the colors you see may vary depending on your terminal. When designing a
|
||||
|
|
@ -229,7 +273,7 @@ settings.
|
|||
|
||||
Some segments support additional configuration. The options for the segment are
|
||||
nested under the name of the segment itself. For example, all of the options
|
||||
for the `cwd` segment are set in `~/.powerline-shell.py` like:
|
||||
for the `cwd` segment are set in `~/.config/powerline-shell/config.json` like:
|
||||
|
||||
```
|
||||
{
|
||||
|
|
@ -237,13 +281,17 @@ for the `cwd` segment are set in `~/.powerline-shell.py` like:
|
|||
"cwd": {
|
||||
options go here
|
||||
}
|
||||
"theme": "theme-name",
|
||||
"vcs": {
|
||||
options go here
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
The options for the `cwd` segment are:
|
||||
|
||||
- `mode`: If "plain" then simple text will be used to show the cwd. If
|
||||
"dironly," only the current directory will be shown. Otherwise expands the
|
||||
- `mode`: If `plain`, then simple text will be used to show the cwd. If
|
||||
`dironly`, only the current directory will be shown. Otherwise expands the
|
||||
cwd into individual directories.
|
||||
- `max_depth`: Maximum number of directories to show in path.
|
||||
- `max_dir_size`: Maximum number of characters displayed for each directory in
|
||||
|
|
@ -256,11 +304,21 @@ The `hostname` segment provides one option:
|
|||
- `colorize`: If true, the hostname will be colorized based on a hash of
|
||||
itself.
|
||||
|
||||
The `vcs` segment provides one option:
|
||||
|
||||
- `show_symbol`: If `true`, the version control system segment will start with
|
||||
a symbol representing the specific version control system in use in the
|
||||
current directory.
|
||||
|
||||
The options for the `battery` segment are:
|
||||
|
||||
- `always_show_percentage`: If true, show percentage when fully charged on AC.
|
||||
- `low_threshold`: Threshold percentage for low-battery indicator color.
|
||||
|
||||
The options for the `time` segment are:
|
||||
|
||||
- `format`: Format string as used by strftime function, e.g. `%H:%M`.
|
||||
|
||||
### Contributing new types of segments
|
||||
|
||||
The `powerline_shell/segments` directory contains python scripts which are
|
||||
|
|
@ -284,6 +342,6 @@ requirements in `requirements-dev.txt`.
|
|||
|
||||
## Troubleshooting
|
||||
|
||||
See the [FAQ](https://github.com/banga/powerline-shell/wiki/FAQ). If you
|
||||
See the [FAQ](https://github.com/b-ryan/powerline-shell/wiki/FAQ). If you
|
||||
continue to have issues, please open an
|
||||
[issue](https://github.com/banga/powerline-shell/issues/new).
|
||||
[issue](https://github.com/b-ryan/powerline-shell/issues/new).
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import os
|
|||
import sys
|
||||
import importlib
|
||||
import json
|
||||
from .utils import warn, py3
|
||||
from .utils import warn, py3, import_file
|
||||
import re
|
||||
|
||||
|
||||
|
|
@ -114,7 +114,9 @@ class Powerline(object):
|
|||
def bgcolor(self, code):
|
||||
return self.color('48', code)
|
||||
|
||||
def append(self, content, fg, bg, separator=None, separator_fg=None):
|
||||
def append(self, content, fg, bg, separator=None, separator_fg=None, sanitize=True):
|
||||
if self.args.shell == "bash" and sanitize:
|
||||
content = re.sub(r"([`$])", r"\\\1", content)
|
||||
self.segments.append((content, fg, bg,
|
||||
separator if separator is not None else self.separator,
|
||||
separator_fg if separator_fg is not None else bg))
|
||||
|
|
@ -129,16 +131,12 @@ class Powerline(object):
|
|||
|
||||
def draw_segment(self, idx):
|
||||
segment = self.segments[idx]
|
||||
if self.args.shell == "bash":
|
||||
sanitized = re.sub(r"([`$])", r"\\\1", segment[0])
|
||||
else:
|
||||
sanitized = segment[0]
|
||||
next_segment = self.segments[idx + 1] if idx < len(self.segments)-1 else None
|
||||
|
||||
return ''.join((
|
||||
self.fgcolor(segment[1]),
|
||||
self.bgcolor(segment[2]),
|
||||
sanitized,
|
||||
segment[0],
|
||||
self.bgcolor(next_segment[2]) if next_segment else self.reset,
|
||||
self.fgcolor(segment[4]),
|
||||
segment[3]))
|
||||
|
|
@ -148,6 +146,7 @@ def find_config():
|
|||
for location in [
|
||||
"powerline-shell.json",
|
||||
"~/.powerline-shell.json",
|
||||
os.path.join(os.environ.get("XDG_CONFIG_HOME", "~/.config"), "powerline-shell", "config.json"),
|
||||
]:
|
||||
full = os.path.expanduser(location)
|
||||
if os.path.exists(full):
|
||||
|
|
@ -168,6 +167,28 @@ DEFAULT_CONFIG = {
|
|||
}
|
||||
|
||||
|
||||
class ModuleNotFoundException(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class CustomImporter(object):
|
||||
def __init__(self):
|
||||
self.file_import_count = 0
|
||||
|
||||
def import_(self, module_prefix, module_or_file, description):
|
||||
try:
|
||||
mod = importlib.import_module(module_prefix + module_or_file)
|
||||
except ImportError:
|
||||
try:
|
||||
module_name = "_custom_mod_{0}".format(self.file_import_count)
|
||||
mod = import_file(module_name, os.path.expanduser(module_or_file))
|
||||
self.file_import_count += 1
|
||||
except (ImportError, IOError):
|
||||
msg = "{0} {1} cannot be found".format(description, module_or_file)
|
||||
raise ModuleNotFoundException( msg)
|
||||
return mod
|
||||
|
||||
|
||||
def main():
|
||||
arg_parser = argparse.ArgumentParser()
|
||||
arg_parser.add_argument('--generate-config', action='store_true',
|
||||
|
|
@ -186,19 +207,33 @@ def main():
|
|||
config_path = find_config()
|
||||
if config_path:
|
||||
with open(config_path) as f:
|
||||
config = json.loads(f.read())
|
||||
try:
|
||||
config = json.loads(f.read())
|
||||
except Exception as e:
|
||||
warn("Config file ({0}) could not be decoded! Error: {1}"
|
||||
.format(config_path, e))
|
||||
config = DEFAULT_CONFIG
|
||||
else:
|
||||
config = DEFAULT_CONFIG
|
||||
|
||||
theme_name = config.get("theme", "default")
|
||||
mod = importlib.import_module("powerline_shell.themes." + theme_name)
|
||||
theme = getattr(mod, "Color")
|
||||
custom_importer = CustomImporter()
|
||||
theme_mod = custom_importer.import_(
|
||||
"powerline_shell.themes.",
|
||||
config.get("theme", "default"),
|
||||
"Theme")
|
||||
theme = getattr(theme_mod, "Color")
|
||||
|
||||
powerline = Powerline(args, config, theme)
|
||||
segments = []
|
||||
for seg_name in config["segments"]:
|
||||
mod = importlib.import_module("powerline_shell.segments." + seg_name)
|
||||
segment = getattr(mod, "Segment")(powerline)
|
||||
for seg_conf in config["segments"]:
|
||||
if not isinstance(seg_conf, dict):
|
||||
seg_conf = {"type": seg_conf}
|
||||
seg_name = seg_conf["type"]
|
||||
seg_mod = custom_importer.import_(
|
||||
"powerline_shell.segments.",
|
||||
seg_name,
|
||||
"Segment")
|
||||
segment = getattr(seg_mod, "Segment")(powerline, seg_conf)
|
||||
segment.start()
|
||||
segments.append(segment)
|
||||
for segment in segments:
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ from .utils import py3
|
|||
|
||||
|
||||
def getOppositeColor(r,g,b):
|
||||
r, g, b = [x/255.0 for x in [r, g, b]] # convert to float before getting hls value
|
||||
hls = rgb_to_hls(r,g,b)
|
||||
opp = list(hls[:])
|
||||
opp[0] = (opp[0]+0.2)%1 # shift hue (a.k.a. color)
|
||||
|
|
|
|||
|
|
@ -1,23 +1,11 @@
|
|||
import os
|
||||
import subprocess
|
||||
from ..utils import RepoStats, ThreadedSegment
|
||||
|
||||
|
||||
def get_PATH():
|
||||
"""Normally gets the PATH from the OS. This function exists to enable
|
||||
easily mocking the PATH in tests.
|
||||
"""
|
||||
return os.getenv("PATH")
|
||||
|
||||
|
||||
def bzr_subprocess_env():
|
||||
return {"PATH": get_PATH()}
|
||||
from ..utils import RepoStats, ThreadedSegment, get_subprocess_env
|
||||
|
||||
|
||||
def _get_bzr_branch():
|
||||
p = subprocess.Popen(['bzr', 'nick'],
|
||||
stdout=subprocess.PIPE, stderr=subprocess.PIPE,
|
||||
env=bzr_subprocess_env())
|
||||
env=get_subprocess_env())
|
||||
branch = p.communicate()[0].decode("utf-8").rstrip('\n')
|
||||
return branch
|
||||
|
||||
|
|
@ -47,7 +35,7 @@ def build_stats():
|
|||
try:
|
||||
p = subprocess.Popen(['bzr', 'status'],
|
||||
stdout=subprocess.PIPE, stderr=subprocess.PIPE,
|
||||
env=bzr_subprocess_env())
|
||||
env=get_subprocess_env())
|
||||
except OSError:
|
||||
# Popen will throw an OSError if bzr is not found
|
||||
return (None, None)
|
||||
|
|
@ -73,6 +61,9 @@ class Segment(ThreadedSegment):
|
|||
if self.stats.dirty:
|
||||
bg = self.powerline.theme.REPO_DIRTY_BG
|
||||
fg = self.powerline.theme.REPO_DIRTY_FG
|
||||
|
||||
self.powerline.append(" " + self.branch + " ", fg, bg)
|
||||
if self.powerline.segment_conf("vcs", "show_symbol"):
|
||||
symbol = RepoStats().symbols["bzr"] + " "
|
||||
else:
|
||||
symbol = ""
|
||||
self.powerline.append(" " + symbol + self.branch + " ", fg, bg)
|
||||
self.stats.add_to_powerline(self.powerline)
|
||||
|
|
|
|||
|
|
@ -58,10 +58,6 @@ def add_cwd_segment(powerline):
|
|||
cwd = cwd.decode("utf-8")
|
||||
cwd = replace_home_dir(cwd)
|
||||
|
||||
if powerline.segment_conf("cwd", "mode") == 'plain':
|
||||
powerline.append(' %s ' % (cwd,), powerline.theme.CWD_FG, powerline.theme.PATH_BG)
|
||||
return
|
||||
|
||||
names = split_path_into_names(cwd)
|
||||
|
||||
full_cwd = powerline.segment_conf("cwd", "full_cwd", False)
|
||||
|
|
@ -84,6 +80,12 @@ def add_cwd_segment(powerline):
|
|||
# displayed, so chop everything else off
|
||||
names = names[-1:]
|
||||
|
||||
elif powerline.segment_conf("cwd", "mode") == "plain":
|
||||
joined = os.path.sep.join(names)
|
||||
powerline.append(" %s " % (joined,), powerline.theme.CWD_FG,
|
||||
powerline.theme.PATH_BG)
|
||||
return
|
||||
|
||||
for i, name in enumerate(names):
|
||||
is_last_dir = (i == len(names) - 1)
|
||||
fg, bg = get_fg_bg(powerline, name, is_last_dir)
|
||||
|
|
|
|||
10
powerline_shell/segments/env.py
Normal file
10
powerline_shell/segments/env.py
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
import os
|
||||
from ..utils import BasicSegment
|
||||
|
||||
|
||||
class Segment(BasicSegment):
|
||||
def add_to_powerline(self):
|
||||
self.powerline.append(
|
||||
" %s " % os.getenv(self.segment_def["var"]),
|
||||
self.segment_def.get("fg_color", self.powerline.theme.PATH_FG),
|
||||
self.segment_def.get("bg_color", self.powerline.theme.PATH_BG))
|
||||
|
|
@ -1,17 +1,6 @@
|
|||
import os
|
||||
import subprocess
|
||||
from ..utils import RepoStats, ThreadedSegment
|
||||
|
||||
|
||||
def get_PATH():
|
||||
"""Normally gets the PATH from the OS. This function exists to enable
|
||||
easily mocking the PATH in tests.
|
||||
"""
|
||||
return os.getenv("PATH")
|
||||
|
||||
|
||||
def fossil_subprocess_env():
|
||||
return {"PATH": get_PATH()}
|
||||
from ..utils import RepoStats, ThreadedSegment, get_subprocess_env
|
||||
|
||||
|
||||
def _get_fossil_branch():
|
||||
|
|
@ -49,7 +38,7 @@ def build_stats():
|
|||
try:
|
||||
subprocess.Popen(['fossil'], stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE,
|
||||
env=fossil_subprocess_env()).communicate()
|
||||
env=get_subprocess_env()).communicate()
|
||||
except OSError:
|
||||
# Popen will throw an OSError if fossil is not found
|
||||
return (None, None)
|
||||
|
|
@ -74,6 +63,9 @@ class Segment(ThreadedSegment):
|
|||
if self.stats.dirty:
|
||||
bg = self.powerline.theme.REPO_DIRTY_BG
|
||||
fg = self.powerline.theme.REPO_DIRTY_FG
|
||||
|
||||
self.powerline.append(" " + self.branch + " ", fg, bg)
|
||||
if self.powerline.segment_conf("vcs", "show_symbol"):
|
||||
symbol = RepoStats().symbols["fossil"] + " "
|
||||
else:
|
||||
symbol = ""
|
||||
self.powerline.append(" " + symbol + self.branch + " ", fg, bg)
|
||||
self.stats.add_to_powerline(self.powerline)
|
||||
|
|
|
|||
|
|
@ -1,28 +1,6 @@
|
|||
import re
|
||||
import subprocess
|
||||
import os
|
||||
from ..utils import RepoStats, ThreadedSegment
|
||||
|
||||
|
||||
def get_PATH():
|
||||
"""Normally gets the PATH from the OS. This function exists to enable
|
||||
easily mocking the PATH in tests.
|
||||
"""
|
||||
return os.getenv("PATH")
|
||||
|
||||
|
||||
def git_subprocess_env():
|
||||
return {
|
||||
# LANG is specified to ensure git always uses a language we are expecting.
|
||||
# Otherwise we may be unable to parse the output.
|
||||
"LANG": "C",
|
||||
|
||||
# https://github.com/milkbikis/powerline-shell/pull/126
|
||||
"HOME": os.getenv("HOME"),
|
||||
|
||||
# https://github.com/milkbikis/powerline-shell/pull/153
|
||||
"PATH": get_PATH(),
|
||||
}
|
||||
from ..utils import RepoStats, ThreadedSegment, get_git_subprocess_env
|
||||
|
||||
|
||||
def parse_git_branch_info(status):
|
||||
|
|
@ -33,7 +11,7 @@ def parse_git_branch_info(status):
|
|||
def _get_git_detached_branch():
|
||||
p = subprocess.Popen(['git', 'describe', '--tags', '--always'],
|
||||
stdout=subprocess.PIPE, stderr=subprocess.PIPE,
|
||||
env=git_subprocess_env())
|
||||
env=get_git_subprocess_env())
|
||||
detached_ref = p.communicate()[0].decode("utf-8").rstrip('\n')
|
||||
if p.returncode == 0:
|
||||
branch = u'{} {}'.format(RepoStats.symbols['detached'], detached_ref)
|
||||
|
|
@ -63,7 +41,7 @@ def build_stats():
|
|||
try:
|
||||
p = subprocess.Popen(['git', 'status', '--porcelain', '-b'],
|
||||
stdout=subprocess.PIPE, stderr=subprocess.PIPE,
|
||||
env=git_subprocess_env())
|
||||
env=get_git_subprocess_env())
|
||||
except OSError:
|
||||
# Popen will throw an OSError if git is not found
|
||||
return (None, None)
|
||||
|
|
@ -98,6 +76,9 @@ class Segment(ThreadedSegment):
|
|||
if self.stats.dirty:
|
||||
bg = self.powerline.theme.REPO_DIRTY_BG
|
||||
fg = self.powerline.theme.REPO_DIRTY_FG
|
||||
|
||||
self.powerline.append(" " + self.branch + " ", fg, bg)
|
||||
if self.powerline.segment_conf("vcs", "show_symbol"):
|
||||
symbol = RepoStats().symbols["git"] + " "
|
||||
else:
|
||||
symbol = ""
|
||||
self.powerline.append(" " + symbol + self.branch + " ", fg, bg)
|
||||
self.stats.add_to_powerline(self.powerline)
|
||||
|
|
|
|||
34
powerline_shell/segments/git_stash.py
Normal file
34
powerline_shell/segments/git_stash.py
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
import subprocess
|
||||
from ..utils import RepoStats, ThreadedSegment, get_git_subprocess_env
|
||||
|
||||
|
||||
def get_stash_count():
|
||||
try:
|
||||
p = subprocess.Popen(['git', 'stash', 'list'],
|
||||
stdout=subprocess.PIPE, stderr=subprocess.PIPE,
|
||||
env=get_git_subprocess_env())
|
||||
except OSError:
|
||||
return 0
|
||||
|
||||
pdata = p.communicate()
|
||||
if p.returncode != 0:
|
||||
return 0
|
||||
|
||||
return pdata[0].count(b'\n')
|
||||
|
||||
|
||||
class Segment(ThreadedSegment):
|
||||
def run(self):
|
||||
self.stash_count = get_stash_count()
|
||||
|
||||
def add_to_powerline(self):
|
||||
self.join()
|
||||
if not self.stash_count:
|
||||
return
|
||||
|
||||
bg = self.powerline.theme.GIT_STASH_BG
|
||||
fg = self.powerline.theme.GIT_STASH_FG
|
||||
|
||||
sc = self.stash_count if self.stash_count > 1 else ''
|
||||
stash_str = u' {}{} '.format(sc, RepoStats.symbols['stash'])
|
||||
self.powerline.append(stash_str, fg, bg)
|
||||
|
|
@ -1,24 +1,12 @@
|
|||
import os
|
||||
import subprocess
|
||||
from ..utils import RepoStats, ThreadedSegment
|
||||
|
||||
|
||||
def get_PATH():
|
||||
"""Normally gets the PATH from the OS. This function exists to enable
|
||||
easily mocking the PATH in tests.
|
||||
"""
|
||||
return os.getenv("PATH")
|
||||
|
||||
|
||||
def hg_subprocess_env():
|
||||
return {"PATH": get_PATH()}
|
||||
from ..utils import RepoStats, ThreadedSegment, get_subprocess_env
|
||||
|
||||
|
||||
def _get_hg_branch():
|
||||
p = subprocess.Popen(["hg", "branch"],
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE,
|
||||
env=hg_subprocess_env())
|
||||
env=get_subprocess_env())
|
||||
branch = p.communicate()[0].decode("utf-8").rstrip('\n')
|
||||
return branch
|
||||
|
||||
|
|
@ -46,7 +34,7 @@ def build_stats():
|
|||
p = subprocess.Popen(["hg", "status"],
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE,
|
||||
env=hg_subprocess_env())
|
||||
env=get_subprocess_env())
|
||||
except OSError:
|
||||
# Will be thrown if hg cannot be found
|
||||
return None, None
|
||||
|
|
@ -72,5 +60,9 @@ class Segment(ThreadedSegment):
|
|||
if self.stats.dirty:
|
||||
bg = self.powerline.theme.REPO_DIRTY_BG
|
||||
fg = self.powerline.theme.REPO_DIRTY_FG
|
||||
self.powerline.append(" " + self.branch + " ", fg, bg)
|
||||
if self.powerline.segment_conf("vcs", "show_symbol"):
|
||||
symbol = RepoStats().symbols["hg"] + " "
|
||||
else:
|
||||
symbol = ""
|
||||
self.powerline.append(" " + symbol + self.branch + " ", fg, bg)
|
||||
self.stats.add_to_powerline(self.powerline)
|
||||
|
|
|
|||
|
|
@ -6,26 +6,30 @@ from ..utils import ThreadedSegment
|
|||
|
||||
|
||||
class Segment(ThreadedSegment):
|
||||
|
||||
def run(self):
|
||||
self.num_jobs = 0
|
||||
if platform.system().startswith('CYGWIN'):
|
||||
system = platform.system()
|
||||
if system.startswith("CYGWIN") or system.startswith("MINGW"):
|
||||
# cygwin ps is a special snowflake...
|
||||
output_proc = subprocess.Popen(['ps', '-af'], stdout=subprocess.PIPE)
|
||||
output = map(lambda l: int(l.split()[2].strip()),
|
||||
output_proc.communicate()[0].decode("utf-8").splitlines()[1:])
|
||||
output_proc = subprocess.Popen(["ps", "-af"], stdout=subprocess.PIPE)
|
||||
output = [int(l.split()[2].strip()) for l in output_proc.communicate()[0].decode("utf-8").splitlines()[1:]]
|
||||
self.num_jobs = output.count(os.getppid()) - 1
|
||||
else:
|
||||
pppid_proc = subprocess.Popen(['ps', '-p', str(os.getppid()), '-oppid='],
|
||||
stdout=subprocess.PIPE)
|
||||
pppid = pppid_proc.communicate()[0].decode("utf-8").strip()
|
||||
output_proc = subprocess.Popen(['ps', '-a', '-o', 'ppid'],
|
||||
stdout=subprocess.PIPE)
|
||||
# The following logic was tested on:
|
||||
# - fish, version 3.3.1
|
||||
# - GNU bash, version 5.1.16(1)-release (x86_64-pc-linux-gnu)
|
||||
# - zsh 5.8.1 (x86_64-ubuntu-linux-gnu)
|
||||
# If you change the behavior to account for another shell's
|
||||
# behavior, please provide details of the shell version you tested
|
||||
# on in this comment.
|
||||
output_proc = subprocess.Popen(["ps", "-a", "-o", "ppid"], stdout=subprocess.PIPE)
|
||||
output = output_proc.communicate()[0].decode("utf-8")
|
||||
self.num_jobs = len(re.findall(str(pppid), output)) - 1
|
||||
self.num_jobs = len(re.findall(str(os.getppid()), output)) - 1
|
||||
|
||||
def add_to_powerline(self):
|
||||
self.join()
|
||||
if self.num_jobs > 0:
|
||||
self.powerline.append(' %d ' % self.num_jobs,
|
||||
self.powerline.append(" %d " % self.num_jobs,
|
||||
self.powerline.theme.JOBS_FG,
|
||||
self.powerline.theme.JOBS_BG)
|
||||
|
|
|
|||
|
|
@ -1,12 +1,14 @@
|
|||
import subprocess
|
||||
from ..utils import ThreadedSegment
|
||||
from ..utils import ThreadedSegment, decode
|
||||
|
||||
|
||||
class Segment(ThreadedSegment):
|
||||
def run(self):
|
||||
self.version = None
|
||||
try:
|
||||
output = subprocess.check_output(['php', '-r', 'echo PHP_VERSION;'],
|
||||
stderr=subprocess.STDOUT)
|
||||
output = decode(
|
||||
subprocess.check_output(['php', '-r', 'echo PHP_VERSION;'],
|
||||
stderr=subprocess.STDOUT))
|
||||
self.version = output.split('-')[0] if '-' in output else output
|
||||
except OSError:
|
||||
self.version = None
|
||||
|
|
|
|||
|
|
@ -15,4 +15,4 @@ class Segment(BasicSegment):
|
|||
if powerline.args.prev_error != 0:
|
||||
fg = powerline.theme.CMD_FAILED_FG
|
||||
bg = powerline.theme.CMD_FAILED_BG
|
||||
powerline.append(root_indicators[powerline.args.shell], fg, bg)
|
||||
powerline.append(root_indicators[powerline.args.shell], fg, bg, sanitize=False)
|
||||
|
|
|
|||
|
|
@ -6,14 +6,17 @@ from ..utils import BasicSegment
|
|||
class Segment(BasicSegment):
|
||||
def add_to_powerline(self):
|
||||
powerline = self.powerline
|
||||
|
||||
try:
|
||||
p1 = subprocess.Popen(["ruby", "-v"], stdout=subprocess.PIPE)
|
||||
p2 = subprocess.Popen(["sed", "s/ (.*//"], stdin=p1.stdout, stdout=subprocess.PIPE)
|
||||
version = p2.communicate()[0].decode("utf-8").rstrip()
|
||||
if os.environ.has_key("GEM_HOME"):
|
||||
gem = os.environ["GEM_HOME"].split("@")
|
||||
if len(gem) > 1:
|
||||
version += " " + gem[1]
|
||||
powerline.append(version, 15, 1)
|
||||
p1 = subprocess.Popen(['ruby', '-v'], stdout=subprocess.PIPE)
|
||||
p2 = subprocess.Popen(['sed', "s/ (.*//"], stdin=p1.stdout, stdout=subprocess.PIPE)
|
||||
ruby_and_gemset = p2.communicate()[0].decode('utf-8').rstrip()
|
||||
|
||||
gem_set = os.environ.get('GEM_HOME', '@').split('@')
|
||||
|
||||
if len(gem_set) > 1:
|
||||
ruby_and_gemset += "@{}".format(gem_set.pop())
|
||||
|
||||
powerline.append(ruby_and_gemset, 15, 1)
|
||||
except OSError:
|
||||
return
|
||||
|
|
|
|||
17
powerline_shell/segments/stdout.py
Normal file
17
powerline_shell/segments/stdout.py
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
import subprocess
|
||||
from ..utils import ThreadedSegment
|
||||
|
||||
|
||||
class Segment(ThreadedSegment):
|
||||
def run(self):
|
||||
cmd = self.segment_def["command"]
|
||||
self.output = subprocess.check_output(cmd).decode("utf-8").strip()
|
||||
# TODO handle OSError
|
||||
# TODO handle no command defined or malformed
|
||||
|
||||
def add_to_powerline(self):
|
||||
self.join()
|
||||
self.powerline.append(
|
||||
" %s " % self.output,
|
||||
self.segment_def.get("fg_color", self.powerline.theme.PATH_FG),
|
||||
self.segment_def.get("bg_color", self.powerline.theme.PATH_BG))
|
||||
|
|
@ -1,41 +1,57 @@
|
|||
import subprocess
|
||||
from ..utils import ThreadedSegment, RepoStats
|
||||
from ..utils import ThreadedSegment, RepoStats, get_subprocess_env
|
||||
|
||||
|
||||
def _get_svn_revision():
|
||||
p = subprocess.Popen(["svn", "info", "--xml"],
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE,
|
||||
env=get_subprocess_env())
|
||||
for line in p.communicate()[0].decode("utf-8").splitlines():
|
||||
if "revision" in line:
|
||||
revision = line.split("=")[1].split('"')[1]
|
||||
break
|
||||
return revision
|
||||
|
||||
|
||||
def parse_svn_stats(status):
|
||||
stats = RepoStats()
|
||||
for line in status:
|
||||
if line[0] == "?":
|
||||
stats.new += 1
|
||||
elif line[0] == "C":
|
||||
stats.conflicted += 1
|
||||
elif line[0] in ["A", "D", "I", "M", "R", "!", "~"]:
|
||||
stats.changed += 1
|
||||
return stats
|
||||
|
||||
|
||||
def _get_svn_status(output):
|
||||
"""This function exists to enable mocking the `svn status` output in tests.
|
||||
"""
|
||||
return output[0].decode("utf-8").splitlines()
|
||||
|
||||
|
||||
def build_stats():
|
||||
try:
|
||||
p = subprocess.Popen(['svn', 'status'],
|
||||
stdout=subprocess.PIPE, stderr=subprocess.PIPE,
|
||||
env=get_subprocess_env())
|
||||
except OSError:
|
||||
# Popen will throw an OSError if svn is not found
|
||||
return None, None
|
||||
pdata = p.communicate()
|
||||
if p.returncode != 0 or pdata[1][:22] == b'svn: warning: W155007:':
|
||||
return None, None
|
||||
status = _get_svn_status(pdata)
|
||||
stats = parse_svn_stats(status)
|
||||
revision = _get_svn_revision()
|
||||
return stats, revision
|
||||
|
||||
|
||||
class Segment(ThreadedSegment):
|
||||
def __init__(self, powerline):
|
||||
super(Segment, self).__init__(powerline)
|
||||
self.stats = None
|
||||
self.revision = ""
|
||||
|
||||
def run(self):
|
||||
try:
|
||||
svn_status = subprocess.Popen(["svn", "status"],
|
||||
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
svn_info = subprocess.Popen(["svn", "info"],
|
||||
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
svn_stdout, svn_stderr = svn_status.communicate()
|
||||
svn_info, _ = svn_info.communicate()
|
||||
except OSError:
|
||||
return
|
||||
|
||||
if len(svn_stderr.decode("utf-8").strip()) != 0:
|
||||
return
|
||||
|
||||
self.stats = RepoStats()
|
||||
for line in svn_stdout.splitlines():
|
||||
line = line.decode("utf-8").strip()
|
||||
if line[0] == "?":
|
||||
self.stats.new += 1
|
||||
elif line[0] == "C":
|
||||
self.stats.conflicted += 1
|
||||
elif line[0] in ["A", "D", "I", "M", "R", "!", "~"]:
|
||||
self.stats.changed += 1
|
||||
|
||||
for line in svn_info.splitlines():
|
||||
line = line.decode("utf-8").strip()
|
||||
if "Revision: " in line:
|
||||
self.revision = line.split(" ", 1)[1]
|
||||
self.stats, self.revision = build_stats()
|
||||
|
||||
def add_to_powerline(self):
|
||||
self.join()
|
||||
|
|
@ -46,6 +62,9 @@ class Segment(ThreadedSegment):
|
|||
if self.stats.dirty:
|
||||
bg = self.powerline.theme.REPO_DIRTY_BG
|
||||
fg = self.powerline.theme.REPO_DIRTY_FG
|
||||
|
||||
self.powerline.append(" rev " + self.revision + " ", fg, bg)
|
||||
if self.powerline.segment_conf("vcs", "show_symbol"):
|
||||
symbol = " " + RepoStats().symbols["svn"]
|
||||
else:
|
||||
symbol = ""
|
||||
self.powerline.append(symbol + " rev " + self.revision + " ", fg, bg)
|
||||
self.stats.add_to_powerline(self.powerline)
|
||||
|
|
|
|||
|
|
@ -6,12 +6,15 @@ import time
|
|||
class Segment(BasicSegment):
|
||||
def add_to_powerline(self):
|
||||
powerline = self.powerline
|
||||
if powerline.args.shell == 'bash':
|
||||
format = powerline.segment_conf('time', 'format')
|
||||
if format:
|
||||
time_ = ' %s ' % time.strftime(format)
|
||||
elif powerline.args.shell == 'bash':
|
||||
time_ = ' \\t '
|
||||
elif powerline.args.shell == 'zsh':
|
||||
time_ = ' %* '
|
||||
else:
|
||||
time_ = ' %s ' % time.strftime('%H:%M:%S')
|
||||
powerline.append(time_,
|
||||
powerline.theme.HOSTNAME_FG,
|
||||
powerline.theme.HOSTNAME_BG)
|
||||
powerline.theme.TIME_FG,
|
||||
powerline.theme.TIME_BG)
|
||||
|
|
|
|||
|
|
@ -1,13 +1,13 @@
|
|||
import subprocess
|
||||
import re
|
||||
from ..utils import BasicSegment
|
||||
from ..utils import BasicSegment, decode
|
||||
|
||||
|
||||
class Segment(BasicSegment):
|
||||
def add_to_powerline(self):
|
||||
powerline = self.powerline
|
||||
try:
|
||||
output = subprocess.check_output(['uptime'], stderr=subprocess.STDOUT).decode("utf-8")
|
||||
output = decode(subprocess.check_output(['uptime'], stderr=subprocess.STDOUT))
|
||||
raw_uptime = re.search('(?<=up).+(?=,\s+\d+\s+user)', output).group(0)
|
||||
day_search = re.search('\d+(?=\s+day)', output)
|
||||
days = '' if not day_search else '%sd ' % day_search.group(0)
|
||||
|
|
|
|||
|
|
@ -7,6 +7,9 @@ class Segment(BasicSegment):
|
|||
env = os.getenv('VIRTUAL_ENV') \
|
||||
or os.getenv('CONDA_ENV_PATH') \
|
||||
or os.getenv('CONDA_DEFAULT_ENV')
|
||||
if os.getenv('VIRTUAL_ENV') \
|
||||
and os.path.basename(env) == '.venv':
|
||||
env = os.path.basename(os.path.dirname(env))
|
||||
if not env:
|
||||
return
|
||||
env_name = os.path.basename(env)
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
from .default import DefaultColor
|
||||
from powerline_shell.themes.default import DefaultColor
|
||||
|
||||
|
||||
class Color(DefaultColor):
|
||||
|
|
@ -40,3 +40,6 @@ class Color(DefaultColor):
|
|||
|
||||
AWS_PROFILE_FG = 14
|
||||
AWS_PROFILE_BG = 8
|
||||
|
||||
TIME_FG = 8
|
||||
TIME_BG = 7
|
||||
|
|
|
|||
|
|
@ -58,6 +58,9 @@ class DefaultColor(object):
|
|||
GIT_CONFLICTED_BG = 9
|
||||
GIT_CONFLICTED_FG = 15
|
||||
|
||||
GIT_STASH_BG = 221
|
||||
GIT_STASH_FG = 0
|
||||
|
||||
VIRTUAL_ENV_BG = 35 # a mid-tone green
|
||||
VIRTUAL_ENV_FG = 00
|
||||
|
||||
|
|
@ -69,6 +72,10 @@ class DefaultColor(object):
|
|||
AWS_PROFILE_FG = 39
|
||||
AWS_PROFILE_BG = 238
|
||||
|
||||
TIME_FG = 250
|
||||
TIME_BG = 238
|
||||
|
||||
|
||||
class Color(DefaultColor):
|
||||
"""
|
||||
This subclass is required when the user chooses to use 'default' theme.
|
||||
|
|
|
|||
111
powerline_shell/themes/gruvbox.py
Normal file
111
powerline_shell/themes/gruvbox.py
Normal file
|
|
@ -0,0 +1,111 @@
|
|||
from powerline_shell.themes.default import DefaultColor
|
||||
|
||||
"""
|
||||
absolute colors based on
|
||||
https://github.com/morhetz/gruvbox/blob/master/colors/gruvbox.vim
|
||||
"""
|
||||
dark0 = 235
|
||||
dark1 = 237
|
||||
dark2 = 239
|
||||
dark3 = 241
|
||||
dark4 = 243
|
||||
|
||||
light0 = 229
|
||||
light1 = 223
|
||||
light2 = 250
|
||||
light3 = 248
|
||||
light4 = 246
|
||||
|
||||
dark_gray = 245
|
||||
light_gray = 244
|
||||
|
||||
neutral_red = 124
|
||||
neutral_green = 106
|
||||
neutral_yellow = 172
|
||||
neutral_blue = 66
|
||||
neutral_purple = 132
|
||||
neutral_aqua = 72
|
||||
neutral_orange = 166
|
||||
|
||||
bright_red = 167
|
||||
bright_green = 142
|
||||
bright_yellow = 214
|
||||
bright_blue = 109
|
||||
bright_purple = 175
|
||||
bright_aqua = 108
|
||||
bright_orange = 208
|
||||
|
||||
faded_red = 88
|
||||
faded_green = 100
|
||||
faded_yellow = 136
|
||||
faded_blue = 24
|
||||
faded_purple = 96
|
||||
faded_aqua = 66
|
||||
faded_orange = 130
|
||||
|
||||
class Color(DefaultColor):
|
||||
USERNAME_ROOT_BG = faded_red
|
||||
USERNAME_BG = dark2
|
||||
USERNAME_FG = bright_purple
|
||||
|
||||
HOSTNAME_BG = dark1
|
||||
HOSTNAME_FG = bright_purple
|
||||
|
||||
HOME_SPECIAL_DISPLAY = True
|
||||
HOME_BG = neutral_blue
|
||||
HOME_FG = light2
|
||||
PATH_BG = dark3
|
||||
PATH_FG = light3
|
||||
CWD_FG = light2
|
||||
SEPARATOR_FG = dark_gray
|
||||
|
||||
READONLY_BG = bright_red
|
||||
READONLY_FG = light0
|
||||
|
||||
SSH_BG = faded_purple
|
||||
SSH_FG = light0
|
||||
|
||||
REPO_CLEAN_BG = faded_green
|
||||
REPO_CLEAN_FG = dark1
|
||||
REPO_DIRTY_BG = faded_orange
|
||||
REPO_DIRTY_FG = light0
|
||||
|
||||
JOBS_FG = neutral_aqua
|
||||
JOBS_BG = dark1
|
||||
|
||||
CMD_PASSED_FG = light4
|
||||
CMD_PASSED_BG = dark1
|
||||
CMD_FAILED_FG = light0
|
||||
CMD_FAILED_BG = neutral_red
|
||||
|
||||
SVN_CHANGES_FG = REPO_DIRTY_FG
|
||||
SVN_CHANGES_BG = REPO_DIRTY_BG
|
||||
|
||||
GIT_AHEAD_BG = dark2
|
||||
GIT_AHEAD_FG = light3
|
||||
GIT_BEHIND_BG = dark2
|
||||
GIT_BEHIND_FG = light3
|
||||
GIT_STAGED_BG = neutral_green
|
||||
GIT_STAGED_FG = light0
|
||||
GIT_NOTSTAGED_BG = neutral_orange
|
||||
GIT_NOTSTAGED_FG = light0
|
||||
GIT_UNTRACKED_BG = faded_red
|
||||
GIT_UNTRACKED_FG = light0
|
||||
GIT_CONFLICTED_BG = neutral_red
|
||||
GIT_CONFLICTED_FG = light0
|
||||
GIT_STASH_BG = neutral_yellow
|
||||
GIT_STASH_FG = dark0
|
||||
|
||||
VIRTUAL_ENV_BG = faded_green
|
||||
VIRTUAL_ENV_FG = light0
|
||||
|
||||
BATTERY_NORMAL_BG = neutral_green
|
||||
BATTERY_NORMAL_FG = dark2
|
||||
BATTERY_LOW_BG = neutral_red
|
||||
BATTERY_LOW_FG = light1
|
||||
|
||||
AWS_PROFILE_FG = neutral_aqua
|
||||
AWS_PROFILE_BG = dark1
|
||||
|
||||
TIME_FG = light2
|
||||
TIME_BG = dark4
|
||||
89
powerline_shell/themes/nord.py
Normal file
89
powerline_shell/themes/nord.py
Normal file
|
|
@ -0,0 +1,89 @@
|
|||
from powerline_shell.themes.default import DefaultColor
|
||||
|
||||
"""
|
||||
colors from https://www.nordtheme.com/docs/colors-and-palettes
|
||||
"""
|
||||
|
||||
night0 = 236 # nord0
|
||||
night1 = 237 # nord1
|
||||
night2 = 238 # nord2
|
||||
night3 = 239 # nord3
|
||||
snow0 = 253 # nord4
|
||||
snow1 = 254 # nord5
|
||||
snow2 = 255 # nord6
|
||||
frost0 = 109 # nord7
|
||||
frost1 = 111 # nord8
|
||||
frost2 = 110 # nord9
|
||||
frost3 = 68 # nord10
|
||||
red = 167 # nord11
|
||||
orange = 173 # nord12
|
||||
yellow = 179 # nord13
|
||||
green = 150 # nord14
|
||||
purple = 139 # nord15
|
||||
|
||||
class Color(DefaultColor):
|
||||
USERNAME_BG = night3
|
||||
USERNAME_FG = snow0
|
||||
|
||||
HOSTNAME_FG = snow0
|
||||
HOSTNAME_BG = night0
|
||||
|
||||
HOME_BG = frost2
|
||||
HOME_FG = snow2
|
||||
PATH_BG = night0
|
||||
PATH_FG = snow0
|
||||
CWD_FG = snow0
|
||||
SEPARATOR_FG = night3
|
||||
|
||||
READONLY_BG = red
|
||||
READONLY_FG = snow2
|
||||
|
||||
SSH_BG = orange
|
||||
SSH_FG = snow2
|
||||
|
||||
REPO_CLEAN_BG = green
|
||||
REPO_CLEAN_FG = night1
|
||||
REPO_DIRTY_BG = red
|
||||
REPO_DIRTY_FG = snow2
|
||||
|
||||
JOBS_FG = frost3
|
||||
JOBS_BG = night0
|
||||
|
||||
CMD_PASSED_BG = night0
|
||||
CMD_PASSED_FG = snow2
|
||||
CMD_FAILED_BG = yellow
|
||||
CMD_FAILED_FG = snow2
|
||||
|
||||
SVN_CHANGES_BG = REPO_DIRTY_FG
|
||||
SVN_CHANGES_FG = REPO_DIRTY_BG
|
||||
|
||||
GIT_AHEAD_BG = night3
|
||||
GIT_AHEAD_FG = snow0
|
||||
GIT_BEHIND_BG = night3
|
||||
GIT_BEHIND_FG = snow0
|
||||
|
||||
GIT_STAGED_BG = frost0
|
||||
GIT_STAGED_FG = night1
|
||||
GIT_NOTSTAGED_BG = orange
|
||||
GIT_NOTSTAGED_FG = snow2
|
||||
GIT_UNTRACKED_BG = purple
|
||||
GIT_UNTRACKED_FG = snow2
|
||||
GIT_CONFLICTED_BG = red
|
||||
GIT_CONFLICTED_FG = snow2
|
||||
|
||||
GIT_STASH_BG = yellow
|
||||
GIT_STASH_FG = night1
|
||||
|
||||
VIRTUAL_ENV_BG = green
|
||||
VIRTUAL_ENV_FG = night1
|
||||
|
||||
BATTERY_NORMAL_BG = green
|
||||
BATTERY_NORMAL_FG = night1
|
||||
BATTERY_LOW_BG = red
|
||||
BATTERY_LOW_FG = snow2
|
||||
|
||||
AWS_PROFILE_FG = frost3
|
||||
AWS_PROFILE_BG = night0
|
||||
|
||||
TIME_BG = night3
|
||||
TIME_FG = snow0
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
from .default import DefaultColor
|
||||
from powerline_shell.themes.default import DefaultColor
|
||||
|
||||
|
||||
class Color(DefaultColor):
|
||||
|
|
@ -39,3 +39,6 @@ class Color(DefaultColor):
|
|||
|
||||
AWS_PROFILE_FG = 7
|
||||
AWS_PROFILE_BG = 2
|
||||
|
||||
TIME_FG = 15
|
||||
TIME_BG = 10
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
from .default import DefaultColor
|
||||
from powerline_shell.themes.default import DefaultColor
|
||||
|
||||
|
||||
class Color(DefaultColor):
|
||||
|
|
@ -36,3 +36,6 @@ class Color(DefaultColor):
|
|||
|
||||
VIRTUAL_ENV_BG = 15
|
||||
VIRTUAL_ENV_FG = 2
|
||||
|
||||
TIME_FG = 15
|
||||
TIME_BG = 10
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
from .default import DefaultColor
|
||||
from powerline_shell.themes.default import DefaultColor
|
||||
|
||||
|
||||
class Color(DefaultColor):
|
||||
|
|
@ -39,3 +39,6 @@ class Color(DefaultColor):
|
|||
|
||||
AWS_PROFILE_FG = 0
|
||||
AWS_PROFILE_BG = 7
|
||||
|
||||
TIME_FG = 8
|
||||
TIME_BG = 7
|
||||
|
|
|
|||
|
|
@ -1,11 +1,17 @@
|
|||
import sys
|
||||
import os
|
||||
import threading
|
||||
|
||||
py3 = sys.version_info[0] == 3
|
||||
|
||||
if py3:
|
||||
def unicode(x):
|
||||
def unicode_(x):
|
||||
return str(x)
|
||||
def decode(x):
|
||||
return x.decode("utf-8")
|
||||
else:
|
||||
unicode_ = unicode
|
||||
decode = unicode
|
||||
|
||||
|
||||
class RepoStats(object):
|
||||
|
|
@ -16,7 +22,13 @@ class RepoStats(object):
|
|||
'staged': u'\u2714',
|
||||
'changed': u'\u270E',
|
||||
'new': u'?',
|
||||
'conflicted': u'\u273C'
|
||||
'conflicted': u'\u273C',
|
||||
'stash': u'\u2398',
|
||||
'git': u'\uE0A0',
|
||||
'hg': u'\u263F',
|
||||
'bzr': u'\u2B61\u20DF',
|
||||
'fossil': u'\u2332',
|
||||
'svn': u'\u2446'
|
||||
}
|
||||
|
||||
def __init__(self, ahead=0, behind=0, new=0, changed=0, staged=0, conflicted=0):
|
||||
|
|
@ -61,7 +73,7 @@ class RepoStats(object):
|
|||
|
||||
segment = repo_stats.n_or_empty("new") + icon_string
|
||||
"""
|
||||
return unicode(self[_key]) if int(self[_key]) > 1 else u''
|
||||
return unicode_(self[_key]) if int(self[_key]) > 1 else u''
|
||||
|
||||
def add_to_powerline(self, powerline):
|
||||
def add(_key, fg, bg):
|
||||
|
|
@ -82,14 +94,59 @@ def warn(msg):
|
|||
|
||||
|
||||
class BasicSegment(object):
|
||||
def __init__(self, powerline):
|
||||
def __init__(self, powerline, segment_def):
|
||||
self.powerline = powerline
|
||||
self.segment_def = segment_def # type: dict
|
||||
|
||||
def start(self):
|
||||
pass
|
||||
|
||||
|
||||
class ThreadedSegment(threading.Thread):
|
||||
def __init__(self, powerline):
|
||||
def __init__(self, powerline, segment_def):
|
||||
super(ThreadedSegment, self).__init__()
|
||||
self.powerline = powerline
|
||||
self.segment_def = segment_def # type: dict
|
||||
|
||||
|
||||
def import_file(module_name, path):
|
||||
# An implementation of https://stackoverflow.com/a/67692/683436
|
||||
if py3 and sys.version_info[1] >= 5:
|
||||
import importlib.util
|
||||
spec = importlib.util.spec_from_file_location(module_name, path)
|
||||
if not spec:
|
||||
raise ImportError()
|
||||
mod = importlib.util.module_from_spec(spec)
|
||||
spec.loader.exec_module(mod)
|
||||
return mod
|
||||
elif py3:
|
||||
from importlib.machinery import SourceFileLoader
|
||||
return SourceFileLoader(module_name, path).load_module()
|
||||
else:
|
||||
import imp
|
||||
return imp.load_source(module_name, path)
|
||||
|
||||
|
||||
def get_PATH():
|
||||
"""Normally gets the PATH from the OS. This function exists to enable
|
||||
easily mocking the PATH in tests.
|
||||
"""
|
||||
return os.getenv("PATH")
|
||||
|
||||
|
||||
def get_subprocess_env(**envs):
|
||||
defaults = {
|
||||
# https://github.com/milkbikis/powerline-shell/pull/153
|
||||
"PATH": get_PATH(),
|
||||
}
|
||||
defaults.update(envs)
|
||||
env = dict(os.environ)
|
||||
env.update(defaults)
|
||||
return env
|
||||
|
||||
|
||||
def get_git_subprocess_env():
|
||||
# LANG is specified to ensure git always uses a language we are expecting.
|
||||
# Otherwise we may be unable to parse the output.
|
||||
return get_subprocess_env(LANG="C")
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
nose>=1.3.7
|
||||
mock>=1.3.0
|
||||
sh>=1.11
|
||||
parameterized>=0.6.1
|
||||
15
setup.py
15
setup.py
|
|
@ -3,11 +3,20 @@ from setuptools import setup, find_packages
|
|||
|
||||
setup(
|
||||
name="powerline-shell",
|
||||
version="0.4.6",
|
||||
version="0.7.0",
|
||||
description="A pretty prompt for your shell",
|
||||
author="Buck Ryan",
|
||||
url="https://github.com/banga/powerline-shell",
|
||||
classifiers=[],
|
||||
author_email="buck@buckryan.com",
|
||||
license="MIT",
|
||||
url="https://github.com/b-ryan/powerline-shell",
|
||||
classifiers=[
|
||||
"Programming Language :: Python :: 2",
|
||||
"Programming Language :: Python :: 2.7",
|
||||
"Programming Language :: Python :: 3",
|
||||
"Programming Language :: Python :: 3.3",
|
||||
"Programming Language :: Python :: 3.4",
|
||||
"Programming Language :: Python :: 3.5",
|
||||
],
|
||||
packages=[
|
||||
"powerline_shell",
|
||||
"powerline_shell.segments",
|
||||
|
|
|
|||
6
test.sh
6
test.sh
|
|
@ -1,4 +1,6 @@
|
|||
#!/bin/sh
|
||||
|
||||
set -eu
|
||||
docker build -t powerline-shell .
|
||||
docker run --rm -it powerline-shell -c nosetests
|
||||
docker run --rm --interactive --tty \
|
||||
--volume $PWD:/code \
|
||||
powerline-shell "$@"
|
||||
|
|
|
|||
0
test/__init__.py
Normal file
0
test/__init__.py
Normal file
49
test/color_compliment_test.py
Normal file
49
test/color_compliment_test.py
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
import unittest
|
||||
from parameterized import parameterized
|
||||
|
||||
from powerline_shell.color_compliment import getOppositeColor
|
||||
|
||||
|
||||
def build_inputs():
|
||||
|
||||
# Build 768 hex/rgb values to test against getOppositeColor
|
||||
input_bytes = map(hex, xrange(pow(2,8)))
|
||||
|
||||
input_list = []
|
||||
for x in input_bytes:
|
||||
|
||||
#Building hex range of [00-ff]:00:00
|
||||
combined1 = hex((int(x,16)<<16)| ((int(input_bytes[0],16)<<8)|int(input_bytes[0],16)))
|
||||
test_input1 = tuple((int(x,16), int(input_bytes[0],16), int(input_bytes[0],16)))
|
||||
|
||||
#Building hex range of 00:[00-ff]:00
|
||||
combined2 = hex((int(input_bytes[0],16)<<16)| ((int(x,16)<<8)|int(input_bytes[0],16)))
|
||||
test_input2 = tuple((int(input_bytes[0],16), int(x,16), int(input_bytes[0],16)))
|
||||
|
||||
#Building hex range of 00:00:[00-ff]
|
||||
combined3 = hex((int(input_bytes[0],16)<<16)| ((int(input_bytes[0],16)<<8)|int(x,16)))
|
||||
test_input3 = tuple((int(input_bytes[0],16), int(input_bytes[0],16), int(x,16)))
|
||||
|
||||
input_list.append(tuple((combined1, test_input1)))
|
||||
input_list.append(tuple((combined2, test_input2)))
|
||||
input_list.append(tuple((combined3, test_input3)))
|
||||
|
||||
return input_list
|
||||
|
||||
class getOppositeColorTestCase(unittest.TestCase):
|
||||
|
||||
'''
|
||||
Test only runs against 768 combinations of rgb values.
|
||||
Trying to run parameterized unittest against 16.77M rgb values
|
||||
was near impossible (need lots of memory and time). Of the 768
|
||||
values tested, the test has proven to catch 192 exceptions (and 3
|
||||
ZeroDivisionError exceptions from rgb_to_hls). This can be tested
|
||||
by commenting out the first line of getOppositeColor, which
|
||||
converts the rgb values to float.
|
||||
'''
|
||||
|
||||
@parameterized.expand(build_inputs)
|
||||
|
||||
def test_rgb_input_get_opposite_not_negative(self, name, test_input):
|
||||
negative = -1
|
||||
self.assertNotIn(negative, getOppositeColor(*test_input), u'{0:#08x} returns negative number in rgb tuple'.format(int(name,16)))
|
||||
0
test/segments_test/__init__.py
Normal file
0
test/segments_test/__init__.py
Normal file
|
|
@ -5,6 +5,7 @@ import shutil
|
|||
import sh
|
||||
import powerline_shell.segments.bzr as bzr
|
||||
from powerline_shell.utils import RepoStats
|
||||
from ..testing_utils import dict_side_effect_fn
|
||||
|
||||
|
||||
test_cases = (
|
||||
|
|
@ -22,6 +23,9 @@ class BzrTest(unittest.TestCase):
|
|||
|
||||
def setUp(self):
|
||||
self.powerline = mock.MagicMock()
|
||||
self.powerline.segment_conf.side_effect = dict_side_effect_fn({
|
||||
("vcs", "show_symbol"): False,
|
||||
})
|
||||
|
||||
self.dirname = tempfile.mkdtemp()
|
||||
sh.cd(self.dirname)
|
||||
|
|
@ -30,7 +34,7 @@ class BzrTest(unittest.TestCase):
|
|||
sh.cd("trunk")
|
||||
sh.bzr("init")
|
||||
|
||||
self.segment = bzr.Segment(self.powerline)
|
||||
self.segment = bzr.Segment(self.powerline, {})
|
||||
|
||||
def tearDown(self):
|
||||
shutil.rmtree(self.dirname)
|
||||
|
|
@ -45,7 +49,7 @@ class BzrTest(unittest.TestCase):
|
|||
sh.bzr("branch", "trunk", branch)
|
||||
sh.cd(branch)
|
||||
|
||||
@mock.patch("powerline_shell.segments.bzr.get_PATH")
|
||||
@mock.patch("powerline_shell.utils.get_PATH")
|
||||
def test_bzr_not_installed(self, get_PATH):
|
||||
get_PATH.return_value = "" # so bzr can't be found
|
||||
self.segment.start()
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import shutil
|
|||
import sh
|
||||
import powerline_shell.segments.fossil as fossil
|
||||
from powerline_shell.utils import RepoStats
|
||||
from ..testing_utils import dict_side_effect_fn
|
||||
|
||||
test_cases = {
|
||||
"EXTRA new-file": RepoStats(new=1),
|
||||
|
|
@ -18,13 +19,16 @@ class FossilTest(unittest.TestCase):
|
|||
|
||||
def setUp(self):
|
||||
self.powerline = mock.MagicMock()
|
||||
self.powerline.segment_conf.side_effect = dict_side_effect_fn({
|
||||
("vcs", "show_symbol"): False,
|
||||
})
|
||||
|
||||
self.dirname = tempfile.mkdtemp()
|
||||
sh.cd(self.dirname)
|
||||
sh.fossil("init", "test.fossil")
|
||||
sh.fossil("open", "test.fossil")
|
||||
|
||||
self.segment = fossil.Segment(self.powerline)
|
||||
self.segment = fossil.Segment(self.powerline, {})
|
||||
|
||||
def tearDown(self):
|
||||
shutil.rmtree(self.dirname)
|
||||
|
|
@ -38,7 +42,7 @@ class FossilTest(unittest.TestCase):
|
|||
sh.fossil("branch", "new", branch, "trunk")
|
||||
sh.fossil("checkout", branch)
|
||||
|
||||
@mock.patch("powerline_shell.segments.fossil.get_PATH")
|
||||
@mock.patch("powerline_shell.utils.get_PATH")
|
||||
def test_fossil_not_installed(self, get_PATH):
|
||||
get_PATH.return_value = "" # so fossil can't be found
|
||||
self.segment.start()
|
||||
|
|
|
|||
77
test/segments_test/git_stash_test.py
Normal file
77
test/segments_test/git_stash_test.py
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
import unittest
|
||||
import mock
|
||||
import tempfile
|
||||
import shutil
|
||||
import sh
|
||||
import powerline_shell.segments.git_stash as git_stash
|
||||
from powerline_shell.utils import RepoStats
|
||||
|
||||
|
||||
class GitStashTest(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
self.powerline = mock.MagicMock()
|
||||
self.dirname = tempfile.mkdtemp()
|
||||
sh.cd(self.dirname)
|
||||
sh.git("init", ".")
|
||||
|
||||
self.segment = git_stash.Segment(self.powerline, {})
|
||||
|
||||
def tearDown(self):
|
||||
shutil.rmtree(self.dirname)
|
||||
|
||||
def _add_and_commit(self, filename):
|
||||
sh.touch(filename)
|
||||
sh.git("add", filename)
|
||||
sh.git("commit", "-m", "add file " + filename)
|
||||
|
||||
def _overwrite_file(self, filename, content):
|
||||
sh.echo(content, _out=filename)
|
||||
|
||||
def _stash(self):
|
||||
sh.git("stash")
|
||||
|
||||
@mock.patch('powerline_shell.utils.get_PATH')
|
||||
def test_git_not_installed(self, get_PATH):
|
||||
get_PATH.return_value = "" # so git can't be found
|
||||
self.segment.start()
|
||||
self.segment.add_to_powerline()
|
||||
self.assertEqual(self.powerline.append.call_count, 0)
|
||||
|
||||
def test_non_git_directory(self):
|
||||
shutil.rmtree(".git")
|
||||
self.segment.start()
|
||||
self.segment.add_to_powerline()
|
||||
self.assertEqual(self.powerline.append.call_count, 0)
|
||||
|
||||
def test_no_stashes(self):
|
||||
self._add_and_commit("foo")
|
||||
self.segment.start()
|
||||
self.segment.add_to_powerline()
|
||||
self.assertEqual(self.powerline.append.call_count, 0)
|
||||
|
||||
def test_one_stash(self):
|
||||
self._add_and_commit("foo")
|
||||
self._overwrite_file("foo", "some new content")
|
||||
self._stash()
|
||||
self.segment.start()
|
||||
self.segment.add_to_powerline()
|
||||
expected = u' {} '.format(RepoStats.symbols["stash"])
|
||||
self.assertEqual(self.powerline.append.call_args[0][0], expected)
|
||||
|
||||
def test_multiple_stashes(self):
|
||||
self._add_and_commit("foo")
|
||||
|
||||
self._overwrite_file("foo", "some new content")
|
||||
self._stash()
|
||||
|
||||
self._overwrite_file("foo", "some different content")
|
||||
self._stash()
|
||||
|
||||
self._overwrite_file("foo", "more different content")
|
||||
self._stash()
|
||||
|
||||
self.segment.start()
|
||||
self.segment.add_to_powerline()
|
||||
expected = u' 3{} '.format(RepoStats.symbols["stash"])
|
||||
self.assertEqual(self.powerline.append.call_args[0][0], expected)
|
||||
|
|
@ -4,18 +4,22 @@ import tempfile
|
|||
import shutil
|
||||
import sh
|
||||
import powerline_shell.segments.git as git
|
||||
from ..testing_utils import dict_side_effect_fn
|
||||
|
||||
|
||||
class GitTest(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
self.powerline = mock.MagicMock()
|
||||
self.powerline.segment_conf.side_effect = dict_side_effect_fn({
|
||||
("vcs", "show_symbol"): False,
|
||||
})
|
||||
|
||||
self.dirname = tempfile.mkdtemp()
|
||||
sh.cd(self.dirname)
|
||||
sh.git("init", ".")
|
||||
|
||||
self.segment = git.Segment(self.powerline)
|
||||
self.segment = git.Segment(self.powerline, {})
|
||||
|
||||
def tearDown(self):
|
||||
shutil.rmtree(self.dirname)
|
||||
|
|
@ -31,7 +35,7 @@ class GitTest(unittest.TestCase):
|
|||
def _get_commit_hash(self):
|
||||
return sh.git("rev-parse", "HEAD")
|
||||
|
||||
@mock.patch('powerline_shell.segments.git.get_PATH')
|
||||
@mock.patch('powerline_shell.utils.get_PATH')
|
||||
def test_git_not_installed(self, get_PATH):
|
||||
get_PATH.return_value = "" # so git can't be found
|
||||
self.segment.start()
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import shutil
|
|||
import sh
|
||||
import powerline_shell.segments.hg as hg
|
||||
from powerline_shell.utils import RepoStats
|
||||
from ..testing_utils import dict_side_effect_fn
|
||||
|
||||
|
||||
test_cases = {
|
||||
|
|
@ -20,12 +21,15 @@ class HgTest(unittest.TestCase):
|
|||
|
||||
def setUp(self):
|
||||
self.powerline = mock.MagicMock()
|
||||
self.powerline.segment_conf.side_effect = dict_side_effect_fn({
|
||||
("vcs", "show_symbol"): False,
|
||||
})
|
||||
|
||||
self.dirname = tempfile.mkdtemp()
|
||||
sh.cd(self.dirname)
|
||||
sh.hg("init", ".")
|
||||
|
||||
self.segment = hg.Segment(self.powerline)
|
||||
self.segment = hg.Segment(self.powerline, {})
|
||||
|
||||
def tearDown(self):
|
||||
shutil.rmtree(self.dirname)
|
||||
|
|
@ -38,7 +42,7 @@ class HgTest(unittest.TestCase):
|
|||
def _checkout_new_branch(self, branch):
|
||||
sh.hg("branch", branch)
|
||||
|
||||
@mock.patch("powerline_shell.segments.hg.get_PATH")
|
||||
@mock.patch("powerline_shell.utils.get_PATH")
|
||||
def test_hg_not_installed(self, get_PATH):
|
||||
get_PATH.return_value = "" # so hg can"t be found
|
||||
self.segment.start()
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ class HostnameTest(unittest.TestCase):
|
|||
def setUp(self):
|
||||
self.powerline = mock.MagicMock()
|
||||
self.powerline.theme = Color
|
||||
self.segment = hostname.Segment(self.powerline)
|
||||
self.segment = hostname.Segment(self.powerline, {})
|
||||
|
||||
def test_colorize(self):
|
||||
self.powerline.segment_conf.return_value = True
|
||||
|
|
|
|||
32
test/segments_test/svn_test.py
Normal file
32
test/segments_test/svn_test.py
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
import tempfile
|
||||
import unittest
|
||||
import shutil
|
||||
import mock
|
||||
import sh
|
||||
import powerline_shell.segments.svn as svn
|
||||
from ..testing_utils import dict_side_effect_fn
|
||||
|
||||
|
||||
class SvnTest(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
self.powerline = mock.MagicMock()
|
||||
self.powerline.segment_conf.side_effect = dict_side_effect_fn({
|
||||
("vcs", "show_symbol"): False,
|
||||
})
|
||||
|
||||
self.dirname = tempfile.mkdtemp()
|
||||
sh.cd(self.dirname)
|
||||
# sh.svn("init", ".")
|
||||
|
||||
self.segment = svn.Segment(self.powerline, {})
|
||||
|
||||
def tearDown(self):
|
||||
shutil.rmtree(self.dirname)
|
||||
|
||||
@mock.patch("powerline_shell.utils.get_PATH")
|
||||
def test_svn_not_installed(self, get_PATH):
|
||||
get_PATH.return_value = "" # so svn can't be found
|
||||
self.segment.start()
|
||||
self.segment.add_to_powerline()
|
||||
self.assertEqual(self.powerline.append.call_count, 0)
|
||||
|
|
@ -19,7 +19,7 @@ class UptimeTest(unittest.TestCase):
|
|||
|
||||
def setUp(self):
|
||||
self.powerline = mock.MagicMock()
|
||||
self.segment = uptime.Segment(self.powerline)
|
||||
self.segment = uptime.Segment(self.powerline, {})
|
||||
|
||||
@mock.patch('subprocess.check_output')
|
||||
def test_all(self, check_output):
|
||||
|
|
|
|||
4
test/testing_utils.py
Normal file
4
test/testing_utils.py
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
def dict_side_effect_fn(dict_):
|
||||
def func(*args):
|
||||
return dict_[args]
|
||||
return func
|
||||
Loading…
Reference in a new issue