mirror of
https://github.com/starship/starship.git
synced 2026-06-23 02:05:51 +07:00
Compare commits
127 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 29eedeb698 | |||
| dcc105ea1b | |||
| 9721666d33 | |||
| 3e5cac9852 | |||
| 86c4a4bdcf | |||
| 6658b7f0aa | |||
| 3435b9cdc2 | |||
| 69ebab46a4 | |||
| 61abe6dd7a | |||
| 313def1d92 | |||
| 80f0600b4f | |||
| eb724279da | |||
| 4f17bae315 | |||
| 2bdfcb1373 | |||
| f8ca3fd007 | |||
| 29325c6b50 | |||
| 1c66869117 | |||
| c5e693b638 | |||
| 8d353f72c6 | |||
| 23cf3e5b12 | |||
| e66d7bae1c | |||
| 68754208c1 | |||
| 84688e4981 | |||
| 5a0f269d85 | |||
| 789d504a44 | |||
| dfade6d629 | |||
| 6db0e20585 | |||
| f2f7815960 | |||
| b4fccc46d7 | |||
| 5e2c8c5745 | |||
| 470648000f | |||
| 722a0652fd | |||
| 59e8b1fc92 | |||
| f8929c2d7d | |||
| de4a715333 | |||
| ba225a6581 | |||
| b802fb6ed8 | |||
| 3dd035056d | |||
| 4eb7beca48 | |||
| 5f05d9e7af | |||
| c121dd4d44 | |||
| 9918dd1aac | |||
| c2a1803681 | |||
| ad8cd7334f | |||
| 9853743eda | |||
| ed27cf4a2c | |||
| cacaf66efe | |||
| fa2d1c05a6 | |||
| f61e7e2f87 | |||
| 656e0bb52e | |||
| e034253a5e | |||
| 81ea165cec | |||
| cdea401589 | |||
| 0fa862a2e9 | |||
| f7754455e6 | |||
| 08aef016cd | |||
| feb737190e | |||
| 57e807fec6 | |||
| 2d10cb2b30 | |||
| a5db918cfd | |||
| e31b3391f1 | |||
| b70f6f1ad3 | |||
| 68cbcb91b7 | |||
| 70d53ee7a9 | |||
| f74e639c49 | |||
| 1478f8c2e9 | |||
| 360ea988e5 | |||
| 1943da86ce | |||
| da86b4f847 | |||
| faa2280620 | |||
| f06247d5d3 | |||
| dcb78a4e0b | |||
| 2f9922ff2f | |||
| ff8b2a3387 | |||
| a08cc971ab | |||
| 075a76897c | |||
| 0e82c19f37 | |||
| 2e39c6d0fa | |||
| 7240a81e98 | |||
| 7f7d77b3d9 | |||
| 5b3641e50b | |||
| b39d31aaa7 | |||
| a8a553578b | |||
| a965b2587d | |||
| f54322f2ab | |||
| 51f723df22 | |||
| 664df257bf | |||
| f7a77edb35 | |||
| 5af70b9699 | |||
| 85ac0a6801 | |||
| 572a07c72d | |||
| dfe2ae643a | |||
| 8782e300fc | |||
| 7475c3dd72 | |||
| 421d22ed5c | |||
| d90c43b8b1 | |||
| 9c213b36b0 | |||
| 3b8d7c040b | |||
| 84c394e7b0 | |||
| d065dff695 | |||
| 7124e353db | |||
| 5ad07bf2d9 | |||
| 6c62c427ea | |||
| e262187f4c | |||
| e250e71019 | |||
| 717ee3339e | |||
| 3f4bd493d4 | |||
| 8671fe89db | |||
| 0f1018e6fb | |||
| 22c8c3459f | |||
| 56f4797a25 | |||
| c5404e0495 | |||
| eb9c19dfe0 | |||
| 03f99e18da | |||
| 6be33284a6 | |||
| 95401c688f | |||
| b06249d61c | |||
| f10bfe4616 | |||
| d296432908 | |||
| bab69c01c4 | |||
| abf5311664 | |||
| 6c120dcd2f | |||
| 7424e9674c | |||
| 589b6cf712 | |||
| 4c26bf06e9 | |||
| a87c0750cc | |||
| 1d6ce77a81 |
@@ -122,6 +122,141 @@
|
||||
"doc",
|
||||
"test"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "AZanellato",
|
||||
"name": "André Zanellato",
|
||||
"avatar_url": "https://avatars3.githubusercontent.com/u/30451287?v=4",
|
||||
"profile": "https://github.com/AZanellato",
|
||||
"contributions": [
|
||||
"code",
|
||||
"doc",
|
||||
"test"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "saghm",
|
||||
"name": "Saghm Rossi",
|
||||
"avatar_url": "https://avatars2.githubusercontent.com/u/5875560?v=4",
|
||||
"profile": "https://saghm.com",
|
||||
"contributions": [
|
||||
"code",
|
||||
"doc",
|
||||
"test"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "cappyzawa",
|
||||
"name": "Shu Kutsuzawa",
|
||||
"avatar_url": "https://avatars3.githubusercontent.com/u/12455284?v=4",
|
||||
"profile": "https://medium.com/@cappyzawa",
|
||||
"contributions": [
|
||||
"code",
|
||||
"doc",
|
||||
"test"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "iamsauravsharma",
|
||||
"name": "Saurav Sharma",
|
||||
"avatar_url": "https://avatars0.githubusercontent.com/u/38726015?v=4",
|
||||
"profile": "https://github.com/iamsauravsharma",
|
||||
"contributions": [
|
||||
"code",
|
||||
"doc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "andytom",
|
||||
"name": "Thomas O'Donnell",
|
||||
"avatar_url": "https://avatars1.githubusercontent.com/u/108836?v=4",
|
||||
"profile": "https://github.com/andytom",
|
||||
"contributions": [
|
||||
"code",
|
||||
"test"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "bbigras",
|
||||
"name": "Bruno Bigras",
|
||||
"avatar_url": "https://avatars1.githubusercontent.com/u/24027?v=4",
|
||||
"profile": "https://github.com/bbigras",
|
||||
"contributions": [
|
||||
"code",
|
||||
"review"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "wyze",
|
||||
"name": "Neil Kistner",
|
||||
"avatar_url": "https://avatars1.githubusercontent.com/u/186971?v=4",
|
||||
"profile": "https://neilkistner.com/",
|
||||
"contributions": [
|
||||
"code",
|
||||
"test",
|
||||
"review"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "qstrahl",
|
||||
"name": "Quinn Strahl",
|
||||
"avatar_url": "https://avatars3.githubusercontent.com/u/2235277?v=4",
|
||||
"profile": "http://ca.linkedin.com/in/qstrahl",
|
||||
"contributions": [
|
||||
"code",
|
||||
"test"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "tivervac",
|
||||
"name": "Titouan Vervack",
|
||||
"avatar_url": "https://avatars2.githubusercontent.com/u/3389524?v=4",
|
||||
"profile": "https://github.com/tivervac",
|
||||
"contributions": [
|
||||
"code",
|
||||
"test"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "oblitum",
|
||||
"name": "Francisco Lopes",
|
||||
"avatar_url": "https://avatars1.githubusercontent.com/u/1269815?v=4",
|
||||
"profile": "http://nosubstance.me",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "ahouts",
|
||||
"name": "Andrew Houts",
|
||||
"avatar_url": "https://avatars1.githubusercontent.com/u/16907671?v=4",
|
||||
"profile": "https://github.com/ahouts",
|
||||
"contributions": [
|
||||
"code",
|
||||
"doc",
|
||||
"test"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "nickwb",
|
||||
"name": "Nick Young",
|
||||
"avatar_url": "https://avatars2.githubusercontent.com/u/594211?v=4",
|
||||
"profile": "https://github.com/nickwb",
|
||||
"contributions": [
|
||||
"code",
|
||||
"doc",
|
||||
"test",
|
||||
"review"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "g2p",
|
||||
"name": "Gabriel de Perthuis",
|
||||
"avatar_url": "https://avatars1.githubusercontent.com/u/61678?v=4",
|
||||
"profile": "https://github.com/g2p",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
}
|
||||
],
|
||||
"contributorsPerLine": 7
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
---
|
||||
name: 🐛 Bug Report
|
||||
about: If something isn't working as expected 🤔.
|
||||
name: "\U0001F41B Bug Report"
|
||||
about: "If something isn't working as expected \U0001F914."
|
||||
title: ''
|
||||
labels: "\U0001F41B bug"
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
## Bug Report
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
---
|
||||
name: 🚀 Feature Request
|
||||
about: I have a suggestion (and may want to implement it 🙂)!
|
||||
name: "\U0001F680 Feature Request"
|
||||
about: "I have a suggestion (and may want to implement it \U0001F642)!"
|
||||
title: ''
|
||||
labels: "✨ enhancement"
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
## Feature Request
|
||||
<!-- Please keep in mind that we are in the beginning phases of Starship and it may take some time to implement features until we have our base set up. -->
|
||||
|
||||
#### Is your feature request related to a problem? Please describe.
|
||||
<!-- A clear and concise description of what the problem is. Ex. I have an issue when [...] -->
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
<!--- Provide a general summary of your changes in the Title above -->
|
||||
<!--- To help with semantic versioning the PR title should start with one of the conventional commit types. -->
|
||||
<!--- The conventional commit types for Semantic PR are: feat, fix, docs, style, refactor, perf, test, build, ci, chore, revert -->
|
||||
|
||||
#### Description
|
||||
<!--- Describe your changes in detail -->
|
||||
|
||||
@@ -0,0 +1,93 @@
|
||||
name: Continuous Integration
|
||||
on: [push, pull_request]
|
||||
jobs:
|
||||
# Run the `rustfmt` code formatter
|
||||
rustfmt:
|
||||
name: Rustfmt [Formatter]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: hecrj/setup-rust-action@master
|
||||
- uses: actions/checkout@master
|
||||
- name: Install rustfmt
|
||||
run: rustup component add rustfmt
|
||||
- name: Run rustfmt
|
||||
run: cargo fmt --all -- --check
|
||||
|
||||
# Run the `clippy` linting tool
|
||||
clippy:
|
||||
name: Clippy [Linter]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: hecrj/setup-rust-action@master
|
||||
- uses: actions/checkout@master
|
||||
- name: Install clippy
|
||||
run: rustup component add clippy
|
||||
- name: Run clippy
|
||||
run: cargo clippy --all-targets --all-features -- -D clippy::all
|
||||
|
||||
# Ensure that the project could be successfully compiled
|
||||
cargo_check:
|
||||
name: Compile
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: hecrj/setup-rust-action@master
|
||||
- uses: actions/checkout@master
|
||||
- run: cargo check --all
|
||||
|
||||
# Run tests on Linux, and macOS
|
||||
# On both Rust stable and Rust nightly
|
||||
test:
|
||||
name: Test Suite
|
||||
needs: [rustfmt, clippy, cargo_check]
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [ubuntu-latest, macOS-latest]
|
||||
rust: [stable, nightly]
|
||||
steps:
|
||||
# Install all the required dependencies for testing
|
||||
- uses: hecrj/setup-rust-action@master
|
||||
with:
|
||||
rust-version: ${{ matrix.rust }}
|
||||
|
||||
# Install Node.js at a fixed version
|
||||
- uses: actions/setup-node@master
|
||||
with:
|
||||
node-version: "12.0.0"
|
||||
|
||||
# Install Golang at a fixed version
|
||||
- uses: actions/setup-go@master
|
||||
with:
|
||||
go-version: "1.12.1"
|
||||
|
||||
# Install Ruby at a fixed version
|
||||
- uses: actions/setup-ruby@master
|
||||
with:
|
||||
ruby-version: "2.6.3"
|
||||
|
||||
# Install Python at a fixed version
|
||||
- uses: actions/setup-python@master
|
||||
with:
|
||||
python-version: "3.6.9"
|
||||
|
||||
# Run the ignored tests that expect the above setup
|
||||
- uses: actions/checkout@master
|
||||
- name: Run all tests
|
||||
run: cargo test -- -Z unstable-options --include-ignored
|
||||
|
||||
# Run the tests in the Docker image
|
||||
docker_test:
|
||||
name: Test in Docker
|
||||
needs: [rustfmt, clippy, cargo_check]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@master
|
||||
- name: Pull the pre-built Docker image
|
||||
run: docker pull starshipcommand/starship-test
|
||||
- name: Fix file permissions
|
||||
run: chmod -R a+w .
|
||||
- name: Build the Docker image
|
||||
run: docker build -f tests/Dockerfile --tag starshipcommand/starship-test --cache-from starshipcommand/starship-test .
|
||||
- name: Run tests in Docker
|
||||
run: docker run --rm -v $(pwd):/src/starship starshipcommand/starship-test
|
||||
@@ -13,6 +13,7 @@ Cargo.lock
|
||||
|
||||
# Intellij IDE configuration
|
||||
.idea/
|
||||
/*.iml
|
||||
|
||||
# Compiled files for documentation
|
||||
docs/node_modules
|
||||
|
||||
@@ -70,6 +70,8 @@ Unit tests are written using the built-in Rust testing library in the same file
|
||||
|
||||
Unit tests should be fully isolated, only testing a given function's expected output given a specific input, and should be reproducible on any machine. Unit tests should not expect the computer running them to be in any particular state. This includes having any applications pre-installed, having any environment variables set, etc.
|
||||
|
||||
The previous point should be emphasized: even seemingly innocuous ideas like "if we can see the directory, we can read it" or "nobody will have their home directory be a git repo" have bitten us in the past. Having even a single test fail can completely break installation on some platforms, so be careful with tests!
|
||||
|
||||
### Acceptance Testing
|
||||
|
||||
Acceptance tests are located in the [`tests/`](tests) directory and are also written using the built-in Rust testing library.
|
||||
|
||||
Generated
+105
-60
@@ -18,7 +18,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ansi_term"
|
||||
version = "0.12.0"
|
||||
version = "0.12.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@@ -96,7 +96,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "1.0.4"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
@@ -113,7 +113,7 @@ name = "c2-chacha"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"ppv-lite86 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
@@ -144,7 +144,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@@ -156,7 +156,7 @@ name = "cloudabi"
|
||||
version = "0.0.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -180,24 +180,24 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-deque"
|
||||
version = "0.6.3"
|
||||
version = "0.7.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"crossbeam-epoch 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"crossbeam-epoch 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-epoch"
|
||||
version = "0.7.1"
|
||||
version = "0.7.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"memoffset 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -214,7 +214,7 @@ version = "0.6.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -244,7 +244,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "env_logger"
|
||||
version = "0.6.1"
|
||||
version = "0.6.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@@ -279,23 +279,32 @@ name = "fuchsia-cprng"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "gethostname"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "getrandom"
|
||||
version = "0.1.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "git2"
|
||||
version = "0.9.2"
|
||||
version = "0.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libgit2-sys 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libgit2-sys 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"openssl-sys 0.9.46 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@@ -327,10 +336,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "lazy_static"
|
||||
version = "1.3.0"
|
||||
version = "1.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"spin 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"spin 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -345,7 +354,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "libgit2-sys"
|
||||
version = "0.8.2"
|
||||
version = "0.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"cc 1.0.36 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@@ -408,15 +417,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "memoffset"
|
||||
version = "0.2.1"
|
||||
version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nix"
|
||||
version = "0.14.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cc 1.0.36 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@@ -493,11 +505,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "pretty_env_logger"
|
||||
version = "0.3.0"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"env_logger 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"env_logger 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
@@ -588,23 +600,23 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "rayon"
|
||||
version = "1.1.0"
|
||||
version = "1.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"crossbeam-deque 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"crossbeam-deque 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"either 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rayon-core 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rayon-core 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rayon-core"
|
||||
version = "1.5.0"
|
||||
version = "1.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"crossbeam-deque 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"crossbeam-deque 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"crossbeam-queue 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
@@ -673,6 +685,14 @@ name = "rustc-demangle"
|
||||
version = "0.1.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "rustc_version"
|
||||
version = "0.2.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ryu"
|
||||
version = "1.0.0"
|
||||
@@ -685,12 +705,25 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "scopeguard"
|
||||
version = "0.3.3"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "semver"
|
||||
version = "0.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "semver-parser"
|
||||
version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.91"
|
||||
version = "1.0.98"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
@@ -700,7 +733,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"ryu 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.98 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -710,26 +743,28 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "spin"
|
||||
version = "0.5.0"
|
||||
version = "0.5.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "starship"
|
||||
version = "0.8.2"
|
||||
version = "0.16.0"
|
||||
dependencies = [
|
||||
"ansi_term 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"ansi_term 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"battery 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"dirs 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"git2 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gethostname 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"git2 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"path-slash 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"pretty_env_logger 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rayon 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"pretty_env_logger 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rayon 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"toml 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"toml 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"unicode-segmentation 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -803,7 +838,7 @@ name = "thread_local"
|
||||
version = "0.3.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -818,10 +853,10 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "toml"
|
||||
version = "0.5.1"
|
||||
version = "0.5.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.98 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -850,6 +885,11 @@ dependencies = [
|
||||
"smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-segmentation"
|
||||
version = "1.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-width"
|
||||
version = "0.1.5"
|
||||
@@ -938,7 +978,7 @@ dependencies = [
|
||||
[metadata]
|
||||
"checksum aho-corasick 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e6f484ae0c99fec2e858eb6134949117399f222608d84cadb3f58c1f97c2364c"
|
||||
"checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b"
|
||||
"checksum ansi_term 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "eaa72766c3585a1f812a3387a7e2c6cab780f899c2f43ff6ea06c8d071fcbb36"
|
||||
"checksum ansi_term 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2"
|
||||
"checksum argon2rs 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "3f67b0b6a86dae6e67ff4ca2b6201396074996379fba2b92ff649126f37cb392"
|
||||
"checksum arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "92c7fb76bc8826a8b33b4ee5bb07a247a81e76764ab4d55e8f73e3a4d8808c71"
|
||||
"checksum atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "9a7d5b8723950951411ee34d271d99dddcc2035a16ab25310ea2c8cfd4369652"
|
||||
@@ -946,7 +986,7 @@ dependencies = [
|
||||
"checksum backtrace 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "f106c02a3604afcdc0df5d36cc47b44b55917dbaf3d808f71c163a0ddba64637"
|
||||
"checksum backtrace-sys 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)" = "797c830ac25ccc92a7f8a7b9862bde440715531514594a6154e3d4a54dd769b6"
|
||||
"checksum battery 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6d6fe5630049e900227cd89afce4c1204b88ec8e61a2581bb96fcce26f047b"
|
||||
"checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12"
|
||||
"checksum bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3d155346769a6855b86399e9bc3814ab343cd3d62c7e985113d46a0ec3c281fd"
|
||||
"checksum blake2-rfc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)" = "5d6d530bdd2d52966a6d03b7a964add7ae1a288d25214066fd4b600f0f796400"
|
||||
"checksum c2-chacha 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7d64d04786e0f528460fc884753cf8dddcc466be308f6026f8e355c41a0e4101"
|
||||
"checksum cc 1.0.36 (registry+https://github.com/rust-lang/crates.io-index)" = "a0c56216487bb80eec9c4516337b2588a4f2a2290d72a1416d930e4dcdb0c90d"
|
||||
@@ -957,33 +997,34 @@ dependencies = [
|
||||
"checksum constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8ff012e225ce166d4422e0e78419d901719760f62ae2b7969ca6b564d1b54a9e"
|
||||
"checksum core-foundation 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "25b9e03f145fd4f2bf705e07b900cd41fc636598fe5dc452fd0db1441c3f496d"
|
||||
"checksum core-foundation-sys 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e7ca8a5221364ef15ce201e8ed2f609fc312682a8f4e0e3d4aa5879764e0fa3b"
|
||||
"checksum crossbeam-deque 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "05e44b8cf3e1a625844d1750e1f7820da46044ff6d28f4d43e455ba3e5bb2c13"
|
||||
"checksum crossbeam-epoch 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "04c9e3102cc2d69cd681412141b390abd55a362afc1540965dad0ad4d34280b4"
|
||||
"checksum crossbeam-deque 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b18cd2e169ad86297e6bc0ad9aa679aee9daa4f19e8163860faf7c164e4f5a71"
|
||||
"checksum crossbeam-epoch 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "fedcd6772e37f3da2a9af9bf12ebe046c0dfe657992377b4df982a2b54cd37a9"
|
||||
"checksum crossbeam-queue 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7c979cd6cfe72335896575c6b5688da489e420d36a27a0b9eb0c73db574b4a4b"
|
||||
"checksum crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "f8306fcef4a7b563b76b7dd949ca48f52bc1141aa067d2ea09565f3e2652aa5c"
|
||||
"checksum dirs 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "13aea89a5c93364a98e9b37b2fa237effbb694d5cfe01c5b70941f7eb087d5e3"
|
||||
"checksum dirs-sys 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "afa0b23de8fd801745c471deffa6e12d248f962c9fd4b4c33787b055599bde7b"
|
||||
"checksum either 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "5527cfe0d098f36e3f8839852688e63c8fff1c90b2b405aef730615f9a7bcf7b"
|
||||
"checksum env_logger 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b61fa891024a945da30a9581546e8cfaf5602c7b3f4c137a2805cf388f92075a"
|
||||
"checksum env_logger 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "aafcde04e90a5226a6443b7aabdb016ba2f8307c847d524724bd9b346dd1a2d3"
|
||||
"checksum failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "795bd83d3abeb9220f257e597aa0080a508b27533824adf336529648f6abf7e2"
|
||||
"checksum failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ea1063915fd7ef4309e222a5a07cf9c319fb9c7836b1f89b85458672dbb127e1"
|
||||
"checksum fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba"
|
||||
"checksum gethostname 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d4ab273ca2a31eb6ca40b15837ccf1aa59a43c5db69ac10c542be342fae2e01d"
|
||||
"checksum getrandom 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "e65cce4e5084b14874c4e7097f38cab54f47ee554f9194673456ea379dcc4c55"
|
||||
"checksum git2 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8cb400360e8a4d61b10e648285bbfa919bbf9519d0d5d5720354456f44349226"
|
||||
"checksum git2 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "327d698f86a7ebdfeb86a4238ccdb004828939d3a3555b6ead679541d14e36c0"
|
||||
"checksum humantime 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3ca7e5f2e110db35f93b837c81797f3714500b81d517bf20c431b16d3ca4f114"
|
||||
"checksum idna 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "02e2673c30ee86b5b96a9cb52ad15718aa1f966f5ab9ad54a8b95d5ca33120a9"
|
||||
"checksum itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "501266b7edd0174f8530248f87f99c88fbe60ca4ef3dd486835b8d8d53136f7f"
|
||||
"checksum lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bc5729f27f159ddd61f4df6228e827e86643d4d3e7c32183cb30a1c08f604a14"
|
||||
"checksum lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
||||
"checksum lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b294d6fa9ee409a054354afc4352b0b9ef7ca222c69b8812cbea9e7d2bf3783f"
|
||||
"checksum libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)" = "6281b86796ba5e4366000be6e9e18bf35580adf9e63fbe2294aadb587613a319"
|
||||
"checksum libgit2-sys 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4c179ed6d19cd3a051e68c177fbbc214e79ac4724fac3a850ec9f3d3eb8a5578"
|
||||
"checksum libgit2-sys 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8c2078aec6f4b16d1b89f6a72e4f6eb1e75ffa85312023291e89c6d3087bc8fb"
|
||||
"checksum libssh2-sys 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "126a1f4078368b163bfdee65fbab072af08a1b374a5551b21e87ade27b1fbf9d"
|
||||
"checksum libz-sys 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)" = "2eb5e43362e38e2bca2fd5f5134c4d4564a23a5c28e9b95411652021a8675ebe"
|
||||
"checksum log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7"
|
||||
"checksum mach 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "86dd2487cdfea56def77b88438a2c915fb45113c5319bfe7e14306ca4cd0b0e1"
|
||||
"checksum matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08"
|
||||
"checksum memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2efc7bc57c883d4a4d6e3246905283d8dae951bb3bd32f49d6ef297f546e1c39"
|
||||
"checksum memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0f9dc261e2b62d7a622bf416ea3c5245cdd5d9a7fcc428c0d06804dfce1775b3"
|
||||
"checksum memoffset 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ce6075db033bbbb7ee5a0bbd3a3186bbae616f57fb001c485c7ff77955f8177f"
|
||||
"checksum nix 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0d10caafde29a846a82ae0af70414e4643e072993441033b2c93217957e2f867"
|
||||
"checksum nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9667ddcc6cc8a43afc9b7917599d7216aa09c463919ea32c59ed6cac8bc945"
|
||||
"checksum num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)" = "e83d528d2677f0518c570baf2b7abdcf0cd2d248860b68507bdcb3e91d4c0cea"
|
||||
@@ -996,7 +1037,7 @@ dependencies = [
|
||||
"checksum percent-encoding 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ba4f28a6faf4ffea762ba8f4baef48c61a6db348647c73095034041fc79dd954"
|
||||
"checksum pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)" = "676e8eb2b1b4c9043511a9b7bea0915320d7e502b0a079fb03f9635a5252b18c"
|
||||
"checksum ppv-lite86 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e3cbf9f658cdb5000fcf6f362b8ea2ba154b9f146a61c7a20d647034c6b6561b"
|
||||
"checksum pretty_env_logger 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "df8b3f4e0475def7d9c2e5de8e5a1306949849761e107b360d03e98eafaffd61"
|
||||
"checksum pretty_env_logger 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "717ee476b1690853d222af4634056d830b5197ffd747726a9a1eee6da9f49074"
|
||||
"checksum proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)" = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759"
|
||||
"checksum quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0"
|
||||
"checksum quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)" = "faf4799c5d274f3868a4aae320a0a182cbd2baee377b378f080e16a23e9d80db"
|
||||
@@ -1007,8 +1048,8 @@ dependencies = [
|
||||
"checksum rand_core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "615e683324e75af5d43d8f7a39ffe3ee4a9dc42c5c701167a71dc59c3a493aca"
|
||||
"checksum rand_hc 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c"
|
||||
"checksum rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7b75f676a1e053fc562eafbb47838d67c84801e38fc1ba459e8f180deabd5071"
|
||||
"checksum rayon 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a4b0186e22767d5b9738a05eab7c6ac90b15db17e5b5f9bd87976dd7d89a10a4"
|
||||
"checksum rayon-core 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ebbe0df8435ac0c397d467b6cad6d25543d06e8a019ef3f6af3c384597515bd2"
|
||||
"checksum rayon 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "83a27732a533a1be0a0035a111fe76db89ad312f6f0347004c220c57f209a123"
|
||||
"checksum rayon-core 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "98dcf634205083b17d0861252431eb2acbfb698ab7478a2d20de07954f47ec7b"
|
||||
"checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2"
|
||||
"checksum redox_syscall 0.1.54 (registry+https://github.com/rust-lang/crates.io-index)" = "12229c14a0f65c4f1cb046a3b52047cdd9da1f4b30f8a39c5063c8bae515e252"
|
||||
"checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76"
|
||||
@@ -1017,13 +1058,16 @@ dependencies = [
|
||||
"checksum regex-syntax 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)" = "dcfd8681eebe297b81d98498869d4aae052137651ad7b96822f09ceb690d0a96"
|
||||
"checksum remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3488ba1b9a2084d38645c4c08276a1752dcbf2c7130d74f1569681ad5d2799c5"
|
||||
"checksum rustc-demangle 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "ccc78bfd5acd7bf3e89cffcf899e5cb1a52d6fafa8dec2739ad70c9577a57288"
|
||||
"checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a"
|
||||
"checksum ryu 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c92464b447c0ee8c4fb3824ecc8383b81717b9f1e74ba2e72540aef7b9f82997"
|
||||
"checksum scoped_threadpool 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "1d51f5df5af43ab3f1360b429fa5e0152ac5ce8c0bd6485cae490332e96846a8"
|
||||
"checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27"
|
||||
"checksum serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)" = "a72e9b96fa45ce22a4bc23da3858dfccfd60acd28a25bcd328a98fdd6bea43fd"
|
||||
"checksum scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b42e15e59b18a828bbf5c58ea01debb36b9b096346de35d941dcb89009f24a0d"
|
||||
"checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403"
|
||||
"checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
|
||||
"checksum serde 1.0.98 (registry+https://github.com/rust-lang/crates.io-index)" = "7fe5626ac617da2f2d9c48af5515a21d5a480dbd151e01bb1c355e26a3e68113"
|
||||
"checksum serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)" = "051c49229f282f7c6f3813f8286cc1e3323e8051823fce42c7ea80fe13521704"
|
||||
"checksum smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "ab606a9c5e214920bb66c458cd7be8ef094f813f20fe77a54cc7dbfff220d4b7"
|
||||
"checksum spin 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "44363f6f51401c34e7be73db0db371c04705d35efbe9f7d6082e03a921a32c55"
|
||||
"checksum spin 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d"
|
||||
"checksum strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
|
||||
"checksum syn 0.15.34 (registry+https://github.com/rust-lang/crates.io-index)" = "a1393e4a97a19c01e900df2aec855a29f71cf02c402e2f443b8d2747c25c5dbe"
|
||||
"checksum synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "73687139bf99285483c96ac0add482c3776528beac1d97d444f6e91f203a2015"
|
||||
@@ -1033,11 +1077,12 @@ dependencies = [
|
||||
"checksum textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060"
|
||||
"checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b"
|
||||
"checksum time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f"
|
||||
"checksum toml 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b8c96d7873fa7ef8bdeb3a9cda3ac48389b4154f32b9803b4bc26220b677b039"
|
||||
"checksum toml 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c7aabe75941d914b72bf3e5d3932ed92ce0664d49d8432305a8b547c37227724"
|
||||
"checksum typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "612d636f949607bdf9b123b4a6f6d966dedf3ff669f7f045890d3a4a73948169"
|
||||
"checksum ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "535c204ee4d8434478593480b8f86ab45ec9aae0e83c568ca81abf0fd0e88f86"
|
||||
"checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5"
|
||||
"checksum unicode-normalization 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "141339a08b982d942be2ca06ff8b076563cbe223d1befd5450716790d44e2426"
|
||||
"checksum unicode-segmentation 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1967f4cdfc355b37fd76d2a954fb2ed3871034eb4f26d60537d88795cfc332a9"
|
||||
"checksum unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "882386231c45df4700b275c7ff55b6f3698780a650026380e72dabe76fa46526"
|
||||
"checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc"
|
||||
"checksum uom 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)" = "347fe3ff20637a62ab9749a5c90d167302bcbdab77ec961dda7f62a5ca6d368a"
|
||||
|
||||
+17
-9
@@ -1,10 +1,11 @@
|
||||
[package]
|
||||
name = "starship"
|
||||
version = "0.8.2"
|
||||
version = "0.16.0"
|
||||
edition = "2018"
|
||||
authors = ["Matan Kushner <hello@matchai.me>"]
|
||||
repository = "https://github.com/starship/starship"
|
||||
homepage = "https://starship.rs"
|
||||
documentation = "https://starship.rs/guide/"
|
||||
repository = "https://github.com/starship/starship"
|
||||
readme = "README.md"
|
||||
license = "ISC"
|
||||
keywords = ["prompt", "shell", "bash", "fish", "zsh"]
|
||||
@@ -20,19 +21,26 @@ is-it-maintained-issue-resolution = { repository = "starship/starship" }
|
||||
is-it-maintained-open-issues = { repository = "starship/starship" }
|
||||
maintenance = { status = "actively-developed" }
|
||||
|
||||
[features]
|
||||
default = ["battery"]
|
||||
|
||||
[dependencies]
|
||||
clap = "2.33.0"
|
||||
ansi_term = "0.12.0"
|
||||
ansi_term = "0.12.1"
|
||||
dirs = "2.0.2"
|
||||
git2 = "0.9.2"
|
||||
toml = "0.5.1"
|
||||
git2 = "0.10.0"
|
||||
toml = "0.5.3"
|
||||
serde_json = "1.0.40"
|
||||
rayon = "1.1.0"
|
||||
pretty_env_logger = "0.3.0"
|
||||
rayon = "1.2.0"
|
||||
pretty_env_logger = "0.3.1"
|
||||
log = "0.4.8"
|
||||
battery = "0.7.4"
|
||||
lazy_static = "1.3.0"
|
||||
# battery is optional (on by default) because the crate doesn't currently build for Termux
|
||||
# see: https://github.com/svartalf/rust-battery/issues/33
|
||||
battery = { version = "0.7.4", optional = true }
|
||||
lazy_static = "1.4.0"
|
||||
path-slash = "0.1.1"
|
||||
unicode-segmentation = "1.3.0"
|
||||
gethostname = "0.2.0"
|
||||
|
||||
[dev-dependencies]
|
||||
tempfile = "3.1.0"
|
||||
|
||||
@@ -1,39 +1,75 @@
|
||||
<p align="center">
|
||||
<br>
|
||||
<img width="400" src="https://raw.githubusercontent.com/starship/starship/master/media/logo.png" alt="Starship – Cross-shell prompt">
|
||||
<p align="center">
|
||||
<a href="https://crates.io/crates/starship"><img src="https://badgen.net/crates/v/starship" alt="Crates.io version"></a>
|
||||
<a href="https://dev.azure.com/starship-control/starship/_build"><img src="https://badgen.net/azure-pipelines/starship-control/starship/Starship%20Test%20Suite" alt="Azure Pipelines Build Status"></a>
|
||||
<a href="#contributors"><img src="https://badgen.net/badge/all%20contributors/10/orange" alt="All Contributors"></a>
|
||||
<a href="https://discord.gg/8Jzqu3T"><img src="https://badgen.net/badge/chat/on%20discord/7289da" alt="Chat on Discord"></a>
|
||||
</p>
|
||||
<br />
|
||||
<img
|
||||
width="400"
|
||||
src="https://raw.githubusercontent.com/starship/starship/master/media/logo.png"
|
||||
alt="Starship – Cross-shell prompt"
|
||||
/>
|
||||
</p>
|
||||
<p align="center">
|
||||
<a href="https://crates.io/crates/starship">
|
||||
<img src="https://badgen.net/crates/v/starship" alt="Crates.io version" />
|
||||
</a>
|
||||
<a href="https://dev.azure.com/starship-control/starship/_build">
|
||||
<img
|
||||
src="https://badgen.net/azure-pipelines/starship-control/starship/Starship%20Test%20Suite"
|
||||
alt="Azure Pipelines Build Status"
|
||||
/>
|
||||
</a>
|
||||
<a href="https://repology.org/project/starship/versions">
|
||||
<img src="https://repology.org/badge/tiny-repos/starship.svg" alt="Packaging status">
|
||||
</a><br>
|
||||
<a href="#contributors">
|
||||
<img
|
||||
src="https://badgen.net/badge/all%20contributors/20/orange"
|
||||
alt="All Contributors"
|
||||
/>
|
||||
</a>
|
||||
<a href="https://discord.gg/8Jzqu3T">
|
||||
<img
|
||||
src="https://badgen.net/badge/chat/on%20discord/7289da"
|
||||
alt="Chat on Discord"
|
||||
/>
|
||||
</a>
|
||||
</p>
|
||||
<h4 align="center">
|
||||
<br>
|
||||
<a href="https://starship.rs">Website</a> ·
|
||||
<a href="#-installation">Installation</a> ·
|
||||
<a href="https://starship.rs/config/">Configuration</a>
|
||||
<br />
|
||||
<a href="https://starship.rs">Website</a>
|
||||
·
|
||||
<a href="#-installation">Installation</a>
|
||||
·
|
||||
<a href="https://starship.rs/config/">Configuration</a>
|
||||
</h4>
|
||||
|
||||
<h1></h1>
|
||||
|
||||
<p align="center">
|
||||
Starship is the minimal, blazing fast, and extremely customizable prompt for any shell!<br>
|
||||
The prompt shows information you need while you're working, while staying sleek and out of the way.
|
||||
<p>
|
||||
|
||||
<p align="center">
|
||||
<img alt="Starship with Hyper and One Dark" src="https://raw.githubusercontent.com/starship/starship/master/media/demo.gif">
|
||||
<br>
|
||||
<img alt="Starship with iTerm2 and the Snazzy theme" src="https://raw.githubusercontent.com/starship/starship/master/media/demo.gif" width="80%">
|
||||
<br>
|
||||
<br>
|
||||
</p>
|
||||
|
||||
## 🍬 Features
|
||||
|
||||
- Prompt character turns red if the last command exits with non-zero code.
|
||||
- Current username if not the same as the logged-in user.
|
||||
- Current Node.js version(`⬢`).
|
||||
- Current Rust version (`🦀`).
|
||||
- Current Python version (`🐍`).
|
||||
- Current Go version (`🐹`).
|
||||
- Package version of package in current directory (`📦`).
|
||||
- Current battery level and status.
|
||||
- Prompt character turns red if the last command exits with non-zero code
|
||||
- Current username if not the same as the logged-in user
|
||||
- Current Node.js version(`⬢`)
|
||||
- Current Rust version (`🦀`)
|
||||
- Current Ruby version (`💎`)
|
||||
- Current Python version (`🐍`)
|
||||
- Current Go version (`🐹`)
|
||||
- Nix-shell environment detection
|
||||
- Current version of package in current directory (`📦`)
|
||||
- npm (Node.js)
|
||||
- cargo (Rust)
|
||||
- poetry (Python)
|
||||
- Current battery level and status
|
||||
- Current Git branch and rich repo status:
|
||||
- `=` — conflicting changes
|
||||
- `⇡` — ahead of remote branch
|
||||
@@ -45,8 +81,8 @@ The prompt shows information you need while you're working, while staying sleek
|
||||
- `+` — added files
|
||||
- `»` — renamed files
|
||||
- `✘` — deleted files
|
||||
- Execution time of the last command if it exceeds the set threshold.
|
||||
- Indicator for jobs in the background (`✦`).
|
||||
- Execution time of the last command if it exceeds the set threshold
|
||||
- Indicator for jobs in the background (`✦`)
|
||||
|
||||
## 🚀 Installation
|
||||
|
||||
@@ -67,21 +103,41 @@ The prompt shows information you need while you're working, while staying sleek
|
||||
```
|
||||
|
||||
#### Rust (v1.33 or higher)
|
||||
|
||||
|
||||
```sh
|
||||
$ cargo install starship
|
||||
```
|
||||
|
||||
1. Add the init script to your shell's config file:
|
||||
#### Arch Linux (AUR)
|
||||
|
||||
#### Bash / Zsh
|
||||
|
||||
Add the following to the end of `~/.bashrc` or `~/.zshrc`:
|
||||
Starship is available on the AUR under the name `starship`. Install it with `yay` or your favorite AUR helper.
|
||||
|
||||
```sh
|
||||
# ~/.bashrc or ~/.zshrc
|
||||
$ yay -S starship
|
||||
```
|
||||
|
||||
eval "$(starship init $0)"
|
||||
#### Nix (unstable)
|
||||
|
||||
```sh
|
||||
$ nix-env --install starship
|
||||
```
|
||||
|
||||
#### Termux
|
||||
|
||||
```sh
|
||||
$ pkg install starship
|
||||
```
|
||||
|
||||
1. Add the init script to your shell's config file:
|
||||
|
||||
#### Bash
|
||||
|
||||
Add the following to the end of `~/.bashrc`:
|
||||
|
||||
```sh
|
||||
# ~/.bashrc
|
||||
|
||||
eval "$(starship init bash)"
|
||||
```
|
||||
|
||||
#### Fish
|
||||
@@ -94,13 +150,23 @@ The prompt shows information you need while you're working, while staying sleek
|
||||
eval (starship init fish)
|
||||
```
|
||||
|
||||
#### Zsh
|
||||
|
||||
Add the following to the end of `~/.zshrc`:
|
||||
|
||||
```sh
|
||||
# ~/.zshrc
|
||||
|
||||
eval "$(starship init zsh)"
|
||||
```
|
||||
|
||||
## 🔧 Configuration
|
||||
|
||||
For details on how to configure Starship, check out our [documentation](https://starship.rs/config/).
|
||||
|
||||
## 🤝 Contributing
|
||||
|
||||
We are always looking for contributors of **all skill levels**! If you're looking to ease your way into the project, try out a [good first issue](https://github.com/starship/starship/labels/good%20first%20issue).
|
||||
We are always looking for contributors of **all skill levels**! If you're looking to ease your way into the project, try out a [good first issue](https://github.com/starship/starship/labels/🌱%20good%20first%20issue).
|
||||
|
||||
### High Priority Needs
|
||||
|
||||
@@ -111,7 +177,7 @@ We are always looking for contributors of **all skill levels**! If you're lookin
|
||||
- 👩💻 **Rust Developer**
|
||||
- There is _a lot_ of low-hanging fruit when it comes to writing idiomatic Rust, designing effective Rust architecture, performance optimizations, cross-platform build optimizations, and more! I ([@matchai](https://github.com/matchai)) am a beginner to Rust. Come point us in the right direction!
|
||||
|
||||
If you are interested in helping contribute to starship, please take a look at our [Contributing Guide](./CONTRIBUTING.md). Also, feel free to drop into our [Discord server](https://discord.gg/8Jzqu3T) and say hi. 👋
|
||||
If you are interested in helping contribute to starship, please take a look at our [Contributing Guide](https://github.com/starship/starship/blob/master/CONTRIBUTING.md). Also, feel free to drop into our [Discord server](https://discord.gg/8Jzqu3T) and say hi. 👋
|
||||
|
||||
### Contributors
|
||||
|
||||
@@ -133,6 +199,23 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
|
||||
<td align="center"><a href="https://github.com/chipbuster"><img src="https://avatars2.githubusercontent.com/u/4605384?v=4" width="100px;" alt="Kevin Song"/><br /><sub><b>Kevin Song</b></sub></a><br /><a href="https://github.com/starship/starship/issues?q=author%3Achipbuster" title="Bug reports">🐛</a> <a href="https://github.com/starship/starship/commits?author=chipbuster" title="Code">💻</a> <a href="https://github.com/starship/starship/commits?author=chipbuster" title="Documentation">📖</a> <a href="https://github.com/starship/starship/commits?author=chipbuster" title="Tests">⚠️</a></td>
|
||||
<td align="center"><a href="https://andrewda.me"><img src="https://avatars1.githubusercontent.com/u/10191084?v=4" width="100px;" alt="Andrew Dassonville"/><br /><sub><b>Andrew Dassonville</b></sub></a><br /><a href="https://github.com/starship/starship/issues?q=author%3Aandrewda" title="Bug reports">🐛</a> <a href="https://github.com/starship/starship/commits?author=andrewda" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/MaT1g3R"><img src="https://avatars1.githubusercontent.com/u/15258494?v=4" width="100px;" alt="MaT1g3R"/><br /><sub><b>MaT1g3R</b></sub></a><br /><a href="https://github.com/starship/starship/commits?author=MaT1g3R" title="Code">💻</a> <a href="https://github.com/starship/starship/commits?author=MaT1g3R" title="Documentation">📖</a> <a href="https://github.com/starship/starship/commits?author=MaT1g3R" title="Tests">⚠️</a></td>
|
||||
<td align="center"><a href="https://github.com/AZanellato"><img src="https://avatars3.githubusercontent.com/u/30451287?v=4" width="100px;" alt="André Zanellato"/><br /><sub><b>André Zanellato</b></sub></a><br /><a href="https://github.com/starship/starship/commits?author=AZanellato" title="Code">💻</a> <a href="https://github.com/starship/starship/commits?author=AZanellato" title="Documentation">📖</a> <a href="https://github.com/starship/starship/commits?author=AZanellato" title="Tests">⚠️</a></td>
|
||||
<td align="center"><a href="https://saghm.com"><img src="https://avatars2.githubusercontent.com/u/5875560?v=4" width="100px;" alt="Saghm Rossi"/><br /><sub><b>Saghm Rossi</b></sub></a><br /><a href="https://github.com/starship/starship/commits?author=saghm" title="Code">💻</a> <a href="https://github.com/starship/starship/commits?author=saghm" title="Documentation">📖</a> <a href="https://github.com/starship/starship/commits?author=saghm" title="Tests">⚠️</a></td>
|
||||
<td align="center"><a href="https://medium.com/@cappyzawa"><img src="https://avatars3.githubusercontent.com/u/12455284?v=4" width="100px;" alt="Shu Kutsuzawa"/><br /><sub><b>Shu Kutsuzawa</b></sub></a><br /><a href="https://github.com/starship/starship/commits?author=cappyzawa" title="Code">💻</a> <a href="https://github.com/starship/starship/commits?author=cappyzawa" title="Documentation">📖</a> <a href="https://github.com/starship/starship/commits?author=cappyzawa" title="Tests">⚠️</a></td>
|
||||
<td align="center"><a href="https://github.com/iamsauravsharma"><img src="https://avatars0.githubusercontent.com/u/38726015?v=4" width="100px;" alt="Saurav Sharma"/><br /><sub><b>Saurav Sharma</b></sub></a><br /><a href="https://github.com/starship/starship/commits?author=iamsauravsharma" title="Code">💻</a> <a href="https://github.com/starship/starship/commits?author=iamsauravsharma" title="Documentation">📖</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://github.com/andytom"><img src="https://avatars1.githubusercontent.com/u/108836?v=4" width="100px;" alt="Thomas O'Donnell"/><br /><sub><b>Thomas O'Donnell</b></sub></a><br /><a href="https://github.com/starship/starship/commits?author=andytom" title="Code">💻</a> <a href="https://github.com/starship/starship/commits?author=andytom" title="Tests">⚠️</a></td>
|
||||
<td align="center"><a href="https://github.com/bbigras"><img src="https://avatars1.githubusercontent.com/u/24027?v=4" width="100px;" alt="Bruno Bigras"/><br /><sub><b>Bruno Bigras</b></sub></a><br /><a href="https://github.com/starship/starship/commits?author=bbigras" title="Code">💻</a> <a href="#review-bbigras" title="Reviewed Pull Requests">👀</a></td>
|
||||
<td align="center"><a href="https://neilkistner.com/"><img src="https://avatars1.githubusercontent.com/u/186971?v=4" width="100px;" alt="Neil Kistner"/><br /><sub><b>Neil Kistner</b></sub></a><br /><a href="https://github.com/starship/starship/commits?author=wyze" title="Code">💻</a> <a href="https://github.com/starship/starship/commits?author=wyze" title="Tests">⚠️</a> <a href="#review-wyze" title="Reviewed Pull Requests">👀</a></td>
|
||||
<td align="center"><a href="http://ca.linkedin.com/in/qstrahl"><img src="https://avatars3.githubusercontent.com/u/2235277?v=4" width="100px;" alt="Quinn Strahl"/><br /><sub><b>Quinn Strahl</b></sub></a><br /><a href="https://github.com/starship/starship/commits?author=qstrahl" title="Code">💻</a> <a href="https://github.com/starship/starship/commits?author=qstrahl" title="Tests">⚠️</a></td>
|
||||
<td align="center"><a href="https://github.com/tivervac"><img src="https://avatars2.githubusercontent.com/u/3389524?v=4" width="100px;" alt="Titouan Vervack"/><br /><sub><b>Titouan Vervack</b></sub></a><br /><a href="https://github.com/starship/starship/commits?author=tivervac" title="Code">💻</a> <a href="https://github.com/starship/starship/commits?author=tivervac" title="Tests">⚠️</a></td>
|
||||
<td align="center"><a href="http://nosubstance.me"><img src="https://avatars1.githubusercontent.com/u/1269815?v=4" width="100px;" alt="Francisco Lopes"/><br /><sub><b>Francisco Lopes</b></sub></a><br /><a href="https://github.com/starship/starship/commits?author=oblitum" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/ahouts"><img src="https://avatars1.githubusercontent.com/u/16907671?v=4" width="100px;" alt="Andrew Houts"/><br /><sub><b>Andrew Houts</b></sub></a><br /><a href="https://github.com/starship/starship/commits?author=ahouts" title="Code">💻</a> <a href="https://github.com/starship/starship/commits?author=ahouts" title="Documentation">📖</a> <a href="https://github.com/starship/starship/commits?author=ahouts" title="Tests">⚠️</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://github.com/nickwb"><img src="https://avatars2.githubusercontent.com/u/594211?v=4" width="100px;" alt="Nick Young"/><br /><sub><b>Nick Young</b></sub></a><br /><a href="https://github.com/starship/starship/commits?author=nickwb" title="Code">💻</a> <a href="https://github.com/starship/starship/commits?author=nickwb" title="Documentation">📖</a> <a href="https://github.com/starship/starship/commits?author=nickwb" title="Tests">⚠️</a> <a href="#review-nickwb" title="Reviewed Pull Requests">👀</a></td>
|
||||
<td align="center"><a href="https://github.com/g2p"><img src="https://avatars1.githubusercontent.com/u/61678?v=4" width="100px;" alt="Gabriel de Perthuis"/><br /><sub><b>Gabriel de Perthuis</b></sub></a><br /><a href="https://github.com/starship/starship/commits?author=g2p" title="Code">💻</a></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
@@ -140,6 +223,16 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
|
||||
|
||||
This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome!
|
||||
|
||||
## 💭 Inspired By
|
||||
|
||||
Please check out these previous works that helped inspire the creation of starship. 🙏
|
||||
|
||||
- **[denysdovhan/spaceship-prompt](https://github.com/denysdovhan/spaceship-prompt)** - A ZSH prompt for astronauts.
|
||||
|
||||
- **[denysdovhan/robbyrussell-node](https://github.com/denysdovhan/robbyrussell-node)** - Cross-shell robbyrussell theme written in JavaScript.
|
||||
|
||||
- **[reujab/silver](https://github.com/reujab/silver)** - A cross-shell customizable powerline-like prompt with icons.
|
||||
|
||||
<p align="center">
|
||||
<br>
|
||||
<img width="100" src="media/icon.png" alt="Starship rocket icon">
|
||||
@@ -148,4 +241,4 @@ This project follows the [all-contributors](https://github.com/all-contributors/
|
||||
## 📝 License
|
||||
|
||||
Copyright © 2019-present, [Starship Contributors](https://github.com/starship/starship/graphs/contributors).<br>
|
||||
This project is [ISC](./LICENSE) licensed.
|
||||
This project is [ISC](https://github.com/starship/starship/blob/master/LICENSE) licensed.
|
||||
|
||||
+2
-56
@@ -1,59 +1,10 @@
|
||||
trigger:
|
||||
branches:
|
||||
include: ["*"]
|
||||
tags:
|
||||
include: ["*"]
|
||||
|
||||
stages:
|
||||
- stage: Checks
|
||||
jobs:
|
||||
# Check formatting
|
||||
- template: ci/rustfmt.yml
|
||||
parameters:
|
||||
name: rustfmt
|
||||
displayName: Check formatting
|
||||
|
||||
# Run linter
|
||||
- template: ci/cargo-clippy.yml
|
||||
parameters:
|
||||
name: cargo_clippy
|
||||
displayName: Run linter
|
||||
|
||||
# Cargo check
|
||||
- template: ci/cargo-check.yml
|
||||
parameters:
|
||||
name: cargo_check
|
||||
displayName: Cargo check
|
||||
|
||||
- stage: Test
|
||||
dependsOn: Checks
|
||||
jobs:
|
||||
# Test stable
|
||||
- template: ci/test.yml
|
||||
parameters:
|
||||
name: cargo_test_stable
|
||||
displayName: Cargo test
|
||||
cross: true # Test on Windows and macOS
|
||||
|
||||
# Test nightly
|
||||
- template: ci/test.yml
|
||||
parameters:
|
||||
name: cargo_test_nightly
|
||||
displayName: Cargo test
|
||||
rust_version: nightly
|
||||
|
||||
# Test docker
|
||||
# Runs integration tests as a starship developer would run them locally
|
||||
- template: ci/test-docker.yml
|
||||
parameters:
|
||||
name: test_docker
|
||||
displayName: Docker test
|
||||
|
||||
- stage: Release
|
||||
dependsOn:
|
||||
- Checks
|
||||
- Test
|
||||
condition: and(succeeded(), startsWith(variables['Build.SourceBranch'], 'refs/tags/v'))
|
||||
condition: startsWith(variables['Build.SourceBranch'], 'refs/tags/v')
|
||||
jobs:
|
||||
# Release binary on GitHub
|
||||
- template: ci/github-release.yml
|
||||
@@ -67,6 +18,7 @@ stages:
|
||||
!.*
|
||||
targets:
|
||||
- x86_64-unknown-linux-gnu
|
||||
- x86_64-unknown-linux-musl
|
||||
# Windows support temporarily disabled
|
||||
# - x86_64-pc-windows-gnu
|
||||
# - x86_64-pc-windows-msvc
|
||||
@@ -81,9 +33,3 @@ stages:
|
||||
parameters:
|
||||
name: cargo_publish
|
||||
displayName: Publish to Crates.io
|
||||
|
||||
# Open a PR on Homebrew/homebrew-core with an update to the starship formula
|
||||
- template: ci/bump-brew-formula.yml
|
||||
parameters:
|
||||
name: bump_brew_formula
|
||||
displayName: Bump the Homebrew formula
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
jobs:
|
||||
- job: ${{ parameters.name }}
|
||||
displayName: ${{ parameters.displayName }}
|
||||
pool:
|
||||
vmImage: macOS-10.13
|
||||
steps:
|
||||
- script: |
|
||||
GIT_TAG="$(Build.SourceBranch)"
|
||||
git config --global user.name "matchai"
|
||||
git config --global user.email "hello@matchai.me"
|
||||
git config --global config.helper store
|
||||
echo "https://matchai:${HOMEBREW_GITHUB_API_TOKEN}@github.com" >> ~/.git-credentials
|
||||
brew update
|
||||
brew bump-formula-pr --url=https://github.com/starship/starship/archive/${GIT_TAG}.tar.gz --message="Automated release pull request using continuous integration." --no-browse -v starship
|
||||
displayName: Bump the Homebrew formula
|
||||
@@ -1,13 +0,0 @@
|
||||
parameters:
|
||||
rust_version: stable
|
||||
|
||||
jobs:
|
||||
- job: ${{ parameters.name }}
|
||||
displayName: ${{ parameters.displayName }}
|
||||
pool:
|
||||
vmImage: ubuntu-16.04
|
||||
steps:
|
||||
- template: install-rust.yml
|
||||
|
||||
- script: cargo check
|
||||
displayName: Check features
|
||||
@@ -1,13 +0,0 @@
|
||||
parameters:
|
||||
rust_version: stable
|
||||
|
||||
jobs:
|
||||
- job: ${{ parameters.name }}
|
||||
displayName: ${{ parameters.displayName }}
|
||||
pool:
|
||||
vmImage: ubuntu-16.04
|
||||
steps:
|
||||
- template: install-rust.yml
|
||||
|
||||
- script: cargo clippy -- -D clippy::all
|
||||
displayName: Run clippy
|
||||
@@ -32,10 +32,6 @@ steps:
|
||||
git config --global user.name "I merge the things"
|
||||
git clone https://github.com/rust-embedded/cross
|
||||
cd cross
|
||||
git remote add pitkley https://github.com/pitkley/cross
|
||||
git fetch pitkley
|
||||
git checkout 718a19c
|
||||
git merge -m "No pseudo tty" pitkley/docker-no-pseudo-tty
|
||||
cargo install --force --path .
|
||||
displayName: Install cross
|
||||
# All platforms
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
jobs:
|
||||
# Check formatting
|
||||
- job: ${{ parameters.name }}
|
||||
displayName: Check rustfmt
|
||||
pool:
|
||||
vmImage: ubuntu-16.04
|
||||
steps:
|
||||
- template: install-rust.yml
|
||||
parameters:
|
||||
rust_version: stable
|
||||
- script: |
|
||||
rustup component add rustfmt
|
||||
displayName: Install rustfmt
|
||||
- script: |
|
||||
cargo fmt --all -- --check
|
||||
displayName: Check formatting
|
||||
@@ -1,25 +0,0 @@
|
||||
steps:
|
||||
# Install Node.js
|
||||
- task: NodeTool@0
|
||||
inputs:
|
||||
versionSpec: "12.0.0"
|
||||
displayName: "Install a fixed version of Node"
|
||||
# Install Go
|
||||
- task: GoTool@0
|
||||
inputs:
|
||||
versionSpec: "1.10"
|
||||
displayName: "Install a fixed version of Go"
|
||||
|
||||
# We are using pyenv to install Python for integration tests
|
||||
# Install Python
|
||||
- script: |
|
||||
echo "##vso[task.setvariable variable=PYTHON_VERSION;]3.6.9"
|
||||
echo "##vso[task.setvariable variable=PYENV_ROOT;]$HOME/.pyenv"
|
||||
- script: |
|
||||
curl https://pyenv.run | bash
|
||||
echo "##vso[task.setvariable variable=PATH;]$PYENV_ROOT/bin:$PYENV_ROOT/shims:$PATH"
|
||||
- script: |
|
||||
eval "$(pyenv init -)"
|
||||
pyenv install $PYTHON_VERSION
|
||||
pyenv global $PYTHON_VERSION
|
||||
displayName: "Install a fixed version of Python"
|
||||
@@ -1,23 +0,0 @@
|
||||
jobs:
|
||||
- job: ${{ parameters.name }}
|
||||
displayName: ${{ parameters.displayName }}
|
||||
pool:
|
||||
vmImage: ubuntu-16.04
|
||||
|
||||
steps:
|
||||
- script: docker pull starshipcommand/starship-test
|
||||
displayName: Pull docker image
|
||||
|
||||
- script: |
|
||||
# In order to run tests as a non-root user in docker,
|
||||
# the files need to be accessible to non-root users
|
||||
chmod -R a+w .
|
||||
./integration_test
|
||||
displayName: Run integration test suite
|
||||
|
||||
- script: |
|
||||
docker login -u $(dockerUsername) -p $(dockerPassword)
|
||||
docker push starshipcommand/starship-test
|
||||
# Only push new image if on master and build is passing
|
||||
condition: and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/master'))
|
||||
displayName: Push image to dockerhub
|
||||
-28
@@ -1,28 +0,0 @@
|
||||
parameters:
|
||||
rust_version: stable
|
||||
|
||||
jobs:
|
||||
- job: ${{ parameters.name }}
|
||||
displayName: ${{ parameters.displayName }} ${{parameters.rust_version}}
|
||||
strategy:
|
||||
matrix:
|
||||
Linux:
|
||||
vmImage: ubuntu-16.04
|
||||
|
||||
${{ if parameters.cross }}:
|
||||
MacOS:
|
||||
vmImage: macOS-10.13
|
||||
# Temporarily disable Windows support
|
||||
# Windows:
|
||||
# vmImage: vs2017-win2016
|
||||
pool:
|
||||
vmImage: $(vmImage)
|
||||
|
||||
steps:
|
||||
- template: install-rust.yml
|
||||
- template: setup-test-env.yml
|
||||
- script: |
|
||||
cargo test -- -Z unstable-options --include-ignored
|
||||
env:
|
||||
CI: "true"
|
||||
displayName: cargo test
|
||||
@@ -9,7 +9,8 @@ module.exports = {
|
||||
sidebar: [
|
||||
'/',
|
||||
['/guide/', 'Guide'],
|
||||
['/config/', 'Configuration']
|
||||
['/config/', 'Configuration'],
|
||||
['/advanced-config/', 'Advanced Configuration']
|
||||
],
|
||||
nav: [
|
||||
{ text: 'Configuration', link: '/config/' },
|
||||
@@ -24,5 +25,13 @@ module.exports = {
|
||||
editLinks: true,
|
||||
// custom text for edit link. Defaults to "Edit this page"
|
||||
editLinkText: 'Edit this page on GitHub'
|
||||
}
|
||||
},
|
||||
plugins: [
|
||||
[
|
||||
'@vuepress/google-analytics',
|
||||
{
|
||||
'ga': 'UA-71160903-4'
|
||||
}
|
||||
]
|
||||
]
|
||||
}
|
||||
|
||||
Binary file not shown.
Binary file not shown.
@@ -8,8 +8,15 @@ $codeBgColor = #282c34
|
||||
min-width: 300px
|
||||
width: 100%
|
||||
|
||||
.center
|
||||
margin 0 auto;
|
||||
width: 80%
|
||||
.demo-video
|
||||
width: 100%
|
||||
margin: 50px 0
|
||||
|
||||
#main-title
|
||||
display: none
|
||||
|
||||
.hero
|
||||
margin: 150px 25px
|
||||
margin: 150px 25px 70px
|
||||
|
||||
+63
-16
@@ -21,32 +21,79 @@ footer: ISC Licensed | Copyright © 2019-present Starship Contributors
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="center">
|
||||
<video class="demo-video" autoplay muted loop>
|
||||
<source src="/demo.webm" type="video/webm">
|
||||
<source src="/demo.mp4" type="video/mp4">
|
||||
</video>
|
||||
</div>
|
||||
|
||||
### Quick Install
|
||||
|
||||
1. Install the **starship** binary:
|
||||
|
||||
```bash
|
||||
cargo install starship
|
||||
```
|
||||
**[Download archives of precompiled binaries](https://github.com/starship/starship/releases)** if you don't use the platforms below.
|
||||
|
||||
#### Homebrew
|
||||
|
||||
```sh
|
||||
$ brew install starship
|
||||
```
|
||||
|
||||
#### Rust (v1.33 or higher)
|
||||
|
||||
```sh
|
||||
$ cargo install starship
|
||||
```
|
||||
|
||||
#### Arch Linux (AUR)
|
||||
|
||||
Starship is available on the AUR under the name `starship`. Install it with `yay` or your favorite AUR helper.
|
||||
|
||||
```sh
|
||||
$ yay -S starship
|
||||
```
|
||||
|
||||
#### Nix (unstable)
|
||||
|
||||
```sh
|
||||
$ nix-env --install starship
|
||||
```
|
||||
|
||||
#### Termux
|
||||
|
||||
```sh
|
||||
$ pkg install starship
|
||||
```
|
||||
|
||||
1. Add the init script to your shell's config file:
|
||||
|
||||
#### Bash / Zsh
|
||||
#### Bash
|
||||
|
||||
Add the following to the end of `~/.bashrc` or `~/.zshrc`:
|
||||
Add the following to the end of `~/.bashrc`:
|
||||
|
||||
```bash
|
||||
# ~/.bashrc or ~/.zshrc
|
||||
|
||||
eval "$(starship init $0)"
|
||||
```
|
||||
```sh
|
||||
# ~/.bashrc
|
||||
|
||||
#### Fish
|
||||
eval "$(starship init bash)"
|
||||
```
|
||||
|
||||
Add the following to the end of `~/.config/fish/config.fish`:
|
||||
#### Fish
|
||||
|
||||
```sh
|
||||
# ~/.config/fish/config.fish
|
||||
Add the following to the end of `~/.config/fish/config.fish`:
|
||||
|
||||
eval (starship init fish)
|
||||
```
|
||||
```sh
|
||||
# ~/.config/fish/config.fish
|
||||
|
||||
eval (starship init fish)
|
||||
```
|
||||
|
||||
#### Zsh
|
||||
|
||||
Add the following to the end of `~/.zshrc`:
|
||||
|
||||
```sh
|
||||
# ~/.zshrc
|
||||
|
||||
eval "$(starship init zsh)"
|
||||
```
|
||||
|
||||
@@ -0,0 +1,101 @@
|
||||
# Advanced Configuration
|
||||
|
||||
While Starship is a versatile shell, sometimes you need to do more than edit
|
||||
`starship.toml` to get it to do certain things. This page details some of the more
|
||||
advanced configuration techniques used in starship.
|
||||
|
||||
::: warning
|
||||
The configurations in this section are subject to change in future releases of Starship.
|
||||
:::
|
||||
|
||||
## Custom pre-prompt and pre-execution Commands in Bash
|
||||
|
||||
Bash does not have a formal preexec/precmd framework like most other shells.
|
||||
Because of this, it is difficult to provide fully customizable hooks in `bash`.
|
||||
However, Starship does give you limited ability to insert your own functions
|
||||
into the prompt-rendering procedure:
|
||||
|
||||
- To run a custom function right before the prompt is drawn, define a new
|
||||
function and then assign its name to `starship_precmd_user_func`. For example,
|
||||
to draw a rocket before the prompt, you would do
|
||||
|
||||
```bash
|
||||
function blastoff(){
|
||||
echo "🚀"
|
||||
}
|
||||
starship_precmd_user_func="blastoff"
|
||||
```
|
||||
|
||||
- To run a custom function right before a command runs, you can use the
|
||||
[`DEBUG` trap mechanism](https://jichu4n.com/posts/debug-trap-and-prompt_command-in-bash/).
|
||||
However, you **must** trap the DEBUG signal *before* initializing Starship!
|
||||
Starship can preserve the value of the DEBUG trap, but if the trap is overwritten
|
||||
after starship starts up, some functionality will break.
|
||||
|
||||
```bash
|
||||
function blastoff(){
|
||||
echo "🚀"
|
||||
}
|
||||
trap blastoff DEBUG # Trap DEBUG *before* running starship
|
||||
eval $(starship init bash)
|
||||
```
|
||||
|
||||
## Change Window Title
|
||||
|
||||
Some shell prompts will automatically change the window title for you (e.g. to
|
||||
reflect your working directory). Fish even does it by default.
|
||||
Starship does not do this, but it's fairly straightforward to add this
|
||||
functionality to `bash` or `zsh`.
|
||||
|
||||
First, define a window title change function (identical in bash and zsh):
|
||||
|
||||
```bash
|
||||
function set_win_title(){
|
||||
echo -ne "\033]0; YOUR_WINDOW_TITLE_HERE \007"
|
||||
}
|
||||
```
|
||||
|
||||
You can use variables to customize this title (`$USER`, `$HOSTNAME`, and `$PWD`
|
||||
are popular choices).
|
||||
|
||||
In `bash`, set this function to be the precmd starship function:
|
||||
|
||||
```bash
|
||||
starship_precmd_user_func="set_win_title"
|
||||
```
|
||||
|
||||
In `zsh`, add this to the `precmd_functions` array:
|
||||
|
||||
```bash
|
||||
precmd_functions+=(set_win_title)
|
||||
```
|
||||
|
||||
If you like the result, add these lines to your shell configuration file
|
||||
(`~/.bashrc` or `~/.zsrhc`) to make it permanent.
|
||||
|
||||
## Style Strings
|
||||
|
||||
Style strings are a list of words, separated by whitespace. The words are not case sensitive (i.e. `bold` and `BoLd` are considered the same string). Each word can be one of the following:
|
||||
|
||||
- `bold`
|
||||
- `underline`
|
||||
- `dimmed`
|
||||
- `bg:<color>`
|
||||
- `fg:<color>`
|
||||
- `<color>`
|
||||
- `none`
|
||||
|
||||
where `<color>` is a color specifier (discussed below). `fg:<color>` and `<color>` currently do the same thing , though this may change in the future. The order of words in the string does not matter.
|
||||
|
||||
The `none` token overrides all other tokens in a string, so that e.g. `fg:red none fg:blue` will still create a string with no styling. It may become an error to use `none` in conjunction with other tokens in the future.
|
||||
|
||||
A color specifier can be one of the following:
|
||||
|
||||
- One of the standard terminal colors: `black`, `red`, `green`, `blue`,
|
||||
`yellow`, `purple`, `cyan`, `white`. You can optionally prefix these
|
||||
with `bright-` to get the bright version (e.g. `bright-white`).
|
||||
- A `#` followed by a six-digit hexadecimal number. This specifies an
|
||||
[RGB color hex code](https://www.w3schools.com/colors/colors_hexadecimal.asp).
|
||||
- A number between 0-255. This specifies an [8-bit ANSI Color Code](https://i.stack.imgur.com/KTSQa.png).
|
||||
|
||||
If multiple colors are specified for foreground/background, the last one in the string will take priority.
|
||||
+278
-83
@@ -17,9 +17,9 @@ All configuration for starship is done in this [TOML](https://github.com/toml-la
|
||||
# Don't print a new line at the start of the prompt
|
||||
add_newline = false
|
||||
|
||||
# Replace the "➜" symbol in the prompt with "❯"
|
||||
# Replace the "❯" symbol in the prompt with "➜"
|
||||
[character] # The name of the module we are confguring is "character"
|
||||
symbol = "❯" # The "symbol" segment is being set to "❯"
|
||||
symbol = "➜" # The "symbol" segment is being set to "➜"
|
||||
|
||||
# Disable the package module, hiding it from the prompt completely
|
||||
[package]
|
||||
@@ -40,15 +40,28 @@ are segments within it. Every module also has a prefix and suffix that are the d
|
||||
"via " "⬢" "v10.4.1" ""
|
||||
```
|
||||
|
||||
### Style Strings
|
||||
|
||||
Most modules in starship allow you to configure their display styles. This is done with an entry (usually called `style`) which is a string specifying the configuration. Here are some examples of style strings along with what they do. For details on the full syntax, consult the [advanced config guide](/advanced-config/).
|
||||
|
||||
- `"fg:green bg:blue"` sets green text on a blue background
|
||||
- `"bg:blue fg:bright-green"` sets bright green text on a blue background
|
||||
- `"bold fg:27"` sets bold text with [ANSI color](https://i.stack.imgur.com/KTSQa.png) 27
|
||||
- `"underline bg:#bf5700"` sets underlined text on a burnt orange background
|
||||
- `""` explicitly disables all styling
|
||||
|
||||
Note that what styling looks like will be controlled by your terminal emulator. For example, some terminal emulators will brighten the colors instead of bolding text, and some color themes use the same values for the normal and bright colors.
|
||||
|
||||
## Prompt
|
||||
|
||||
This is the list of prompt-wide configuration options.
|
||||
|
||||
### Options
|
||||
|
||||
| Variable | Default | Description |
|
||||
| ------------- | ------- | ---------------------------------------------- |
|
||||
| `add_newline` | `true` | Add a new line before the start of the prompt. |
|
||||
| Variable | Default | Description |
|
||||
| -------------- | ----------------------------- | ------------------------------------------------------ |
|
||||
| `add_newline` | `true` | Add a new line before the start of the prompt. |
|
||||
| `prompt_order` | [link](#default-prompt-order) | Configure the order in which the prompt module occurs. |
|
||||
|
||||
### Example
|
||||
|
||||
@@ -57,6 +70,35 @@ This is the list of prompt-wide configuration options.
|
||||
|
||||
# Disable the newline at the start of the prompt
|
||||
add_newline = false
|
||||
# Overwrite a default_prompt_order and use custom prompt_order
|
||||
prompt_order=["rust","line_break","package","line_break","character"]
|
||||
```
|
||||
|
||||
### Default prompt order
|
||||
|
||||
The `default_prompt_order` configuration option is used to define the order in which modules are shown in the prompt, if empty or no `prompt_order` is provided. The default is as shown:
|
||||
|
||||
```
|
||||
default_prompt_order = [
|
||||
"username",
|
||||
"hostname",
|
||||
"directory",
|
||||
"git_branch",
|
||||
"git_state",
|
||||
"git_status",
|
||||
"package",
|
||||
"nodejs",
|
||||
"ruby",
|
||||
"rust",
|
||||
"python",
|
||||
"golang",
|
||||
"nix_shell",
|
||||
"cmd_duration",
|
||||
"line_break",
|
||||
"jobs",
|
||||
"battery",
|
||||
"character",
|
||||
]
|
||||
```
|
||||
|
||||
## Battery
|
||||
@@ -66,12 +108,13 @@ The module is only visible when the device's battery is below 10%.
|
||||
|
||||
### Options
|
||||
|
||||
| Variable | Default | Description |
|
||||
| -------------------- | ------- | ------------------------------------------------- |
|
||||
| `full_symbol` | `"•"` | The symbol shown when the battery is full. |
|
||||
| `charging_symbol` | `"⇡"` | The symbol shown when the battery is charging. |
|
||||
| `discharging_symbol` | `"⇣"` | The symbol shown when the battery is discharging. |
|
||||
| `disabled` | `false` | Disables the `battery` module. |
|
||||
| Variable | Default | Description |
|
||||
| -------------------- | ------------ | ------------------------------------------------- |
|
||||
| `full_symbol` | `"•"` | The symbol shown when the battery is full. |
|
||||
| `charging_symbol` | `"⇡"` | The symbol shown when the battery is charging. |
|
||||
| `discharging_symbol` | `"⇣"` | The symbol shown when the battery is discharging. |
|
||||
| `style` | `"bold red"` | The style for the module. |
|
||||
| `disabled` | `false` | Disables the `battery` module. |
|
||||
|
||||
### Example
|
||||
|
||||
@@ -89,18 +132,21 @@ discharging_symbol = "💀"
|
||||
The `character` module shows a character (usually an arrow) beside where the text
|
||||
is entered in your terminal.
|
||||
|
||||
The character will tell you whether the last command was successful or not. It
|
||||
can do this in two ways: by changing color (red/green) or by changing its shape
|
||||
(➜/✖). The latter will only be done if `use_symbol_for_status` is set to `true`.
|
||||
The character will tell you whether the last command was successful or not. It
|
||||
can do this in two ways: by changing color (red/green) or by changing its shape
|
||||
(❯/✖). The latter will only be done if `use_symbol_for_status` is set to `true`.
|
||||
|
||||
### Options
|
||||
|
||||
| Variable | Default | Description |
|
||||
| ---------- | ------- | ---------------------------------------------------- |
|
||||
| `symbol` | `"➜"` | The symbol used before the text input in the prompt. |
|
||||
| `error_symbol` | `"✖"` | The symbol used before text input if the previous command failed. |
|
||||
| `use_symbol_for_status` | `false` | Indicate error status by changing the symbol. |
|
||||
| `disabled` | `false` | Disables the `character` module. |
|
||||
| Variable | Default | Description |
|
||||
| ----------------------- | -------------- | ----------------------------------------------------------------------------------- |
|
||||
| `symbol` | `"❯"` | The symbol used before the text input in the prompt. |
|
||||
| `error_symbol` | `"✖"` | The symbol used before text input if the previous command failed. |
|
||||
| `use_symbol_for_status` | `false` | Indicate error status by changing the symbol. |
|
||||
| `vicmd_symbol` | `"❮"` | The symbol used before the text input in the prompt if shell is in vim normal mode. |
|
||||
| `style_success` | `"bold green"` | The style used if the last command was successful. |
|
||||
| `style_failure` | `"bold red"` | The style used if the last command failed. |
|
||||
| `disabled` | `false` | Disables the `character` module. |
|
||||
|
||||
### Example
|
||||
|
||||
@@ -108,7 +154,7 @@ can do this in two ways: by changing color (red/green) or by changing its shape
|
||||
# ~/.config/starship.toml
|
||||
|
||||
[character]
|
||||
symbol = "❯"
|
||||
symbol = "➜"
|
||||
error_symbol = "✗"
|
||||
use_symbol_for_status = true
|
||||
```
|
||||
@@ -119,17 +165,23 @@ The `cmd_duration` module shows how long the last command took to execute.
|
||||
The module will be shown only if the command took longer than two seconds, or
|
||||
the `min_time` config value, if it exists.
|
||||
|
||||
::: warning NOTE
|
||||
Command duration is currently not supported in `bash`. See
|
||||
[this issue](https://github.com/starship/starship/issues/124) for more details.
|
||||
::: warning Do not hook the DEBUG trap in Bash
|
||||
If you are running Starship in `bash`, do not hook the `DEBUG` trap after running
|
||||
`eval $(starship init $0)`, or this module **will** break.
|
||||
:::
|
||||
|
||||
Bash users who need preexec-like functionality can use
|
||||
[rcaloras's bash_preexec framework](https://github.com/rcaloras/bash-preexec).
|
||||
Simply define the arrays `preexec_functions` and `precmd_functions` before
|
||||
running `eval $(starship init $0)`, and then proceed as normal.
|
||||
|
||||
### Options
|
||||
|
||||
| Variable | Default | Description |
|
||||
| ---------- | ------- | ----------------------------------- |
|
||||
| `min_time` | `2` | Shortest duration to show time for. |
|
||||
| `disabled` | `false` | Disables the `cmd_duration` module. |
|
||||
| Variable | Default | Description |
|
||||
| ---------- | --------------- | ----------------------------------- |
|
||||
| `min_time` | `2` | Shortest duration to show time for. |
|
||||
| `style` | `"bold yellow"` | The style for the module. |
|
||||
| `disabled` | `false` | Disables the `cmd_duration` module. |
|
||||
|
||||
### Example
|
||||
|
||||
@@ -146,12 +198,23 @@ The `directory` module shows the path to your current directory, truncated to
|
||||
three parent folders. Your directory will also be truncated to the root of the
|
||||
git repo that you're currently in.
|
||||
|
||||
When using the fish style pwd option, instead of hiding the path that is
|
||||
truncated, you will see a shortened name of each directory based on the number
|
||||
you enable for the option.
|
||||
|
||||
For example, given `~/Dev/Nix/nixpkgs/pkgs` where `nixpkgs` is the repo root,
|
||||
and the option set to `1`. You will now see `~/D/N/nixpkgs/pkgs`, whereas before
|
||||
it would have been `nixpkgs/pkgs`.
|
||||
|
||||
### Options
|
||||
|
||||
| Variable | Default | Description |
|
||||
| ------------------- | ------- | ------------------------------------------------------------------------------- |
|
||||
| `truncation_length` | `3` | The number of parent folders that the current directory should be truncated to. |
|
||||
| `disabled` | `false` | Disables the `directory` module. |
|
||||
| Variable | Default | Description |
|
||||
| --------------------------- | ------------- | -------------------------------------------------------------------------------- |
|
||||
| `truncation_length` | `3` | The number of parent folders that the current directory should be truncated to. |
|
||||
| `truncate_to_repo` | `true` | Whether or not to truncate to the root of the git repo that you're currently in. |
|
||||
| `fish_style_pwd_dir_length` | `0` | The number of characters to use when applying fish shell pwd path logic. |
|
||||
| `style` | `"bold cyan"` | The style for the module. |
|
||||
| `disabled` | `false` | Disables the `directory` module. |
|
||||
|
||||
### Example
|
||||
|
||||
@@ -168,10 +231,13 @@ The `git_branch` module shows the active branch of the repo in your current dire
|
||||
|
||||
### Options
|
||||
|
||||
| Variable | Default | Description |
|
||||
| ---------- | ------- | ----------------------------------------------------------------------------- |
|
||||
| `symbol` | `" "` | The symbol used before the branch name of the repo in your current directory. |
|
||||
| `disabled` | `false` | Disables the `git_branch` module. |
|
||||
| Variable | Default | Description |
|
||||
| ------------------- | --------------- | ------------------------------------------------------------------------------------- |
|
||||
| `symbol` | `" "` | The symbol used before the branch name of the repo in your current directory. |
|
||||
| `truncation_length` | `2^63 - 1` | Truncates a git branch to X graphemes |
|
||||
| `truncation_symbol` | `"…"` | The symbol used to indicate a branch name was truncated. You can use "" for no symbol |
|
||||
| `style` | `"bold purple"` | The style for the module. |
|
||||
| `disabled` | `false` | Disables the `git_branch` module. |
|
||||
|
||||
### Example
|
||||
|
||||
@@ -180,6 +246,40 @@ The `git_branch` module shows the active branch of the repo in your current dire
|
||||
|
||||
[git_branch]
|
||||
symbol = "🌱 "
|
||||
truncation_length = "4"
|
||||
truncation_symbol = ""
|
||||
```
|
||||
|
||||
## Git State
|
||||
|
||||
The `git_state` module will show in directories which are part of a git
|
||||
repository, and where there is an operation in progress, such as: _REBASING_,
|
||||
_BISECTING_, etc. If there is progress information (e.g., REBASING 3/10),
|
||||
that information will be shown too.
|
||||
|
||||
### Options
|
||||
|
||||
| Variable | Default | Description |
|
||||
| ------------------ | ------------------ | ---------------------------------------------------------------------------------------------------------------- |
|
||||
| `rebase` | `"REBASING"` | The text displayed when a `rebase` is in progress. |
|
||||
| `merge` | `"MERGING"` | The text displayed when a `merge` is in progress. |
|
||||
| `revert` | `"REVERTING"` | The text displayed when a `revert` is in progress. |
|
||||
| `cherry_pick` | `"CHERRY-PICKING"` | The text displayed when a `cherry-pick` is in progress. |
|
||||
| `bisect` | `"BISECTING"` | The text displayed when a `bisect` is in progress. |
|
||||
| `am` | `"AM"` | The text displayed when an `apply-mailbox` (`git am`) is in progress. |
|
||||
| `am_or_rebase` | `"AM/REBASE"` | The text displayed when an ambiguous `apply-mailbox` or `rebase` is in progress. |
|
||||
| `progress_divider` | `"/"` | The symbol or text which will separate the current and total progress amounts. (e.g., `" of "`, for `"3 of 10"`) |
|
||||
| `style` | `"bold yellow"` | The style for the module. |
|
||||
| `disabled` | `false` | Disables the `git_state` module. |
|
||||
|
||||
### Example
|
||||
|
||||
```toml
|
||||
# ~/.config/starship.toml
|
||||
|
||||
[git_state]
|
||||
progress_divider = " of "
|
||||
cherry_pick = "🍒 PICKING"
|
||||
```
|
||||
|
||||
## Git Status
|
||||
@@ -189,19 +289,21 @@ current directory.
|
||||
|
||||
### Options
|
||||
|
||||
| Variable | Default | Description |
|
||||
| ------------ | ------- | ------------------------------------------------------- |
|
||||
| `conflicted` | `"="` | This branch has merge conflicts. |
|
||||
| `ahead` | `"⇡"` | This branch is ahead of the branch being tracked. |
|
||||
| `behind` | `"⇣"` | This branch is behind of the branch being tracked. |
|
||||
| `diverged` | `"⇕"` | This branch has diverged from the branch being tracked. |
|
||||
| `untracked` | `"?"` | There are untracked files in the working directory. |
|
||||
| `stashed` | `"$"` | A stash exists for the local repository. |
|
||||
| `modified` | `"!"` | There are file modifications in the working directory. |
|
||||
| `added` | `"+"` | A new file has been added to the staging area. |
|
||||
| `renamed` | `"»"` | A renamed file has been added to the staging area. |
|
||||
| `deleted` | `"✘"` | A file's deletion has been added to the staging area. |
|
||||
| `disabled` | `false` | Disables the `git_status` module. |
|
||||
| Variable | Default | Description |
|
||||
| ----------------- | ------------ | ------------------------------------------------------- |
|
||||
| `conflicted` | `"="` | This branch has merge conflicts. |
|
||||
| `ahead` | `"⇡"` | This branch is ahead of the branch being tracked. |
|
||||
| `behind` | `"⇣"` | This branch is behind of the branch being tracked. |
|
||||
| `diverged` | `"⇕"` | This branch has diverged from the branch being tracked. |
|
||||
| `untracked` | `"?"` | There are untracked files in the working directory. |
|
||||
| `stashed` | `"$"` | A stash exists for the local repository. |
|
||||
| `modified` | `"!"` | There are file modifications in the working directory. |
|
||||
| `staged` | `"+"` | A new file has been added to the staging area. |
|
||||
| `renamed` | `"»"` | A renamed file has been added to the staging area. |
|
||||
| `deleted` | `"✘"` | A file's deletion has been added to the staging area. |
|
||||
| `show_sync_count` | `false` | Show ahead/behind count of the branch being tracked. |
|
||||
| `style` | `"bold red"` | The style for the module. |
|
||||
| `disabled` | `false` | Disables the `git_status` module. |
|
||||
|
||||
### Example
|
||||
|
||||
@@ -216,7 +318,7 @@ diverged = "😵"
|
||||
untracked = "🤷"
|
||||
stashed = "📦"
|
||||
modified = "📝"
|
||||
added = "➕"
|
||||
staged = "➕"
|
||||
renamed = "👅"
|
||||
deleted = "🗑"
|
||||
```
|
||||
@@ -236,10 +338,11 @@ The module will be shown if any of the following conditions are met:
|
||||
|
||||
### Options
|
||||
|
||||
| Variable | Default | Description |
|
||||
| ---------- | ------- | -------------------------------------------------------- |
|
||||
| `symbol` | `"🐹 "` | The symbol used before displaying the version of Golang. |
|
||||
| `disabled` | `false` | Disables the `golang` module. |
|
||||
| Variable | Default | Description |
|
||||
| ---------- | ------------- | -------------------------------------------------------- |
|
||||
| `symbol` | `"🐹 "` | The symbol used before displaying the version of Golang. |
|
||||
| `style` | `"bold cyan"` | The style for the module. |
|
||||
| `disabled` | `false` | Disables the `golang` module. |
|
||||
|
||||
### Example
|
||||
|
||||
@@ -250,6 +353,34 @@ The module will be shown if any of the following conditions are met:
|
||||
symbol = "🏎💨 "
|
||||
```
|
||||
|
||||
|
||||
## Hostname
|
||||
|
||||
The `hostname` module shows the system hostname.
|
||||
|
||||
### Options
|
||||
|
||||
| Variable | Default | Description |
|
||||
| ---------- | --------------------- | ---------------------------------------------------- |
|
||||
| `ssh_only` | `true` | Only show hostname when connected to an SSH session. |
|
||||
| `prefix` | `""` | Prefix to display immediately before the hostname. |
|
||||
| `suffix` | `""` | Suffix to display immediately after the hostname. |
|
||||
| `style` | `"bold dimmed green"` | The style for the module. |
|
||||
| `disabled` | `false` | Disables the `hostname` module. |
|
||||
|
||||
### Example
|
||||
|
||||
```toml
|
||||
# ~/.config/starship.toml
|
||||
|
||||
[hostname]
|
||||
ssh_only = false
|
||||
prefix = "⟪"
|
||||
suffix = "⟫"
|
||||
disabled = false
|
||||
```
|
||||
|
||||
|
||||
## Jobs
|
||||
|
||||
The `jobs` module shows the current number of jobs running.
|
||||
@@ -259,10 +390,12 @@ more than the `threshold` config value, if it exists.
|
||||
|
||||
### Options
|
||||
|
||||
| Variable | Default | Description |
|
||||
| ----------- | ------- | -------------------------------- |
|
||||
| `threshold` | `1` | Show number of jobs if execeded. |
|
||||
| `disabled` | `false` | Disables the `jobs` module. |
|
||||
| Variable | Default | Description |
|
||||
| ----------- | ------------- | ----------------------------------------------------- |
|
||||
| `symbol` | `"✦ "` | The symbol used before displaying the number of jobs. |
|
||||
| `threshold` | `1` | Show number of jobs if exceeded. |
|
||||
| `style` | `"bold blue"` | The style for the module. |
|
||||
| `disabled` | `false` | Disables the `jobs` module. |
|
||||
|
||||
### Example
|
||||
|
||||
@@ -270,6 +403,7 @@ more than the `threshold` config value, if it exists.
|
||||
# ~/.config/starship.toml
|
||||
|
||||
[jobs]
|
||||
symbol = "+ "
|
||||
threshold = 4
|
||||
```
|
||||
|
||||
@@ -292,6 +426,44 @@ The `line_break` module separates the prompt into two lines.
|
||||
disabled = true
|
||||
```
|
||||
|
||||
|
||||
### Example
|
||||
|
||||
```toml
|
||||
# ~/.config/starship.toml
|
||||
|
||||
[ruby]
|
||||
symbol = "🔺 "
|
||||
```
|
||||
|
||||
## Nix-shell
|
||||
|
||||
The `nix_shell` module shows the nix-shell environment.
|
||||
The module will be shown when inside a nix-shell environment.
|
||||
|
||||
### Options
|
||||
|
||||
| Variable | Default | Description |
|
||||
| ------------ | ------------ | ---------------------------------- |
|
||||
| `use_name` | `false` | Display the name of the nix-shell. |
|
||||
| `impure_msg` | `impure` | Customize the "impure" msg. |
|
||||
| `pure_msg` | `pure` | Customize the "pure" msg. |
|
||||
| `style` | `"bold red"` | The style for the module. |
|
||||
| `disabled` | `false` | Disables the `nix_shell` module. |
|
||||
|
||||
### Example
|
||||
|
||||
```toml
|
||||
# ~/.config/starship.toml
|
||||
|
||||
[nix_shell]
|
||||
disabled = true
|
||||
use_name = true
|
||||
impure_msg = "impure shell"
|
||||
pure_msg = "pure shell"
|
||||
```
|
||||
|
||||
|
||||
## NodeJS
|
||||
|
||||
The `nodejs` module shows the currently installed version of NodeJS.
|
||||
@@ -303,10 +475,11 @@ The module will be shown if any of the following conditions are met:
|
||||
|
||||
### Options
|
||||
|
||||
| Variable | Default | Description |
|
||||
| ---------- | ------- | -------------------------------------------------------- |
|
||||
| `symbol` | `"⬢ "` | The symbol used before displaying the version of NodeJS. |
|
||||
| `disabled` | `false` | Disables the `nodejs` module. |
|
||||
| Variable | Default | Description |
|
||||
| ---------- | -------------- | -------------------------------------------------------- |
|
||||
| `symbol` | `"⬢ "` | The symbol used before displaying the version of NodeJS. |
|
||||
| `style` | `"bold green"` | The style for the module. |
|
||||
| `disabled` | `false` | Disables the `nodejs` module. |
|
||||
|
||||
### Example
|
||||
|
||||
@@ -320,23 +493,26 @@ symbol = "🤖 "
|
||||
## Package Version
|
||||
|
||||
The `package` module is shown when the current directory is the repository for a
|
||||
package, and shows its current version. The module currently supports `npm` and
|
||||
`cargo` packages.
|
||||
package, and shows its current version. The module currently supports `npm`, `cargo`,
|
||||
and `poetry` packages.
|
||||
|
||||
- **npm** – The `npm` package version is extracted from the `package.json` present
|
||||
in the current directory
|
||||
- **cargo** – The `cargo` package version is extracted from the `Cargo.toml` present
|
||||
in the current directory
|
||||
- **poetry** – The `poetry` package version is extracted from the `pyproject.toml` present
|
||||
in the current directory
|
||||
|
||||
> ⚠️ The version being shown is that of the package whose source code is in your
|
||||
> current directory, not your package manager.
|
||||
|
||||
### Options
|
||||
|
||||
| Variable | Default | Description |
|
||||
| ---------- | ------- | ---------------------------------------------------------- |
|
||||
| `symbol` | `"📦 "` | The symbol used before displaying the version the package. |
|
||||
| `disabled` | `false` | Disables the `package` module. |
|
||||
| Variable | Default | Description |
|
||||
| ---------- | ------------ | ---------------------------------------------------------- |
|
||||
| `symbol` | `"📦 "` | The symbol used before displaying the version the package. |
|
||||
| `style` | `"bold red"` | The style for the module. |
|
||||
| `disabled` | `false` | Disables the `package` module. |
|
||||
|
||||
### Example
|
||||
|
||||
@@ -363,16 +539,17 @@ The module will be shown if any of the following conditions are met:
|
||||
- The current directory contains a `requirements.txt` file
|
||||
- The current directory contains a `pyproject.toml` file
|
||||
- The current directory contains a file with the `.py` extension
|
||||
- The current directory contains a `Pipfile` file
|
||||
|
||||
### Options
|
||||
|
||||
| Variable | Default | Description |
|
||||
| ---------- | ------- | -------------------------------------------------------- |
|
||||
| `symbol` | `"🐍 "` | The symbol used before displaying the version of Python. |
|
||||
| `disabled` | `false` | Disables the `python` module. |
|
||||
| `pyenv_version_name` | `false` | Use pyenv to get Python version |
|
||||
| `pyenv_prefix` | `"pyenv "` | Prefix before pyenv version display (default display is `pyenv MY_VERSION`) |
|
||||
|
||||
| Variable | Default | Description |
|
||||
| -------------------- | --------------- | --------------------------------------------------------------------------- |
|
||||
| `symbol` | `"🐍 "` | The symbol used before displaying the version of Python. |
|
||||
| `pyenv_version_name` | `false` | Use pyenv to get Python version |
|
||||
| `pyenv_prefix` | `"pyenv "` | Prefix before pyenv version display (default display is `pyenv MY_VERSION`) |
|
||||
| `style` | `"bold yellow"` | The style for the module. |
|
||||
| `disabled` | `false` | Disables the `python` module. |
|
||||
|
||||
### Example
|
||||
|
||||
@@ -385,6 +562,22 @@ pyenv_version_name = true
|
||||
pyenv_prefix = "foo "
|
||||
```
|
||||
|
||||
## Ruby
|
||||
|
||||
The `ruby` module shows the currently installed version of Ruby.
|
||||
The module will be shown if any of the following conditions are met:
|
||||
|
||||
- The current directory contains a `Gemfile` file
|
||||
- The current directory contains a `.rb` file
|
||||
|
||||
### Options
|
||||
|
||||
| Variable | Default | Description |
|
||||
| ---------- | ------------ | ------------------------------------------------------ |
|
||||
| `symbol` | `"💎 "` | The symbol used before displaying the version of Ruby. |
|
||||
| `style` | `"bold red"` | The style for the module. |
|
||||
| `disabled` | `false` | Disables the `ruby` module. |
|
||||
|
||||
## Rust
|
||||
|
||||
The `rust` module shows the currently installed version of Rust.
|
||||
@@ -395,10 +588,11 @@ The module will be shown if any of the following conditions are met:
|
||||
|
||||
### Options
|
||||
|
||||
| Variable | Default | Description |
|
||||
| ---------- | ------- | -------------------------------------------------------- |
|
||||
| `symbol` | `"🦀 "` | The symbol used before displaying the version of Python. |
|
||||
| `disabled` | `false` | Disables the `rust` module. |
|
||||
| Variable | Default | Description |
|
||||
| ---------- | ------------ | ------------------------------------------------------ |
|
||||
| `symbol` | `"🦀 "` | The symbol used before displaying the version of Rust. |
|
||||
| `style` | `"bold red"` | The style for the module. |
|
||||
| `disabled` | `false` | Disables the `rust` module. |
|
||||
|
||||
### Example
|
||||
|
||||
@@ -420,9 +614,11 @@ The module will be shown if any of the following conditions are met:
|
||||
|
||||
### Options
|
||||
|
||||
| Variable | Default | Description |
|
||||
| ---------- | ------- | ------------------------------- |
|
||||
| `disabled` | `false` | Disables the `username` module. |
|
||||
| Variable | Default | Description |
|
||||
| ------------ | --------------- | ------------------------------------- |
|
||||
| `style_root` | `"bold red"` | The style used when the user is root. |
|
||||
| `style_user` | `"bold yellow"` | The style used for non-root users. |
|
||||
| `disabled` | `false` | Disables the `username` module. |
|
||||
|
||||
### Example
|
||||
|
||||
@@ -432,4 +628,3 @@ The module will be shown if any of the following conditions are met:
|
||||
[username]
|
||||
disabled = true
|
||||
```
|
||||
|
||||
|
||||
Generated
+6
@@ -1060,6 +1060,12 @@
|
||||
"lodash.throttle": "^4.1.1"
|
||||
}
|
||||
},
|
||||
"@vuepress/plugin-google-analytics": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@vuepress/plugin-google-analytics/-/plugin-google-analytics-1.0.3.tgz",
|
||||
"integrity": "sha512-mqFFQSJjQp5zscZJ0Ik+YDLV7sZSAO8w13CG8c5WsUCjy+0oWhqAw/NjpVrEK8Y/PdYPe4l/OE5jMUU5AqRRjg==",
|
||||
"dev": true
|
||||
},
|
||||
"@vuepress/plugin-last-updated": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@vuepress/plugin-last-updated/-/plugin-last-updated-1.0.2.tgz",
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
"build": "vuepress build"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@vuepress/plugin-google-analytics": "^1.0.3",
|
||||
"vuepress": "^1.0.2"
|
||||
}
|
||||
}
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 5.2 MiB After Width: | Height: | Size: 2.4 MiB |
+216
-1
@@ -4,6 +4,8 @@ use std::env;
|
||||
use dirs::home_dir;
|
||||
use toml::value::Table;
|
||||
|
||||
use ansi_term::Color;
|
||||
|
||||
pub trait Config {
|
||||
fn initialize() -> Table;
|
||||
fn config_from_file() -> Option<Table>;
|
||||
@@ -13,6 +15,8 @@ pub trait Config {
|
||||
fn get_as_bool(&self, key: &str) -> Option<bool>;
|
||||
fn get_as_str(&self, key: &str) -> Option<&str>;
|
||||
fn get_as_i64(&self, key: &str) -> Option<i64>;
|
||||
fn get_as_array(&self, key: &str) -> Option<&Vec<toml::value::Value>>;
|
||||
fn get_as_ansi_style(&self, key: &str) -> Option<ansi_term::Style>;
|
||||
|
||||
// Internal implementation for accessors
|
||||
fn get_config(&self, key: &str) -> Option<&toml::value::Value>;
|
||||
@@ -35,7 +39,7 @@ impl Config for Table {
|
||||
log::debug!("STARSHIP_CONFIG is set: \n{}", &path);
|
||||
path
|
||||
} else {
|
||||
// Default to using ~/.config/starhip.toml
|
||||
// Default to using ~/.config/starship.toml
|
||||
log::debug!("STARSHIP_CONFIG is not set");
|
||||
let config_path = home_dir()?.join(".config/starship.toml");
|
||||
let config_path_str = config_path.to_str()?.to_owned();
|
||||
@@ -141,11 +145,147 @@ impl Config for Table {
|
||||
|
||||
i64_value
|
||||
}
|
||||
|
||||
/// Get a key from a module's configuration as a vector
|
||||
fn get_as_array(&self, key: &str) -> Option<&Vec<toml::value::Value>> {
|
||||
let value = self.get_config(key)?;
|
||||
let array_value = value.as_array();
|
||||
if array_value.is_none() {
|
||||
log::debug!(
|
||||
"Expected \"{}\" to be a array. Instead received {} of type {}.",
|
||||
key,
|
||||
value,
|
||||
value.type_str()
|
||||
);
|
||||
}
|
||||
array_value
|
||||
}
|
||||
|
||||
/// Get a text key and attempt to interpret it into an ANSI style.
|
||||
fn get_as_ansi_style(&self, key: &str) -> Option<ansi_term::Style> {
|
||||
let style_string = self.get_as_str(key)?;
|
||||
parse_style_string(style_string)
|
||||
}
|
||||
}
|
||||
|
||||
/** Parse a style string which represents an ansi style. Valid tokens in the style
|
||||
string include the following:
|
||||
- 'fg:<color>' (specifies that the color read should be a foreground color)
|
||||
- 'bg:<color>' (specifies that the color read should be a background color)
|
||||
- 'underline'
|
||||
- 'bold'
|
||||
- '<color>' (see the parse_color_string doc for valid color strings)
|
||||
*/
|
||||
fn parse_style_string(style_string: &str) -> Option<ansi_term::Style> {
|
||||
let tokens = style_string.split_whitespace();
|
||||
let mut style = ansi_term::Style::new();
|
||||
|
||||
// If col_fg is true, color the foreground. If it's false, color the background.
|
||||
let mut col_fg: bool;
|
||||
|
||||
for token in tokens {
|
||||
let token = token.to_lowercase();
|
||||
|
||||
// Check for FG/BG identifiers and strip them off if appropriate
|
||||
let token = if token.as_str().starts_with("fg:") {
|
||||
col_fg = true;
|
||||
token.trim_start_matches("fg:").to_owned()
|
||||
} else if token.as_str().starts_with("bg:") {
|
||||
col_fg = false;
|
||||
token.trim_start_matches("bg:").to_owned()
|
||||
} else {
|
||||
col_fg = true; // Bare colors are assumed to color the foreground
|
||||
token
|
||||
};
|
||||
|
||||
match token.as_str() {
|
||||
"underline" => style = style.underline(),
|
||||
"bold" => style = style.bold(),
|
||||
"dimmed" => style = style.dimmed(),
|
||||
"none" => return Some(ansi_term::Style::new()), // Overrides other toks
|
||||
|
||||
// Try to see if this token parses as a valid color string
|
||||
color_string => {
|
||||
// Match found: set either fg or bg color
|
||||
if let Some(ansi_color) = parse_color_string(color_string) {
|
||||
if col_fg {
|
||||
style = style.fg(ansi_color);
|
||||
} else {
|
||||
style = style.on(ansi_color);
|
||||
}
|
||||
} else {
|
||||
// Match failed: skip this token and log it
|
||||
log::debug!("Could not parse token in color string: {}", token)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Some(style)
|
||||
}
|
||||
|
||||
/** Parse a string that represents a color setting, returning None if this fails
|
||||
There are three valid color formats:
|
||||
- #RRGGBB (a hash followed by an RGB hex)
|
||||
- u8 (a number from 0-255, representing an ANSI color)
|
||||
- colstring (one of the 16 predefined color strings)
|
||||
*/
|
||||
fn parse_color_string(color_string: &str) -> Option<ansi_term::Color> {
|
||||
// Parse RGB hex values
|
||||
log::trace!("Parsing color_string: {}", color_string);
|
||||
if color_string.starts_with('#') {
|
||||
log::trace!(
|
||||
"Attempting to read hexadecimal color string: {}",
|
||||
color_string
|
||||
);
|
||||
let r: u8 = u8::from_str_radix(&color_string[1..3], 16).ok()?;
|
||||
let g: u8 = u8::from_str_radix(&color_string[3..5], 16).ok()?;
|
||||
let b: u8 = u8::from_str_radix(&color_string[5..7], 16).ok()?;
|
||||
log::trace!("Read RGB color string: {},{},{}", r, g, b);
|
||||
return Some(Color::RGB(r, g, b));
|
||||
}
|
||||
|
||||
// Parse a u8 (ansi color)
|
||||
if let Result::Ok(ansi_color_num) = color_string.parse::<u8>() {
|
||||
log::trace!("Read ANSI color string: {}", ansi_color_num);
|
||||
return Some(Color::Fixed(ansi_color_num));
|
||||
}
|
||||
|
||||
// Check for any predefined color strings
|
||||
// There are no predefined enums for bright colors, so we use Color::Fixed
|
||||
let predefined_color = match color_string.to_lowercase().as_str() {
|
||||
"black" => Some(Color::Black),
|
||||
"red" => Some(Color::Red),
|
||||
"green" => Some(Color::Green),
|
||||
"yellow" => Some(Color::Yellow),
|
||||
"blue" => Some(Color::Blue),
|
||||
"purple" => Some(Color::Purple),
|
||||
"cyan" => Some(Color::Cyan),
|
||||
"white" => Some(Color::White),
|
||||
"bright-black" => Some(Color::Fixed(8)), // "bright-black" is dark grey
|
||||
"bright-red" => Some(Color::Fixed(9)),
|
||||
"bright-green" => Some(Color::Fixed(10)),
|
||||
"bright-yellow" => Some(Color::Fixed(11)),
|
||||
"bright-blue" => Some(Color::Fixed(12)),
|
||||
"bright-purple" => Some(Color::Fixed(13)),
|
||||
"bright-cyan" => Some(Color::Fixed(14)),
|
||||
"bright-white" => Some(Color::Fixed(15)),
|
||||
_ => None,
|
||||
};
|
||||
|
||||
if predefined_color.is_some() {
|
||||
log::trace!("Read predefined color: {}", color_string);
|
||||
return predefined_color;
|
||||
}
|
||||
|
||||
// All attempts to parse have failed
|
||||
None
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use ansi_term::Style;
|
||||
|
||||
#[test]
|
||||
fn table_get_as_bool() {
|
||||
@@ -194,4 +334,79 @@ mod tests {
|
||||
);
|
||||
assert_eq!(table.get_as_bool("string"), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn table_get_styles_simple() {
|
||||
let mut table = toml::value::Table::new();
|
||||
|
||||
// Test for a bold underline green module (with SiLlY cApS)
|
||||
table.insert(
|
||||
String::from("mystyle"),
|
||||
toml::value::Value::String(String::from("bOlD uNdErLiNe GrEeN")),
|
||||
);
|
||||
assert!(table.get_as_ansi_style("mystyle").unwrap().is_bold);
|
||||
assert!(table.get_as_ansi_style("mystyle").unwrap().is_underline);
|
||||
assert_eq!(
|
||||
table.get_as_ansi_style("mystyle").unwrap(),
|
||||
ansi_term::Style::new().bold().underline().fg(Color::Green)
|
||||
);
|
||||
|
||||
// Test a "plain" style with no formatting
|
||||
table.insert(
|
||||
String::from("plainstyle"),
|
||||
toml::value::Value::String(String::from("")),
|
||||
);
|
||||
assert_eq!(
|
||||
table.get_as_ansi_style("plainstyle").unwrap(),
|
||||
ansi_term::Style::new()
|
||||
);
|
||||
|
||||
// Test a string that's clearly broken
|
||||
table.insert(
|
||||
String::from("broken"),
|
||||
toml::value::Value::String(String::from("djklgfhjkldhlhk;j")),
|
||||
);
|
||||
assert_eq!(
|
||||
table.get_as_ansi_style("broken").unwrap(),
|
||||
ansi_term::Style::new()
|
||||
);
|
||||
|
||||
// Test a string that's nullified by `none`
|
||||
table.insert(
|
||||
String::from("nullified"),
|
||||
toml::value::Value::String(String::from("fg:red bg:green bold none")),
|
||||
);
|
||||
assert_eq!(
|
||||
table.get_as_ansi_style("nullified").unwrap(),
|
||||
ansi_term::Style::new()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn table_get_styles_ordered() {
|
||||
let mut table = toml::value::Table::new();
|
||||
|
||||
// Test a background style with inverted order (also test hex + ANSI)
|
||||
table.insert(
|
||||
String::from("flipstyle"),
|
||||
toml::value::Value::String(String::from("bg:#050505 underline fg:120")),
|
||||
);
|
||||
assert_eq!(
|
||||
table.get_as_ansi_style("flipstyle").unwrap(),
|
||||
Style::new()
|
||||
.underline()
|
||||
.fg(Color::Fixed(120))
|
||||
.on(Color::RGB(5, 5, 5))
|
||||
);
|
||||
|
||||
// Test that the last color style is always the one used
|
||||
table.insert(
|
||||
String::from("multistyle"),
|
||||
toml::value::Value::String(String::from("bg:120 bg:125 bg:127 fg:127 122 125")),
|
||||
);
|
||||
assert_eq!(
|
||||
table.get_as_ansi_style("multistyle").unwrap(),
|
||||
Style::new().fg(Color::Fixed(125)).on(Color::Fixed(127))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
+16
-13
@@ -37,7 +37,7 @@ impl<'a> Context<'a> {
|
||||
/// Identify the current working directory and create an instance of Context
|
||||
/// for it.
|
||||
pub fn new(arguments: ArgMatches) -> Context {
|
||||
// Retreive the "path" flag. If unavailable, use the current directory instead.
|
||||
// Retrieve the "path" flag. If unavailable, use the current directory instead.
|
||||
let path = arguments
|
||||
.value_of("path")
|
||||
.map(From::from)
|
||||
@@ -177,20 +177,20 @@ pub fn path_has_name<'a>(dir_entry: &PathBuf, names: &'a [&'a str]) -> bool {
|
||||
}
|
||||
}
|
||||
|
||||
/// checks if pathbuf matches the extension provided
|
||||
/// checks if pathbuf doesn't start with a dot and matches any provided extension
|
||||
pub fn has_extension<'a>(dir_entry: &PathBuf, extensions: &'a [&'a str]) -> bool {
|
||||
let found_ext = extensions.iter().find(|ext| {
|
||||
dir_entry
|
||||
.extension()
|
||||
.and_then(OsStr::to_str)
|
||||
.unwrap_or_default()
|
||||
== **ext
|
||||
});
|
||||
|
||||
match found_ext {
|
||||
Some(extension) => !extension.is_empty(),
|
||||
None => false,
|
||||
if let Some(file_name) = dir_entry.file_name() {
|
||||
if file_name.to_string_lossy().starts_with('.') {
|
||||
return false;
|
||||
}
|
||||
return extensions.iter().any(|ext| {
|
||||
dir_entry
|
||||
.extension()
|
||||
.and_then(OsStr::to_str)
|
||||
.map_or(false, |e| e == *ext)
|
||||
});
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
fn get_current_branch(repository: &Repository) -> Option<String> {
|
||||
@@ -228,6 +228,9 @@ mod tests {
|
||||
buf.set_file_name("some-file.rs");
|
||||
assert_eq!(has_extension(&buf, &extensions), false);
|
||||
|
||||
buf.set_file_name(".some-file.js");
|
||||
assert_eq!(has_extension(&buf, &extensions), false);
|
||||
|
||||
buf.set_file_name("some-file.js");
|
||||
assert_eq!(has_extension(&buf, &extensions), true)
|
||||
}
|
||||
|
||||
+244
-52
@@ -1,26 +1,92 @@
|
||||
use std::ffi::OsStr;
|
||||
use std::path::Path;
|
||||
use std::{env, io};
|
||||
|
||||
/* We need to send execution time to the prompt for the cmd_duration module. For fish,
|
||||
this is fairly straightforward. For bash and zsh, we'll need to use several
|
||||
shell utilities to get the time, as well as render the prompt */
|
||||
/* We use a two-phase init here: the first phase gives a simple command to the
|
||||
shell. This command evaluates a more complicated script using `source` and
|
||||
process substitution.
|
||||
|
||||
pub fn init(shell_name: &str) {
|
||||
Directly using `eval` on a shell script causes it to be evaluated in
|
||||
a single line, which sucks because things like comments will comment out the
|
||||
rest of the script, and you have to spam semicolons everywhere. By using
|
||||
source and process substitutions, we make it possible to comment and debug
|
||||
the init scripts. */
|
||||
|
||||
fn path_to_starship() -> io::Result<String> {
|
||||
let current_exe = env::current_exe()?
|
||||
.to_str()
|
||||
.ok_or_else(|| io::Error::new(io::ErrorKind::Other, "can't convert to str"))?
|
||||
.to_string();
|
||||
Ok(current_exe)
|
||||
}
|
||||
|
||||
/* This prints the setup stub, the short piece of code which sets up the main
|
||||
init code. The stub produces the main init script, then evaluates it with
|
||||
`source` and process substitution */
|
||||
pub fn init_stub(shell_name: &str) -> io::Result<()> {
|
||||
log::debug!("Shell name: {}", shell_name);
|
||||
|
||||
let shell_basename = Path::new(shell_name).file_stem().and_then(OsStr::to_str);
|
||||
|
||||
let setup_script = match shell_basename {
|
||||
let starship = path_to_starship()?.replace("\"", "\"'\"'\"");
|
||||
|
||||
let setup_stub = match shell_basename {
|
||||
Some("bash") => {
|
||||
let script = BASH_INIT;
|
||||
/*
|
||||
* The standard bash bootstrap is:
|
||||
* `source <(starship init bash --print-full-init)`
|
||||
*
|
||||
* Unfortunately there is an issue with bash 3.2 (the MacOS
|
||||
* default) which prevents this from working. It does not support
|
||||
* `source` with process substitution.
|
||||
*
|
||||
* There are more details here: https://stackoverflow.com/a/32596626
|
||||
*
|
||||
* The workaround for MacOS is to use the `/dev/stdin` trick you
|
||||
* see below. However, there are some systems with emulated POSIX
|
||||
* environments which do not support `/dev/stdin`. For example,
|
||||
* `Git Bash` within `Git for Windows and `Termux` on Android.
|
||||
*
|
||||
* Fortunately, these apps ship with recent-ish versions of bash.
|
||||
* Git Bash is currently shipping bash 4.4 and Termux is shipping
|
||||
* bash 5.0.
|
||||
*
|
||||
* Some testing has suggested that bash 4.0 is also incompatible
|
||||
* with the standard bootstrap, whereas bash 4.1 appears to be
|
||||
* consistently compatible.
|
||||
*
|
||||
* The upshot of all of this, is that we will use the standard
|
||||
* bootstrap whenever the bash version is 4.1 or higher. Otherwise,
|
||||
* we fall back to the `/dev/stdin` solution.
|
||||
*
|
||||
* More background can be found in these pull requests:
|
||||
* https://github.com/starship/starship/pull/241
|
||||
* https://github.com/starship/starship/pull/278
|
||||
*/
|
||||
let script = {
|
||||
format!(
|
||||
r#"if [ "${{BASH_VERSINFO[0]}}" -gt 4 ] || ([ "${{BASH_VERSINFO[0]}}" -eq 4 ] && [ "${{BASH_VERSINFO[1]}}" -ge 1 ])
|
||||
then
|
||||
source <("{}" init bash --print-full-init)
|
||||
else
|
||||
source /dev/stdin <<<"$("{}" init bash --print-full-init)"
|
||||
fi"#,
|
||||
starship, starship
|
||||
)
|
||||
};
|
||||
|
||||
Some(script)
|
||||
}
|
||||
Some("zsh") => {
|
||||
let script = ZSH_INIT;
|
||||
let script = format!("source <(\"{}\" init zsh --print-full-init)", starship);
|
||||
Some(script)
|
||||
}
|
||||
Some("fish") => {
|
||||
let script = FISH_INIT;
|
||||
// Fish does process substitution with pipes and psub instead of bash syntax
|
||||
let script = format!(
|
||||
"source (\"{}\" init fish --print-full-init | psub)",
|
||||
starship
|
||||
);
|
||||
Some(script)
|
||||
}
|
||||
None => {
|
||||
@@ -33,81 +99,207 @@ pub fn init(shell_name: &str) {
|
||||
);
|
||||
None
|
||||
}
|
||||
_ => {
|
||||
/* Calling unwrap() here is fine because the None case will have
|
||||
already matched on the previous arm */
|
||||
Some(shell_basename) => {
|
||||
println!(
|
||||
"printf \"\\n{0} is not yet supported by starship.\\n\
|
||||
For the time being, we support bash, zsh, and fish.\\n\
|
||||
Please open an issue in the starship repo if you would like to \
|
||||
see support for {0}:\\nhttps://github.com/starship/starship/issues/new\"\\n\\n",
|
||||
shell_basename.unwrap()
|
||||
shell_basename
|
||||
);
|
||||
None
|
||||
}
|
||||
};
|
||||
|
||||
if let Some(script) = setup_script {
|
||||
if let Some(script) = setup_stub {
|
||||
print!("{}", script);
|
||||
}
|
||||
};
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/* Bash does not currently support command durations (see issue #124) for details
|
||||
https://github.com/starship/starship/issues/124
|
||||
/* This function (called when `--print-full-init` is passed to `starship init`)
|
||||
prints out the main initialization script */
|
||||
pub fn init_main(shell_name: &str) -> io::Result<()> {
|
||||
let starship_path = path_to_starship()?.replace("\"", "\"'\"'\"");
|
||||
|
||||
let setup_script = match shell_name {
|
||||
"bash" => Some(BASH_INIT.replace("## STARSHIP ##", &format!("\"{}\"", starship_path))),
|
||||
"zsh" => Some(ZSH_INIT.replace("## STARSHIP ##", &format!("\"{}\"", starship_path))),
|
||||
"fish" => Some(FISH_INIT.replace("## STARSHIP ##", &format!("\"{}\"", starship_path))),
|
||||
_ => {
|
||||
println!(
|
||||
"printf \"Shell name detection failed on phase two init.\\n\
|
||||
This probably indicates a bug within starship: please open\\n\
|
||||
an issue at https://github.com/starship/starship/issues/new\\n\""
|
||||
);
|
||||
None
|
||||
}
|
||||
};
|
||||
if let Some(script) = setup_script {
|
||||
print!("{}", script);
|
||||
};
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/* GENERAL INIT SCRIPT NOTES
|
||||
|
||||
Each init script will be passed as-is. Global notes for init scripts are in this
|
||||
comment, with additional per-script comments in the strings themselves.
|
||||
|
||||
JOBS: The argument to `--jobs` is quoted because MacOS's `wc` leaves whitespace
|
||||
in the output. We pass it to starship and do the whitespace removal in Rust,
|
||||
to avoid the cost of an additional shell fork every shell draw.
|
||||
*/
|
||||
|
||||
/* BASH INIT SCRIPT
|
||||
|
||||
We use PROMPT_COMMAND and the DEBUG trap to generate timing information. We try
|
||||
to avoid clobbering what we can, and try to give the user ways around our
|
||||
clobbers, if it's unavoidable.
|
||||
|
||||
A bash quirk is that the DEBUG trap is fired every time a command runs, even
|
||||
if it's later on in the pipeline. If uncorrected, this could cause bad timing
|
||||
data for commands like `slow | slow | fast`, since the timer starts at the start
|
||||
of the "fast" command.
|
||||
|
||||
To solve this, we set a flag `PREEXEC_READY` when the prompt is drawn, and only
|
||||
start the timer if this flag is present. That way, timing is for the entire command,
|
||||
and not just a portion of it
|
||||
*/
|
||||
|
||||
const BASH_INIT: &str = r##"
|
||||
# Will be run before *every* command (even ones in pipes!)
|
||||
starship_preexec() {
|
||||
# Avoid restarting the timer for commands in the same pipeline
|
||||
if [ "$PREEXEC_READY" = "true" ]; then
|
||||
PREEXEC_READY=false
|
||||
STARSHIP_START_TIME=$(date +%s)
|
||||
fi
|
||||
}
|
||||
# Will be run before the prompt is drawn
|
||||
starship_precmd() {
|
||||
PS1="$(starship prompt --status=$? --jobs=$(jobs -p | wc -l))";
|
||||
};
|
||||
PROMPT_COMMAND=starship_precmd;
|
||||
# Save the status, because commands in this pipeline will change $?
|
||||
STATUS=$?
|
||||
|
||||
# Run the bash precmd function, if it's set. If not set, evaluates to no-op
|
||||
"${starship_precmd_user_func-:}"
|
||||
|
||||
# Prepare the timer data, if needed.
|
||||
if [[ $STARSHIP_START_TIME ]]; then
|
||||
STARSHIP_END_TIME=$(date +%s)
|
||||
STARSHIP_DURATION=$((STARSHIP_END_TIME - STARSHIP_START_TIME))
|
||||
PS1="$(## STARSHIP ## prompt --status=$STATUS --jobs="$(jobs -p | wc -l)" --cmd-duration=$STARSHIP_DURATION)"
|
||||
unset STARSHIP_START_TIME
|
||||
else
|
||||
PS1="$(## STARSHIP ## prompt --status=$STATUS --jobs="$(jobs -p | wc -l)")"
|
||||
fi
|
||||
PREEXEC_READY=true; # Signal that we can safely restart the timer
|
||||
}
|
||||
|
||||
# If the user appears to be using https://github.com/rcaloras/bash-preexec,
|
||||
# then hook our functions into their framework.
|
||||
if [[ $preexec_functions ]]; then
|
||||
preexec_functions+=(starship_preexec)
|
||||
precmd_functions+=(starship_precmd)
|
||||
else
|
||||
# We want to avoid destroying an existing DEBUG hook. If we detect one, create
|
||||
# a new function that runs both the existing function AND our function, then
|
||||
# re-trap DEBUG to use this new function. This prevents a trap clobber.
|
||||
dbg_trap="$(trap -p DEBUG | cut -d' ' -f3 | tr -d \')"
|
||||
if [[ -z "$dbg_trap" ]]; then
|
||||
trap starship_preexec DEBUG
|
||||
elif [[ "$dbg_trap" != "starship_preexec" && "$dbg_trap" != "starship_preexec_all" ]]; then
|
||||
function starship_preexec_all(){
|
||||
$dbg_trap; starship_preexec
|
||||
}
|
||||
trap starship_preexec_all DEBUG
|
||||
fi
|
||||
|
||||
# Finally, prepare the precmd function and set up the start time.
|
||||
PROMPT_COMMAND=starship_precmd
|
||||
fi
|
||||
|
||||
# Set up the start time and STARSHIP_SHELL, which controls shell-specific sequences
|
||||
STARSHIP_START_TIME=$(date +%s)
|
||||
export STARSHIP_SHELL="bash"
|
||||
"##;
|
||||
/* TODO: Once warning/error system is implemented in starship, print a warning
|
||||
if starship will not be printing timing due to DEBUG clobber error */
|
||||
|
||||
/* For zsh: preexec_functions and precmd_functions provide preexec/precmd in a
|
||||
way that lets us avoid clobbering them.
|
||||
/* ZSH INIT SCRIPT
|
||||
|
||||
Zsh quirk: preexec() is only fired if a command is actually run (unlike in
|
||||
bash, where spamming empty commands still triggers DEBUG). This means a user
|
||||
spamming ENTER at an empty command line will see increasing runtime (since
|
||||
preexec never actually fires to reset the start time).
|
||||
ZSH has a quirk where `preexec` is only run if a command is actually run (i.e
|
||||
pressing ENTER at an empty command line will not cause preexec to fire). This
|
||||
can cause timing issues, as a user who presses "ENTER" without running a command
|
||||
will see the time to the start of the last command, which may be very large.
|
||||
|
||||
To fix this, only pass the time if STARSHIP_START_TIME is defined, and unset
|
||||
it after passing the time, so that we only measure actual commands.
|
||||
To fix this, we create STARSHIP_START_TIME upon preexec() firing, and destroy it
|
||||
after drawing the prompt. This ensures that the timing for one command is only
|
||||
ever drawn once (for the prompt immediately after it is run).
|
||||
*/
|
||||
|
||||
const ZSH_INIT: &str = r##"
|
||||
zmodload zsh/parameter # Needed to access jobstates variable for NUM_JOBS
|
||||
|
||||
# Will be run before every prompt draw
|
||||
starship_precmd() {
|
||||
STATUS=$?;
|
||||
if [[ $STARSHIP_START_TIME ]]; then
|
||||
STARSHIP_END_TIME="$(date +%s)";
|
||||
STARSHIP_DURATION=$((STARSHIP_END_TIME - STARSHIP_START_TIME));
|
||||
PROMPT="$(starship prompt --status=$STATUS --cmd-duration=$STARSHIP_DURATION --jobs=$(jobs | wc -l))";
|
||||
unset STARSHIP_START_TIME;
|
||||
# Save the status, because commands in this pipeline will change $?
|
||||
STATUS=$?
|
||||
|
||||
# Use length of jobstates array as number of jobs. Expansion fails inside
|
||||
# quotes so we set it here and then use the value later on.
|
||||
NUM_JOBS=$#jobstates
|
||||
# Compute cmd_duration, if we have a time to consume
|
||||
if [[ ! -z "${STARSHIP_START_TIME+1}" ]]; then
|
||||
STARSHIP_END_TIME="$(date +%s)"
|
||||
STARSHIP_DURATION=$((STARSHIP_END_TIME - STARSHIP_START_TIME))
|
||||
PROMPT="$(## STARSHIP ## prompt --status=$STATUS --cmd-duration=$STARSHIP_DURATION --jobs="$NUM_JOBS")"
|
||||
unset STARSHIP_START_TIME
|
||||
else
|
||||
PROMPT="$(starship prompt --status=$STATUS --jobs=$(jobs | wc -l))";
|
||||
PROMPT="$(## STARSHIP ## prompt --status=$STATUS --jobs="$NUM_JOBS")"
|
||||
fi
|
||||
};
|
||||
}
|
||||
starship_preexec(){
|
||||
STARSHIP_START_TIME="$(date +%s)"
|
||||
};
|
||||
}
|
||||
|
||||
# If precmd/preexec arrays are not already set, set them. If we don't do this,
|
||||
# the code to detect whether starship_precmd is already in precmd_functions will
|
||||
# fail because the array doesn't exist (and same for starship_preexec)
|
||||
[[ -z "${precmd_functions+1}" ]] && precmd_functions=()
|
||||
[[ -z "${preexec_functions+1}" ]] && preexec_functions=()
|
||||
|
||||
# If starship precmd/preexec functions are already hooked, don't double-hook them
|
||||
# to avoid unnecessary performance degradation in nested shells
|
||||
if [[ ${precmd_functions[(ie)starship_precmd]} -gt ${#precmd_functions} ]]; then
|
||||
precmd_functions+=(starship_precmd);
|
||||
fi;
|
||||
precmd_functions+=(starship_precmd)
|
||||
fi
|
||||
if [[ ${preexec_functions[(ie)starship_preexec]} -gt ${#preexec_functions} ]]; then
|
||||
preexec_functions+=(starship_preexec);
|
||||
fi;
|
||||
STARSHIP_START_TIME="$(date +%s)";
|
||||
preexec_functions+=(starship_preexec)
|
||||
fi
|
||||
# Set up a function to redraw the prompt if the user switches vi modes
|
||||
function zle-keymap-select
|
||||
{
|
||||
PROMPT=$(## STARSHIP ## prompt --keymap=$KEYMAP --jobs="$(jobs | wc -l)")
|
||||
zle reset-prompt
|
||||
}
|
||||
|
||||
STARSHIP_START_TIME="$(date +%s)"
|
||||
zle -N zle-keymap-select
|
||||
export STARSHIP_SHELL="zsh"
|
||||
"##;
|
||||
|
||||
/* Fish setup is simple because they give us CMD_DURATION. Just account for name
|
||||
changes between 2.7/3.0 and do some math to convert ms->s and we can use it */
|
||||
const FISH_INIT: &str = r##"
|
||||
function fish_prompt;
|
||||
set -l exit_code $status;
|
||||
set -l CMD_DURATION "$CMD_DURATION$cmd_duration";
|
||||
set -l starship_duration (math --scale=0 "$CMD_DURATION / 1000");
|
||||
starship prompt --status=$exit_code --cmd-duration=$starship_duration --jobs=(count (jobs -p));
|
||||
end;
|
||||
function fish_prompt
|
||||
switch "$fish_key_bindings"
|
||||
case fish_hybrid_key_bindings fish_vi_key_bindings
|
||||
set keymap "$fish_bind_mode"
|
||||
case '*'
|
||||
set keymap insert
|
||||
end
|
||||
set -l exit_code $status
|
||||
# Account for changes in variable name between v2.7 and v3.0
|
||||
set -l CMD_DURATION "$CMD_DURATION$cmd_duration"
|
||||
set -l starship_duration (math --scale=0 "$CMD_DURATION / 1000")
|
||||
## STARSHIP ## prompt --status=$exit_code --keymap=$keymap --cmd-duration=$starship_duration --jobs=(count (jobs -p))
|
||||
end
|
||||
function fish_mode_prompt; end
|
||||
export STARSHIP_SHELL="fish"
|
||||
"##;
|
||||
|
||||
+40
-5
@@ -10,6 +10,7 @@ mod print;
|
||||
mod segment;
|
||||
mod utils;
|
||||
|
||||
use crate::module::ALL_MODULES;
|
||||
use clap::{App, AppSettings, Arg, SubCommand};
|
||||
|
||||
fn main() {
|
||||
@@ -43,6 +44,14 @@ fn main() {
|
||||
.help("The execution duration of the last command, in seconds")
|
||||
.takes_value(true);
|
||||
|
||||
let keymap_arg = Arg::with_name("keymap")
|
||||
.short("k")
|
||||
.long("keymap")
|
||||
.value_name("KEYMAP")
|
||||
// fish/zsh only
|
||||
.help("The keymap of fish/zsh")
|
||||
.takes_value(true);
|
||||
|
||||
let jobs_arg = Arg::with_name("jobs")
|
||||
.short("j")
|
||||
.long("jobs")
|
||||
@@ -50,6 +59,10 @@ fn main() {
|
||||
.help("The number of currently running jobs")
|
||||
.takes_value(true);
|
||||
|
||||
let init_scripts_arg = Arg::with_name("print_full_init")
|
||||
.long("print-full-init")
|
||||
.help("Print the main initialization script (as opposed to the init stub)");
|
||||
|
||||
let matches = App::new("starship")
|
||||
.about("The cross-shell prompt for astronauts. ☄🌌️")
|
||||
// pull the version number from Cargo.toml
|
||||
@@ -61,7 +74,8 @@ fn main() {
|
||||
.subcommand(
|
||||
SubCommand::with_name("init")
|
||||
.about("Prints the shell function used to execute starship")
|
||||
.arg(&shell_arg),
|
||||
.arg(&shell_arg)
|
||||
.arg(&init_scripts_arg),
|
||||
)
|
||||
.subcommand(
|
||||
SubCommand::with_name("prompt")
|
||||
@@ -69,6 +83,7 @@ fn main() {
|
||||
.arg(&status_code_arg)
|
||||
.arg(&path_arg)
|
||||
.arg(&cmd_duration_arg)
|
||||
.arg(&keymap_arg)
|
||||
.arg(&jobs_arg),
|
||||
)
|
||||
.subcommand(
|
||||
@@ -77,11 +92,19 @@ fn main() {
|
||||
.arg(
|
||||
Arg::with_name("name")
|
||||
.help("The name of the module to be printed")
|
||||
.required(true),
|
||||
.required(true)
|
||||
.required_unless("list"),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("list")
|
||||
.short("l")
|
||||
.long("list")
|
||||
.help("List out all supported modules"),
|
||||
)
|
||||
.arg(&status_code_arg)
|
||||
.arg(&path_arg)
|
||||
.arg(&cmd_duration_arg)
|
||||
.arg(&keymap_arg)
|
||||
.arg(&jobs_arg),
|
||||
)
|
||||
.get_matches();
|
||||
@@ -89,12 +112,24 @@ fn main() {
|
||||
match matches.subcommand() {
|
||||
("init", Some(sub_m)) => {
|
||||
let shell_name = sub_m.value_of("shell").expect("Shell name missing.");
|
||||
init::init(shell_name)
|
||||
if sub_m.is_present("print_full_init") {
|
||||
init::init_main(shell_name).expect("can't init_main");
|
||||
} else {
|
||||
init::init_stub(shell_name).expect("can't init_stub");
|
||||
}
|
||||
}
|
||||
("prompt", Some(sub_m)) => print::prompt(sub_m.clone()),
|
||||
("module", Some(sub_m)) => {
|
||||
let module_name = sub_m.value_of("name").expect("Module name missing.");
|
||||
print::module(module_name, sub_m.clone());
|
||||
if sub_m.is_present("list") {
|
||||
println!("Supported modules list");
|
||||
println!("----------------------");
|
||||
for modules in ALL_MODULES {
|
||||
println!("{}", modules);
|
||||
}
|
||||
}
|
||||
if let Some(module_name) = sub_m.value_of("name") {
|
||||
print::module(module_name, sub_m.clone());
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
+78
-1
@@ -4,6 +4,29 @@ use ansi_term::Style;
|
||||
use ansi_term::{ANSIString, ANSIStrings};
|
||||
use std::fmt;
|
||||
|
||||
// List of all modules
|
||||
pub const ALL_MODULES: &[&str] = &[
|
||||
#[cfg(feature = "battery")]
|
||||
"battery",
|
||||
"character",
|
||||
"cmd_duration",
|
||||
"directory",
|
||||
"git_branch",
|
||||
"git_state",
|
||||
"git_status",
|
||||
"golang",
|
||||
"hostname",
|
||||
"jobs",
|
||||
"line_break",
|
||||
"nix_shell",
|
||||
"nodejs",
|
||||
"package",
|
||||
"python",
|
||||
"ruby",
|
||||
"rust",
|
||||
"username",
|
||||
];
|
||||
|
||||
/// A module is a collection of segments showing data for a single integration
|
||||
/// (e.g. The git module shows the current git branch and status)
|
||||
pub struct Module<'a> {
|
||||
@@ -79,12 +102,19 @@ impl<'a> Module<'a> {
|
||||
/// Returns a vector of colored ANSIString elements to be later used with
|
||||
/// `ANSIStrings()` to optimize ANSI codes
|
||||
pub fn ansi_strings(&self) -> Vec<ANSIString> {
|
||||
let mut ansi_strings = self
|
||||
let shell = std::env::var("STARSHIP_SHELL").unwrap_or_default();
|
||||
let ansi_strings = self
|
||||
.segments
|
||||
.iter()
|
||||
.map(Segment::ansi_string)
|
||||
.collect::<Vec<ANSIString>>();
|
||||
|
||||
let mut ansi_strings = match shell.as_str() {
|
||||
"bash" => ansi_strings_modified(ansi_strings, shell),
|
||||
"zsh" => ansi_strings_modified(ansi_strings, shell),
|
||||
_ => ansi_strings,
|
||||
};
|
||||
|
||||
ansi_strings.insert(0, self.prefix.ansi_string());
|
||||
ansi_strings.push(self.suffix.ansi_string());
|
||||
|
||||
@@ -109,6 +139,11 @@ impl<'a> Module<'a> {
|
||||
pub fn config_value_bool(&self, key: &str) -> Option<bool> {
|
||||
self.config.and_then(|config| config.get_as_bool(key))
|
||||
}
|
||||
|
||||
/// Get a module's config value as a style
|
||||
pub fn config_value_style(&self, key: &str) -> Option<Style> {
|
||||
self.config.and_then(|config| config.get_as_ansi_style(key))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> fmt::Display for Module<'a> {
|
||||
@@ -118,6 +153,48 @@ impl<'a> fmt::Display for Module<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Many shells cannot deal with raw unprintable characters (like ANSI escape sequences) and
|
||||
/// miscompute the cursor position as a result, leading to strange visual bugs. Here, we wrap these
|
||||
/// characters in shell-specific escape codes to indicate to the shell that they are zero-length.
|
||||
fn ansi_strings_modified(ansi_strings: Vec<ANSIString>, shell: String) -> Vec<ANSIString> {
|
||||
const ESCAPE_BEGIN: char = '\u{1b}';
|
||||
const MAYBE_ESCAPE_END: char = 'm';
|
||||
ansi_strings
|
||||
.iter()
|
||||
.map(|ansi| {
|
||||
let mut escaped = false;
|
||||
let final_string: String = ansi
|
||||
.to_string()
|
||||
.chars()
|
||||
.map(|x| match x {
|
||||
ESCAPE_BEGIN => {
|
||||
escaped = true;
|
||||
match shell.as_str() {
|
||||
"bash" => String::from("\u{5c}\u{5b}\u{1b}"), // => \[ESC
|
||||
"zsh" => String::from("\u{25}\u{7b}\u{1b}"), // => %{ESC
|
||||
_ => x.to_string(),
|
||||
}
|
||||
}
|
||||
MAYBE_ESCAPE_END => {
|
||||
if escaped {
|
||||
escaped = false;
|
||||
match shell.as_str() {
|
||||
"bash" => String::from("m\u{5c}\u{5d}"), // => m\]
|
||||
"zsh" => String::from("m\u{25}\u{7d}"), // => m%}
|
||||
_ => x.to_string(),
|
||||
}
|
||||
} else {
|
||||
x.to_string()
|
||||
}
|
||||
}
|
||||
_ => x.to_string(),
|
||||
})
|
||||
.collect();
|
||||
ANSIString::from(final_string)
|
||||
})
|
||||
.collect::<Vec<ANSIString>>()
|
||||
}
|
||||
|
||||
/// Module affixes are to be used for the prefix or suffix of a module.
|
||||
pub struct Affix {
|
||||
/// The affix's name, to be used in configuration and logging.
|
||||
|
||||
+12
-2
@@ -8,6 +8,13 @@ pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
|
||||
const BATTERY_CHARGING: &str = "⇡";
|
||||
const BATTERY_DISCHARGING: &str = "⇣";
|
||||
const BATTERY_THRESHOLD: f32 = 10.0;
|
||||
// TODO: Update when v1.0 printing refactor is implemented to only
|
||||
// print escapes in a prompt context.
|
||||
let shell = std::env::var("STARSHIP_SHELL").unwrap_or_default();
|
||||
let percentage_char = match shell.as_str() {
|
||||
"zsh" => "%%", // % is an escape in zsh, see PROMPT in `man zshmisc`
|
||||
_ => "%",
|
||||
};
|
||||
|
||||
let battery_status = get_battery_status()?;
|
||||
let BatteryStatus { state, percentage } = battery_status;
|
||||
@@ -23,7 +30,10 @@ pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
|
||||
|
||||
// TODO: Set style based on percentage when threshold is modifiable
|
||||
let mut module = context.new_module("battery")?;
|
||||
module.set_style(Color::Red.bold());
|
||||
let module_style = module
|
||||
.config_value_style("style")
|
||||
.unwrap_or_else(|| Color::Red.bold());
|
||||
module.set_style(module_style);
|
||||
module.get_prefix().set_value("");
|
||||
|
||||
match state {
|
||||
@@ -42,7 +52,7 @@ pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
|
||||
let mut percent_string = Vec::<String>::with_capacity(2);
|
||||
// Round the percentage to a whole number
|
||||
percent_string.push(percentage.round().to_string());
|
||||
percent_string.push("%".to_string());
|
||||
percent_string.push(percentage_char.to_string());
|
||||
module.new_segment("percentage", percent_string.join("").as_ref());
|
||||
|
||||
Some(module)
|
||||
|
||||
@@ -5,37 +5,64 @@ use ansi_term::Color;
|
||||
///
|
||||
/// The character segment prints an arrow character in a color dependant on the exit-
|
||||
/// code of the last executed command:
|
||||
/// - If the exit-code was "0", the arrow will be formatted with `COLOR_SUCCESS`
|
||||
/// - If the exit-code was "0", the arrow will be formatted with `style_success`
|
||||
/// (green by default)
|
||||
/// - If the exit-code was anything else, the arrow will be formatted with
|
||||
/// `COLOR_FAILURE` (red by default)
|
||||
/// `style_failure` (red by default)
|
||||
pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
|
||||
const SUCCESS_CHAR: &str = "➜";
|
||||
const SUCCESS_CHAR: &str = "❯";
|
||||
const FAILURE_CHAR: &str = "✖";
|
||||
let color_success = Color::Green.bold();
|
||||
let color_failure = Color::Red.bold();
|
||||
const VICMD_CHAR: &str = "❮";
|
||||
enum ShellEditMode {
|
||||
Normal,
|
||||
Insert,
|
||||
};
|
||||
const ASSUMED_MODE: ShellEditMode = ShellEditMode::Insert;
|
||||
// TODO: extend config to more modes
|
||||
|
||||
let mut module = context.new_module("character")?;
|
||||
module.get_prefix().set_value("");
|
||||
|
||||
let style_success = module
|
||||
.config_value_style("style_success")
|
||||
.unwrap_or_else(|| Color::Green.bold());
|
||||
let style_failure = module
|
||||
.config_value_style("style_failure")
|
||||
.unwrap_or_else(|| Color::Red.bold());
|
||||
|
||||
let arguments = &context.arguments;
|
||||
let use_symbol = module
|
||||
.config_value_bool("use_symbol_for_status")
|
||||
.unwrap_or(false);
|
||||
let exit_success = arguments.value_of("status_code").unwrap_or("0") == "0";
|
||||
let shell = std::env::var("STARSHIP_SHELL").unwrap_or_default();
|
||||
let keymap = arguments.value_of("keymap").unwrap_or("viins");
|
||||
|
||||
// Match shell "keymap" names to normalized vi modes
|
||||
// NOTE: in vi mode, fish reports normal mode as "default".
|
||||
// Unfortunately, this is also the name of the non-vi default mode.
|
||||
// We do some environment detection in src/init.rs to translate.
|
||||
// The result: in non-vi fish, keymap is always reported as "insert"
|
||||
let mode = match (shell.as_str(), keymap) {
|
||||
("fish", "default") | ("zsh", "vicmd") => ShellEditMode::Normal,
|
||||
_ => ASSUMED_MODE,
|
||||
};
|
||||
|
||||
/* If an error symbol is set in the config, use symbols to indicate
|
||||
success/failure, in addition to color */
|
||||
let symbol = if use_symbol && !exit_success {
|
||||
module.new_segment("error_symbol", FAILURE_CHAR)
|
||||
} else {
|
||||
module.new_segment("symbol", SUCCESS_CHAR)
|
||||
match mode {
|
||||
ShellEditMode::Normal => module.new_segment("vicmd_symbol", VICMD_CHAR),
|
||||
ShellEditMode::Insert => module.new_segment("symbol", SUCCESS_CHAR),
|
||||
}
|
||||
};
|
||||
|
||||
if exit_success {
|
||||
symbol.set_style(color_success.bold());
|
||||
symbol.set_style(style_success);
|
||||
} else {
|
||||
symbol.set_style(color_failure.bold());
|
||||
symbol.set_style(style_failure);
|
||||
};
|
||||
|
||||
Some(module)
|
||||
|
||||
@@ -32,7 +32,9 @@ pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
|
||||
|
||||
let module_color = match elapsed {
|
||||
time if time < config_min => return None,
|
||||
_ => Color::Yellow.bold(),
|
||||
_ => module
|
||||
.config_value_style("style")
|
||||
.unwrap_or_else(|| Color::Yellow.bold()),
|
||||
};
|
||||
|
||||
module.set_style(module_color);
|
||||
|
||||
+93
-12
@@ -8,7 +8,7 @@ use super::{Context, Module};
|
||||
///
|
||||
/// Will perform path contraction and truncation.
|
||||
/// **Contraction**
|
||||
/// - Paths begining with the home directory will be contracted to `~`
|
||||
/// - Paths beginning with the home directory will be contracted to `~`
|
||||
/// - Paths containing a git repo will contract to begin at the repo root
|
||||
///
|
||||
/// **Truncation**
|
||||
@@ -16,33 +16,52 @@ use super::{Context, Module};
|
||||
pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
|
||||
const HOME_SYMBOL: &str = "~";
|
||||
const DIR_TRUNCATION_LENGTH: i64 = 3;
|
||||
let module_color = Color::Cyan.bold();
|
||||
const FISH_STYLE_PWD_DIR_LENGTH: i64 = 0;
|
||||
|
||||
let mut module = context.new_module("directory")?;
|
||||
let module_color = module
|
||||
.config_value_style("style")
|
||||
.unwrap_or_else(|| Color::Cyan.bold());
|
||||
module.set_style(module_color);
|
||||
|
||||
let truncation_length = module
|
||||
.config_value_i64("truncation_length")
|
||||
.unwrap_or(DIR_TRUNCATION_LENGTH);
|
||||
let truncate_to_repo = module.config_value_bool("truncate_to_repo").unwrap_or(true);
|
||||
let fish_style_pwd_dir_length = module
|
||||
.config_value_i64("fish_style_pwd_dir_length")
|
||||
.unwrap_or(FISH_STYLE_PWD_DIR_LENGTH);
|
||||
|
||||
let home_dir = dirs::home_dir().unwrap();
|
||||
let current_dir = &context.current_dir;
|
||||
log::debug!("Current directory: {:?}", current_dir);
|
||||
|
||||
let dir_string;
|
||||
if let Some(repo_root) = &context.repo_root {
|
||||
// Contract the path to the git repo root
|
||||
let repo_folder_name = repo_root.file_name().unwrap().to_str().unwrap();
|
||||
let dir_string = match &context.repo_root {
|
||||
Some(repo_root) if truncate_to_repo => {
|
||||
let repo_folder_name = repo_root.file_name().unwrap().to_str().unwrap();
|
||||
|
||||
dir_string = contract_path(current_dir, repo_root, repo_folder_name);
|
||||
} else {
|
||||
// Contract the path to the git repo root
|
||||
contract_path(current_dir, repo_root, repo_folder_name)
|
||||
}
|
||||
// Contract the path to the home directory
|
||||
let home_dir = dirs::home_dir().unwrap();
|
||||
|
||||
dir_string = contract_path(current_dir, &home_dir, HOME_SYMBOL);
|
||||
}
|
||||
_ => contract_path(current_dir, &home_dir, HOME_SYMBOL),
|
||||
};
|
||||
|
||||
// Truncate the dir string to the maximum number of path components
|
||||
let truncated_dir_string = truncate(dir_string, truncation_length as usize);
|
||||
|
||||
if fish_style_pwd_dir_length > 0 {
|
||||
// If user is using fish style path, we need to add the segment first
|
||||
let contracted_home_dir = contract_path(current_dir, &home_dir, HOME_SYMBOL);
|
||||
let fish_style_dir = to_fish_style(
|
||||
fish_style_pwd_dir_length as usize,
|
||||
contracted_home_dir,
|
||||
&truncated_dir_string,
|
||||
);
|
||||
|
||||
module.new_segment("path", &fish_style_dir);
|
||||
}
|
||||
|
||||
module.new_segment("path", &truncated_dir_string);
|
||||
|
||||
module.get_prefix().set_value("in ");
|
||||
@@ -111,6 +130,38 @@ fn truncate(dir_string: String, length: usize) -> String {
|
||||
truncated_components.join("/")
|
||||
}
|
||||
|
||||
/// Takes part before contracted path and replaces it with fish style path
|
||||
///
|
||||
/// Will take the first letter of each directory before the contracted path and
|
||||
/// use that in the path instead. See the following example.
|
||||
///
|
||||
/// Absolute Path: `/Users/Bob/Projects/work/a_repo`
|
||||
/// Contracted Path: `a_repo`
|
||||
/// With Fish Style: `~/P/w/a_repo`
|
||||
///
|
||||
/// Absolute Path: `/some/Path/not/in_a/repo/but_nested`
|
||||
/// Contracted Path: `in_a/repo/but_nested`
|
||||
/// With Fish Style: `/s/P/n/in_a/repo/but_nested`
|
||||
fn to_fish_style(pwd_dir_length: usize, dir_string: String, truncated_dir_string: &str) -> String {
|
||||
let replaced_dir_string = dir_string.replace(truncated_dir_string, "");
|
||||
let components = replaced_dir_string.split('/').collect::<Vec<&str>>();
|
||||
|
||||
if components.is_empty() {
|
||||
return replaced_dir_string;
|
||||
}
|
||||
|
||||
components
|
||||
.into_iter()
|
||||
.map(|word| match word {
|
||||
"" => "",
|
||||
_ if word.len() <= pwd_dir_length => word,
|
||||
_ if word.starts_with('.') => &word[..=pwd_dir_length],
|
||||
_ => &word[..pwd_dir_length],
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
.join("/")
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
@@ -200,4 +251,34 @@ mod tests {
|
||||
let output = truncate(path.to_string(), 3);
|
||||
assert_eq!(output, "engines/booster/rocket")
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn fish_style_with_user_home_contracted_path() {
|
||||
let path = "~/starship/engines/booster/rocket";
|
||||
let output = to_fish_style(1, path.to_string(), "engines/booster/rocket");
|
||||
assert_eq!(output, "~/s/");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn fish_style_with_user_home_contracted_path_and_dot_dir() {
|
||||
let path = "~/.starship/engines/booster/rocket";
|
||||
let output = to_fish_style(1, path.to_string(), "engines/booster/rocket");
|
||||
assert_eq!(output, "~/.s/");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn fish_style_with_no_contracted_path() {
|
||||
// `truncatation_length = 2`
|
||||
let path = "/absolute/Path/not/in_a/repo/but_nested";
|
||||
let output = to_fish_style(1, path.to_string(), "repo/but_nested");
|
||||
assert_eq!(output, "/a/P/n/i/");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn fish_style_with_pwd_dir_len_no_contracted_path() {
|
||||
// `truncatation_length = 2`
|
||||
let path = "/absolute/Path/not/in_a/repo/but_nested";
|
||||
let output = to_fish_style(2, path.to_string(), "repo/but_nested");
|
||||
assert_eq!(output, "/ab/Pa/no/in/");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
use ansi_term::Color;
|
||||
use unicode_segmentation::UnicodeSegmentation;
|
||||
|
||||
use super::{Context, Module};
|
||||
|
||||
@@ -8,15 +9,56 @@ use super::{Context, Module};
|
||||
pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
|
||||
const GIT_BRANCH_CHAR: &str = " ";
|
||||
|
||||
let branch_name = context.branch_name.as_ref()?;
|
||||
let segment_color = Color::Purple.bold();
|
||||
|
||||
let mut module = context.new_module("git_branch")?;
|
||||
|
||||
let segment_color = module
|
||||
.config_value_style("style")
|
||||
.unwrap_or_else(|| Color::Purple.bold());
|
||||
module.set_style(segment_color);
|
||||
module.get_prefix().set_value("on ");
|
||||
|
||||
let unsafe_truncation_length = module
|
||||
.config_value_i64("truncation_length")
|
||||
.unwrap_or(std::i64::MAX);
|
||||
let truncation_symbol = get_graphemes(
|
||||
module.config_value_str("truncation_symbol").unwrap_or("…"),
|
||||
1,
|
||||
);
|
||||
|
||||
module.new_segment("symbol", GIT_BRANCH_CHAR);
|
||||
module.new_segment("name", branch_name);
|
||||
|
||||
// TODO: Once error handling is implemented, warn the user if their config
|
||||
// truncation length is nonsensical
|
||||
let len = if unsafe_truncation_length <= 0 {
|
||||
log::debug!(
|
||||
"[WARN]: \"truncation_length\" should be a positive value, found {}",
|
||||
unsafe_truncation_length
|
||||
);
|
||||
std::usize::MAX
|
||||
} else {
|
||||
unsafe_truncation_length as usize
|
||||
};
|
||||
let branch_name = context.branch_name.as_ref()?;
|
||||
let truncated_graphemes = get_graphemes(&branch_name, len);
|
||||
// The truncation symbol should only be added if we truncated
|
||||
let truncated_and_symbol = if len < graphemes_len(&branch_name) {
|
||||
truncated_graphemes + &truncation_symbol
|
||||
} else {
|
||||
truncated_graphemes
|
||||
};
|
||||
|
||||
module.new_segment("name", &truncated_and_symbol);
|
||||
|
||||
Some(module)
|
||||
}
|
||||
|
||||
fn get_graphemes(text: &str, length: usize) -> String {
|
||||
UnicodeSegmentation::graphemes(text, true)
|
||||
.take(length)
|
||||
.collect::<Vec<&str>>()
|
||||
.concat()
|
||||
}
|
||||
|
||||
fn graphemes_len(text: &str) -> usize {
|
||||
UnicodeSegmentation::graphemes(&text[..], true).count()
|
||||
}
|
||||
|
||||
@@ -0,0 +1,169 @@
|
||||
use ansi_term::Color;
|
||||
use git2::{Repository, RepositoryState};
|
||||
use std::path::Path;
|
||||
|
||||
use super::{Context, Module};
|
||||
|
||||
/// Creates a module with the state of the git repository at the current directory
|
||||
///
|
||||
/// During a git operation it will show: REBASING, BISECTING, MERGING, etc.
|
||||
/// If the progress information is available (e.g. rebasing 3/10), it will show that too.
|
||||
pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
|
||||
let mut module = context.new_module("git_state")?;
|
||||
|
||||
let repo_root = context.repo_root.as_ref()?;
|
||||
let mut repository = Repository::open(repo_root).ok()?;
|
||||
let state_description = get_state_description(&mut repository);
|
||||
|
||||
if let StateDescription::Clean = state_description {
|
||||
return None;
|
||||
}
|
||||
|
||||
let module_style = module
|
||||
.config_value_style("style")
|
||||
.unwrap_or_else(|| Color::Yellow.bold());
|
||||
module.set_style(module_style);
|
||||
module.get_prefix().set_value("(");
|
||||
module.get_suffix().set_value(") ");
|
||||
|
||||
let label = match state_description {
|
||||
StateDescription::Label(label) => label,
|
||||
StateDescription::LabelAndProgress(label, _) => label,
|
||||
// Should only be possible if you've added a new variant to StateDescription
|
||||
_ => panic!("Expected to have a label at this point in the control flow."),
|
||||
};
|
||||
|
||||
module.new_segment(label.segment_name, label.message_default);
|
||||
|
||||
if let StateDescription::LabelAndProgress(_, progress) = state_description {
|
||||
module.new_segment("progress_current", &format!(" {}", progress.current));
|
||||
module.new_segment("progress_divider", "/");
|
||||
module.new_segment("progress_total", &format!("{}", progress.total));
|
||||
}
|
||||
|
||||
Some(module)
|
||||
}
|
||||
|
||||
static MERGE_LABEL: StateLabel = StateLabel {
|
||||
segment_name: "merge",
|
||||
message_default: "MERGING",
|
||||
};
|
||||
|
||||
static REVERT_LABEL: StateLabel = StateLabel {
|
||||
segment_name: "revert",
|
||||
message_default: "REVERTING",
|
||||
};
|
||||
|
||||
static CHERRY_LABEL: StateLabel = StateLabel {
|
||||
segment_name: "cherry_pick",
|
||||
message_default: "CHERRY-PICKING",
|
||||
};
|
||||
|
||||
static BISECT_LABEL: StateLabel = StateLabel {
|
||||
segment_name: "bisect",
|
||||
message_default: "BISECTING",
|
||||
};
|
||||
|
||||
static AM_LABEL: StateLabel = StateLabel {
|
||||
segment_name: "am",
|
||||
message_default: "AM",
|
||||
};
|
||||
|
||||
static REBASE_LABEL: StateLabel = StateLabel {
|
||||
segment_name: "rebase",
|
||||
message_default: "REBASING",
|
||||
};
|
||||
|
||||
static AM_OR_REBASE_LABEL: StateLabel = StateLabel {
|
||||
segment_name: "am_or_rebase",
|
||||
message_default: "AM/REBASE",
|
||||
};
|
||||
|
||||
fn get_state_description(repository: &mut Repository) -> StateDescription {
|
||||
match repository.state() {
|
||||
RepositoryState::Clean => StateDescription::Clean,
|
||||
RepositoryState::Merge => StateDescription::Label(&MERGE_LABEL),
|
||||
RepositoryState::Revert => StateDescription::Label(&REVERT_LABEL),
|
||||
RepositoryState::RevertSequence => StateDescription::Label(&REVERT_LABEL),
|
||||
RepositoryState::CherryPick => StateDescription::Label(&CHERRY_LABEL),
|
||||
RepositoryState::CherryPickSequence => StateDescription::Label(&CHERRY_LABEL),
|
||||
RepositoryState::Bisect => StateDescription::Label(&BISECT_LABEL),
|
||||
RepositoryState::ApplyMailbox => StateDescription::Label(&AM_LABEL),
|
||||
RepositoryState::ApplyMailboxOrRebase => StateDescription::Label(&AM_OR_REBASE_LABEL),
|
||||
RepositoryState::Rebase => describe_rebase(repository),
|
||||
RepositoryState::RebaseInteractive => describe_rebase(repository),
|
||||
RepositoryState::RebaseMerge => describe_rebase(repository),
|
||||
}
|
||||
}
|
||||
|
||||
fn describe_rebase(repository: &mut Repository) -> StateDescription {
|
||||
/*
|
||||
* Sadly, libgit2 seems to have some issues with reading the state of
|
||||
* interactive rebases. So, instead, we'll poke a few of the .git files
|
||||
* ourselves. This might be worth re-visiting this in the future...
|
||||
*
|
||||
* The following is based heavily on: https://github.com/magicmonty/bash-git-prompt
|
||||
*/
|
||||
|
||||
let just_label = StateDescription::Label(&REBASE_LABEL);
|
||||
|
||||
let dot_git = repository
|
||||
.workdir()
|
||||
.and_then(|d| Some(d.join(Path::new(".git"))));
|
||||
|
||||
let dot_git = match dot_git {
|
||||
None => {
|
||||
// We didn't find the .git directory.
|
||||
// Something very odd is going on. We'll just back away slowly.
|
||||
return just_label;
|
||||
}
|
||||
Some(path) => path,
|
||||
};
|
||||
|
||||
let has_path = |relative_path: &str| {
|
||||
let path = dot_git.join(Path::new(relative_path));
|
||||
path.exists()
|
||||
};
|
||||
|
||||
let file_to_usize = |relative_path: &str| {
|
||||
let path = dot_git.join(Path::new(relative_path));
|
||||
let contents = crate::utils::read_file(path).ok()?;
|
||||
let quantity = contents.trim().parse::<usize>().ok()?;
|
||||
Some(quantity)
|
||||
};
|
||||
|
||||
let paths_to_progress = |current_path: &str, total_path: &str| {
|
||||
let current = file_to_usize(current_path)?;
|
||||
let total = file_to_usize(total_path)?;
|
||||
Some(StateProgress { current, total })
|
||||
};
|
||||
|
||||
let progress = if has_path("rebase-merge") {
|
||||
paths_to_progress("rebase-merge/msgnum", "rebase-merge/end")
|
||||
} else if has_path("rebase-apply") {
|
||||
paths_to_progress("rebase-apply/next", "rebase-apply/last")
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
match progress {
|
||||
None => just_label,
|
||||
Some(progress) => StateDescription::LabelAndProgress(&REBASE_LABEL, progress),
|
||||
}
|
||||
}
|
||||
|
||||
enum StateDescription {
|
||||
Clean,
|
||||
Label(&'static StateLabel),
|
||||
LabelAndProgress(&'static StateLabel, StateProgress),
|
||||
}
|
||||
|
||||
struct StateLabel {
|
||||
segment_name: &'static str,
|
||||
message_default: &'static str,
|
||||
}
|
||||
|
||||
struct StateProgress {
|
||||
current: usize,
|
||||
total: usize,
|
||||
}
|
||||
@@ -34,8 +34,12 @@ pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
|
||||
let repo_root = context.repo_root.as_ref()?;
|
||||
let repository = Repository::open(repo_root).ok()?;
|
||||
|
||||
let module_style = Color::Red.bold();
|
||||
let mut module = context.new_module("git_status")?;
|
||||
let show_sync_count = module.config_value_bool("show_sync_count").unwrap_or(false);
|
||||
let module_style = module
|
||||
.config_value_style("style")
|
||||
.unwrap_or_else(|| Color::Red.bold());
|
||||
|
||||
module.get_prefix().set_value("[").set_style(module_style);
|
||||
module.get_suffix().set_value("] ").set_style(module_style);
|
||||
module.set_style(module_style);
|
||||
@@ -66,12 +70,37 @@ pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
|
||||
|
||||
// Add the ahead/behind segment
|
||||
if let Ok((ahead, behind)) = ahead_behind {
|
||||
let add_ahead = |m: &mut Module<'a>| {
|
||||
m.new_segment("ahead", GIT_STATUS_AHEAD);
|
||||
|
||||
if show_sync_count {
|
||||
m.new_segment("ahead_count", &ahead.to_string());
|
||||
}
|
||||
};
|
||||
|
||||
let add_behind = |m: &mut Module<'a>| {
|
||||
m.new_segment("behind", GIT_STATUS_BEHIND);
|
||||
|
||||
if show_sync_count {
|
||||
m.new_segment("behind_count", &behind.to_string());
|
||||
}
|
||||
};
|
||||
|
||||
if ahead > 0 && behind > 0 {
|
||||
module.new_segment("diverged", GIT_STATUS_DIVERGED);
|
||||
} else if ahead > 0 {
|
||||
module.new_segment("ahead", GIT_STATUS_AHEAD);
|
||||
} else if behind > 0 {
|
||||
module.new_segment("behind", GIT_STATUS_BEHIND);
|
||||
|
||||
if show_sync_count {
|
||||
add_ahead(&mut module);
|
||||
add_behind(&mut module);
|
||||
}
|
||||
}
|
||||
|
||||
if ahead > 0 && behind == 0 {
|
||||
add_ahead(&mut module);
|
||||
}
|
||||
|
||||
if behind > 0 && ahead == 0 {
|
||||
add_behind(&mut module);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -113,7 +142,14 @@ pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
|
||||
/// Gets the bitflags associated with the repo's git status
|
||||
fn get_repo_status(repository: &Repository) -> Result<Status, git2::Error> {
|
||||
let mut status_options = git2::StatusOptions::new();
|
||||
status_options.include_untracked(true);
|
||||
|
||||
match repository.config()?.get_entry("status.showUntrackedFiles") {
|
||||
Ok(entry) => status_options.include_untracked(entry.value() != Some("no")),
|
||||
_ => status_options.include_untracked(true),
|
||||
};
|
||||
status_options.renames_from_rewrites(true);
|
||||
status_options.renames_head_to_index(true);
|
||||
status_options.renames_index_to_workdir(true);
|
||||
|
||||
let repo_file_statuses = repository.statuses(Some(&mut status_options))?;
|
||||
|
||||
|
||||
@@ -28,10 +28,12 @@ pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
|
||||
match get_go_version() {
|
||||
Some(go_version) => {
|
||||
const GO_CHAR: &str = "🐹 ";
|
||||
let module_color = Color::Cyan.bold();
|
||||
|
||||
let mut module = context.new_module("go")?;
|
||||
module.set_style(module_color);
|
||||
let mut module = context.new_module("golang")?;
|
||||
let module_style = module
|
||||
.config_value_style("style")
|
||||
.unwrap_or_else(|| Color::Cyan.bold());
|
||||
module.set_style(module_style);
|
||||
|
||||
let formatted_version = format_go_version(&go_version)?;
|
||||
module.new_segment("symbol", GO_CHAR);
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
use ansi_term::Color;
|
||||
use std::env;
|
||||
|
||||
use super::{Context, Module};
|
||||
use std::ffi::OsString;
|
||||
|
||||
/// Creates a module with the system hostname
|
||||
///
|
||||
/// Will display the hostname if all of the following criteria are met:
|
||||
/// - hostname.disabled is absent or false
|
||||
/// - hostname.ssh_only is false OR the user is currently connected as an SSH session (`$SSH_CONNECTION`)
|
||||
pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
|
||||
let mut module = context.new_module("hostname")?;
|
||||
let module_style = module
|
||||
.config_value_style("style")
|
||||
.unwrap_or_else(|| Color::Green.bold().dimmed());
|
||||
|
||||
let ssh_connection = env::var("SSH_CONNECTION").ok();
|
||||
if module.config_value_bool("ssh_only").unwrap_or(true) && ssh_connection.is_none() {
|
||||
return None;
|
||||
}
|
||||
|
||||
let os_hostname: OsString = gethostname::gethostname();
|
||||
|
||||
let host = match os_hostname.into_string() {
|
||||
Ok(host) => host,
|
||||
Err(bad) => {
|
||||
log::debug!("hostname is not valid UTF!\n{:?}", bad);
|
||||
return None;
|
||||
}
|
||||
};
|
||||
|
||||
let prefix = module.config_value_str("prefix").unwrap_or("").to_owned();
|
||||
let suffix = module.config_value_str("suffix").unwrap_or("").to_owned();
|
||||
|
||||
module.set_style(module_style);
|
||||
module.new_segment("hostname", &format!("{}{}{}", prefix, host, suffix));
|
||||
module.get_prefix().set_value("on ");
|
||||
|
||||
Some(module)
|
||||
}
|
||||
+5
-3
@@ -9,14 +9,16 @@ pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
|
||||
let threshold = module.config_value_i64("threshold").unwrap_or(1);
|
||||
|
||||
const JOB_CHAR: &str = "✦";
|
||||
let module_color = Color::Blue.bold();
|
||||
|
||||
module.set_style(module_color);
|
||||
let module_style = module
|
||||
.config_value_style("style")
|
||||
.unwrap_or_else(|| Color::Blue.bold());
|
||||
module.set_style(module_style);
|
||||
|
||||
let arguments = &context.arguments;
|
||||
let num_of_jobs = arguments
|
||||
.value_of("jobs")
|
||||
.unwrap_or("0")
|
||||
.trim()
|
||||
.parse::<i64>()
|
||||
.ok()?;
|
||||
if num_of_jobs == 0 {
|
||||
|
||||
+22
-7
@@ -1,38 +1,53 @@
|
||||
mod battery;
|
||||
// While adding out new module add out module to src/module.rs ALL_MODULES const array also.
|
||||
mod character;
|
||||
mod cmd_duration;
|
||||
mod directory;
|
||||
mod git_branch;
|
||||
mod git_state;
|
||||
mod git_status;
|
||||
mod golang;
|
||||
mod hostname;
|
||||
mod jobs;
|
||||
mod line_break;
|
||||
mod nix_shell;
|
||||
mod nodejs;
|
||||
mod package;
|
||||
mod python;
|
||||
mod ruby;
|
||||
mod rust;
|
||||
mod username;
|
||||
|
||||
#[cfg(feature = "battery")]
|
||||
mod battery;
|
||||
|
||||
use crate::context::Context;
|
||||
use crate::module::Module;
|
||||
|
||||
pub fn handle<'a>(module: &str, context: &'a Context) -> Option<Module<'a>> {
|
||||
match module {
|
||||
"dir" | "directory" => directory::module(context),
|
||||
"char" | "character" => character::module(context),
|
||||
"node" | "nodejs" => nodejs::module(context),
|
||||
"rust" | "rustlang" => rust::module(context),
|
||||
"directory" => directory::module(context),
|
||||
"character" => character::module(context),
|
||||
"nodejs" => nodejs::module(context),
|
||||
"rust" => rust::module(context),
|
||||
"python" => python::module(context),
|
||||
"go" | "golang" => golang::module(context),
|
||||
"ruby" => ruby::module(context),
|
||||
"golang" => golang::module(context),
|
||||
"line_break" => line_break::module(context),
|
||||
"package" => package::module(context),
|
||||
"git_branch" => git_branch::module(context),
|
||||
"git_state" => git_state::module(context),
|
||||
"git_status" => git_status::module(context),
|
||||
"username" => username::module(context),
|
||||
#[cfg(feature = "battery")]
|
||||
"battery" => battery::module(context),
|
||||
"cmd_duration" => cmd_duration::module(context),
|
||||
"jobs" => jobs::module(context),
|
||||
"nix_shell" => nix_shell::module(context),
|
||||
"hostname" => hostname::module(context),
|
||||
|
||||
_ => panic!("Unknown module: {}", module),
|
||||
_ => {
|
||||
eprintln!("Error: Unknown module {}. Use starship module --list to list out all supported modules.", module);
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
use ansi_term::Color;
|
||||
use std::env;
|
||||
|
||||
use super::{Context, Module};
|
||||
|
||||
// IN_NIX_SHELL should be "pure" or "impure" but lorri uses "1" for "impure"
|
||||
// https://github.com/target/lorri/issues/140
|
||||
|
||||
/// Creates a module showing if inside a nix-shell
|
||||
///
|
||||
/// The module will use the `$IN_NIX_SHELL` and `$name` environment variable to
|
||||
/// determine if it's inside a nix-shell and the name of it.
|
||||
///
|
||||
/// The following options are availables:
|
||||
/// - use_name (bool) // print the name of the nix-shell
|
||||
/// - impure_msg (string) // change the impure msg
|
||||
/// - pure_msg (string) // change the pure msg
|
||||
///
|
||||
/// Will display the following:
|
||||
/// - name (pure) // use_name == true in a pure nix-shell
|
||||
/// - name (impure) // use_name == true in an impure nix-shell
|
||||
/// - pure // use_name == false in a pure nix-shell
|
||||
/// - impure // use_name == false in an impure nix-shell
|
||||
pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
|
||||
let mut module = context.new_module("nix_shell")?;
|
||||
|
||||
env::var("IN_NIX_SHELL")
|
||||
.ok()
|
||||
.and_then(|shell_type| {
|
||||
if shell_type == "1" || shell_type == "impure" {
|
||||
Some(module.config_value_str("impure_msg").unwrap_or("impure"))
|
||||
} else if shell_type == "pure" {
|
||||
Some(module.config_value_str("pure_msg").unwrap_or("pure"))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.map(|shell_type| {
|
||||
if module.config_value_bool("use_name").unwrap_or(false) {
|
||||
match env::var("name").ok() {
|
||||
Some(name) => format!("{} ({})", name, shell_type),
|
||||
None => shell_type.to_string(),
|
||||
}
|
||||
} else {
|
||||
shell_type.to_string()
|
||||
}
|
||||
})
|
||||
.map(|segment| {
|
||||
let module_style = module
|
||||
.config_value_style("style")
|
||||
.unwrap_or_else(|| Color::Red.bold());
|
||||
module.set_style(module_style);
|
||||
module.new_segment("nix_shell", &segment);
|
||||
module
|
||||
})
|
||||
}
|
||||
@@ -24,10 +24,12 @@ pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
|
||||
match get_node_version() {
|
||||
Some(node_version) => {
|
||||
const NODE_CHAR: &str = "⬢ ";
|
||||
let module_color = Color::Green.bold();
|
||||
|
||||
let mut module = context.new_module("node")?;
|
||||
module.set_style(module_color);
|
||||
let mut module = context.new_module("nodejs")?;
|
||||
let module_style = module
|
||||
.config_value_style("style")
|
||||
.unwrap_or_else(|| Color::Green.bold());
|
||||
module.set_style(module_style);
|
||||
|
||||
let formatted_version = node_version.trim();
|
||||
module.new_segment("symbol", NODE_CHAR);
|
||||
|
||||
+52
-12
@@ -12,10 +12,12 @@ pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
|
||||
match get_package_version() {
|
||||
Some(package_version) => {
|
||||
const PACKAGE_CHAR: &str = "📦 ";
|
||||
let module_color = Color::Red.bold();
|
||||
|
||||
let mut module = context.new_module("package")?;
|
||||
module.set_style(module_color);
|
||||
let module_style = module
|
||||
.config_value_style("style")
|
||||
.unwrap_or_else(|| Color::Red.bold());
|
||||
module.set_style(module_style);
|
||||
module.get_prefix().set_value("is ");
|
||||
|
||||
module.new_segment("symbol", PACKAGE_CHAR);
|
||||
@@ -46,18 +48,28 @@ fn extract_package_version(file_contents: &str) -> Option<String> {
|
||||
Some(formatted_version)
|
||||
}
|
||||
|
||||
fn extract_poetry_version(file_contents: &str) -> Option<String> {
|
||||
let poetry_toml: toml::Value = toml::from_str(file_contents).ok()?;
|
||||
let raw_version = poetry_toml
|
||||
.get("tool")?
|
||||
.get("poetry")?
|
||||
.get("version")?
|
||||
.as_str()?;
|
||||
|
||||
let formatted_version = format_version(raw_version);
|
||||
Some(formatted_version)
|
||||
}
|
||||
|
||||
fn get_package_version() -> Option<String> {
|
||||
let cargo_toml = utils::read_file("Cargo.toml");
|
||||
if let Ok(cargo_toml) = cargo_toml {
|
||||
return extract_cargo_version(&cargo_toml);
|
||||
if let Ok(cargo_toml) = utils::read_file("Cargo.toml") {
|
||||
extract_cargo_version(&cargo_toml)
|
||||
} else if let Ok(package_json) = utils::read_file("package.json") {
|
||||
extract_package_version(&package_json)
|
||||
} else if let Ok(poetry_toml) = utils::read_file("pyproject.toml") {
|
||||
extract_poetry_version(&poetry_toml)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
|
||||
let package_json = utils::read_file("package.json");
|
||||
if let Ok(package_json) = package_json {
|
||||
return extract_package_version(&package_json);
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
fn format_version(version: &str) -> String {
|
||||
@@ -123,4 +135,32 @@ mod tests {
|
||||
expected_version
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_extract_poetry_version() {
|
||||
let poetry_with_version = toml::toml! {
|
||||
[tool.poetry]
|
||||
name = "starship"
|
||||
version = "0.1.0"
|
||||
}
|
||||
.to_string();
|
||||
|
||||
let expected_version = Some("v0.1.0".to_string());
|
||||
assert_eq!(
|
||||
extract_poetry_version(&poetry_with_version),
|
||||
expected_version
|
||||
);
|
||||
|
||||
let poetry_without_version = toml::toml! {
|
||||
[tool.poetry]
|
||||
name = "starship"
|
||||
}
|
||||
.to_string();
|
||||
|
||||
let expected_version = None;
|
||||
assert_eq!(
|
||||
extract_poetry_version(&poetry_without_version),
|
||||
expected_version
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
+10
-17
@@ -4,8 +4,6 @@ use std::process::Command;
|
||||
|
||||
use ansi_term::Color;
|
||||
|
||||
use crate::config::Config;
|
||||
|
||||
use super::{Context, Module};
|
||||
|
||||
/// Creates a module with the current Python version
|
||||
@@ -15,10 +13,16 @@ use super::{Context, Module};
|
||||
/// - Current directory contains a `requirements.txt` file
|
||||
/// - Current directory contains a `pyproject.toml` file
|
||||
/// - Current directory contains a file with the `.py` extension
|
||||
/// - Current directory contains a `Pipfile` file
|
||||
pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
|
||||
let is_py_project = context
|
||||
.new_scan_dir()
|
||||
.set_files(&["requirements.txt", ".python-version", "pyproject.toml"])
|
||||
.set_files(&[
|
||||
"requirements.txt",
|
||||
".python-version",
|
||||
"pyproject.toml",
|
||||
"Pipfile",
|
||||
])
|
||||
.set_extensions(&["py"])
|
||||
.scan();
|
||||
|
||||
@@ -32,7 +36,9 @@ pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
|
||||
.unwrap_or(false);
|
||||
|
||||
const PYTHON_CHAR: &str = "🐍 ";
|
||||
let module_color = Color::Yellow.bold();
|
||||
let module_color = module
|
||||
.config_value_style("style")
|
||||
.unwrap_or_else(|| Color::Yellow.bold());
|
||||
module.set_style(module_color);
|
||||
module.new_segment("symbol", PYTHON_CHAR);
|
||||
|
||||
@@ -111,17 +117,4 @@ mod tests {
|
||||
let input = "Python 3.7.2";
|
||||
assert_eq!(format_python_version(input), "v3.7.2");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_no_virtual_env() {
|
||||
env::set_var("VIRTUAL_ENV", "");
|
||||
assert_eq!(get_python_virtual_env(), None)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_virtual_env() {
|
||||
env::set_var("VIRTUAL_ENV", "/foo/bar/my_venv");
|
||||
assert_eq!(get_python_virtual_env().unwrap(), "my_venv")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
use ansi_term::Color;
|
||||
use std::process::Command;
|
||||
|
||||
use super::{Context, Module};
|
||||
|
||||
/// Creates a module with the current Ruby version
|
||||
///
|
||||
/// Will display the Ruby version if any of the following criteria are met:
|
||||
/// - Current directory contains a `.rb` file
|
||||
/// - Current directory contains a `Gemfile` file
|
||||
pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
|
||||
let is_rb_project = context
|
||||
.new_scan_dir()
|
||||
.set_files(&["Gemfile"])
|
||||
.set_extensions(&["rb"])
|
||||
.scan();
|
||||
|
||||
if !is_rb_project {
|
||||
return None;
|
||||
}
|
||||
|
||||
match get_ruby_version() {
|
||||
Some(ruby_version) => {
|
||||
const RUBY_CHAR: &str = "💎 ";
|
||||
|
||||
let mut module = context.new_module("ruby")?;
|
||||
let module_style = module
|
||||
.config_value_style("style")
|
||||
.unwrap_or_else(|| Color::Red.bold());
|
||||
module.set_style(module_style);
|
||||
|
||||
let formatted_version = format_ruby_version(&ruby_version)?;
|
||||
module.new_segment("symbol", RUBY_CHAR);
|
||||
module.new_segment("version", &formatted_version);
|
||||
|
||||
Some(module)
|
||||
}
|
||||
None => None,
|
||||
}
|
||||
}
|
||||
|
||||
fn get_ruby_version() -> Option<String> {
|
||||
match Command::new("ruby").arg("-v").output() {
|
||||
Ok(output) => Some(String::from_utf8(output.stdout).unwrap()),
|
||||
Err(_) => None,
|
||||
}
|
||||
}
|
||||
|
||||
fn format_ruby_version(ruby_version: &str) -> Option<String> {
|
||||
let version = ruby_version
|
||||
// split into ["ruby", "2.6.0p0", "linux/amd64"]
|
||||
.split_whitespace()
|
||||
// return "2.6.0p0"
|
||||
.nth(1)?
|
||||
.get(0..5)?;
|
||||
|
||||
let mut formatted_version = String::with_capacity(version.len() + 1);
|
||||
formatted_version.push('v');
|
||||
formatted_version.push_str(version);
|
||||
Some(formatted_version)
|
||||
}
|
||||
+4
-2
@@ -22,10 +22,12 @@ pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
|
||||
match get_rust_version() {
|
||||
Some(rust_version) => {
|
||||
const RUST_CHAR: &str = "🦀 ";
|
||||
let module_color = Color::Red.bold();
|
||||
|
||||
let mut module = context.new_module("rust")?;
|
||||
module.set_style(module_color);
|
||||
let module_style = module
|
||||
.config_value_style("style")
|
||||
.unwrap_or_else(|| Color::Red.bold());
|
||||
module.set_style(module_style);
|
||||
|
||||
let formatted_version = format_rustc_version(rust_version);
|
||||
module.new_segment("symbol", RUST_CHAR);
|
||||
|
||||
+14
-13
@@ -6,7 +6,7 @@ use super::{Context, Module};
|
||||
|
||||
/// Creates a module with the current user's username
|
||||
///
|
||||
/// Will display the usename if any of the following criteria are met:
|
||||
/// Will display the username if any of the following criteria are met:
|
||||
/// - The current user isn't the same as the one that is logged in (`$LOGNAME` != `$USER`)
|
||||
/// - The current user is root (UID = 0)
|
||||
/// - The user is currently connected as an SSH session (`$SSH_CONNECTION`)
|
||||
@@ -15,11 +15,12 @@ pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
|
||||
let logname = env::var("LOGNAME").ok();
|
||||
let ssh_connection = env::var("SSH_CONNECTION").ok();
|
||||
|
||||
let mut module_color = Color::Yellow.bold();
|
||||
|
||||
if user != logname || ssh_connection.is_some() || is_root(&mut module_color) {
|
||||
const ROOT_UID: Option<u32> = Some(0);
|
||||
let user_uid = get_uid();
|
||||
if user != logname || ssh_connection.is_some() || user_uid == ROOT_UID {
|
||||
let mut module = context.new_module("username")?;
|
||||
module.set_style(module_color);
|
||||
let module_style = get_mod_style(user_uid, &module);
|
||||
module.set_style(module_style);
|
||||
module.new_segment("username", &user?);
|
||||
|
||||
return Some(module);
|
||||
@@ -37,13 +38,13 @@ fn get_uid() -> Option<u32> {
|
||||
}
|
||||
}
|
||||
|
||||
fn is_root(style: &mut Style) -> bool {
|
||||
match get_uid() {
|
||||
Some(uid) if uid == 0 => {
|
||||
style.clone_from(&Color::Red.bold());
|
||||
|
||||
true
|
||||
}
|
||||
_ => false,
|
||||
fn get_mod_style(user_uid: Option<u32>, module: &Module) -> Style {
|
||||
match user_uid {
|
||||
Some(0) => module
|
||||
.config_value_style("style_root")
|
||||
.unwrap_or_else(|| Color::Red.bold()),
|
||||
_ => module
|
||||
.config_value_style("style_user")
|
||||
.unwrap_or_else(|| Color::Yellow.bold()),
|
||||
}
|
||||
}
|
||||
|
||||
+46
-3
@@ -5,21 +5,30 @@ use std::io::{self, Write};
|
||||
use crate::config::Config;
|
||||
use crate::context::Context;
|
||||
use crate::module::Module;
|
||||
use crate::module::ALL_MODULES;
|
||||
use crate::modules;
|
||||
|
||||
const PROMPT_ORDER: &[&str] = &[
|
||||
// List of default prompt order
|
||||
// NOTE: If this const value is changed then Default prompt order subheading inside
|
||||
// prompt heading of config docs needs to be updated according to changes made here.
|
||||
const DEFAULT_PROMPT_ORDER: &[&str] = &[
|
||||
"username",
|
||||
"hostname",
|
||||
"directory",
|
||||
"git_branch",
|
||||
"git_state",
|
||||
"git_status",
|
||||
"package",
|
||||
"nodejs",
|
||||
"ruby",
|
||||
"rust",
|
||||
"python",
|
||||
"go",
|
||||
"golang",
|
||||
"nix_shell",
|
||||
"cmd_duration",
|
||||
"line_break",
|
||||
"jobs",
|
||||
#[cfg(feature = "battery")]
|
||||
"battery",
|
||||
"character",
|
||||
];
|
||||
@@ -36,7 +45,41 @@ pub fn prompt(args: ArgMatches) {
|
||||
writeln!(handle).unwrap();
|
||||
}
|
||||
|
||||
let modules = PROMPT_ORDER
|
||||
let mut prompt_order: Vec<&str> = Vec::new();
|
||||
|
||||
// Write out a custom prompt order
|
||||
if let Some(modules) = config.get_as_array("prompt_order") {
|
||||
// if prompt_order = [] use default_prompt_order
|
||||
if !modules.is_empty() {
|
||||
for module in modules {
|
||||
let str_value = module.as_str();
|
||||
|
||||
if let Some(value) = str_value {
|
||||
if ALL_MODULES.contains(&value) {
|
||||
prompt_order.push(value);
|
||||
} else {
|
||||
log::debug!(
|
||||
"Expected prompt_order to contain value from {:?}. Instead received {}",
|
||||
ALL_MODULES,
|
||||
value,
|
||||
);
|
||||
}
|
||||
} else {
|
||||
log::debug!(
|
||||
"Expected prompt_order to be an array of strings. Instead received {} of type {}",
|
||||
module,
|
||||
module.type_str()
|
||||
);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
prompt_order = DEFAULT_PROMPT_ORDER.to_vec();
|
||||
}
|
||||
} else {
|
||||
prompt_order = DEFAULT_PROMPT_ORDER.to_vec();
|
||||
}
|
||||
|
||||
let modules = &prompt_order
|
||||
.par_iter()
|
||||
.map(|module| modules::handle(module, &context)) // Compute modules
|
||||
.flatten()
|
||||
|
||||
+2
-1
@@ -1,8 +1,9 @@
|
||||
use std::fs::File;
|
||||
use std::io::{Read, Result};
|
||||
use std::path::Path;
|
||||
|
||||
/// Return the string contents of a file
|
||||
pub fn read_file(file_name: &str) -> Result<String> {
|
||||
pub fn read_file<P: AsRef<Path>>(file_name: P) -> Result<String> {
|
||||
let mut file = File::open(file_name)?;
|
||||
let mut data = String::new();
|
||||
|
||||
|
||||
+11
-1
@@ -16,7 +16,7 @@ RUN curl https://raw.githubusercontent.com/creationix/nvm/master/install.sh | ba
|
||||
RUN node --version
|
||||
|
||||
# Install Go
|
||||
ENV GO_VERSION 1.10.0
|
||||
ENV GO_VERSION 1.12.1
|
||||
ENV GOENV_ROOT /home/nonroot/.goenv
|
||||
ENV PATH $GOENV_ROOT/bin:$GOENV_ROOT/shims:$PATH
|
||||
RUN git clone https://github.com/syndbg/goenv.git $GOENV_ROOT \
|
||||
@@ -27,6 +27,16 @@ RUN git clone https://github.com/syndbg/goenv.git $GOENV_ROOT \
|
||||
# Check that Go was correctly installed
|
||||
RUN go version
|
||||
|
||||
# Install Ruby
|
||||
ENV RUBY_VERSION 2.6.3
|
||||
ENV RBENV_ROOT /home/nonroot/.rbenv
|
||||
ENV PATH $RBENV_ROOT/bin:$RBENV_ROOT/shims:$PATH
|
||||
RUN curl -fsSL https://github.com/rbenv/rbenv-installer/raw/master/bin/rbenv-installer | bash \
|
||||
&& rbenv install $RUBY_VERSION \
|
||||
&& rbenv global $RUBY_VERSION
|
||||
# Check that Ruby was correctly installed
|
||||
RUN ruby --version
|
||||
|
||||
# Install Python
|
||||
ENV PYTHON_VERSION 3.6.9
|
||||
ENV PYENV_ROOT /home/nonroot/.pyenv
|
||||
|
||||
Vendored
BIN
Binary file not shown.
@@ -5,7 +5,7 @@ use crate::common::{self, TestCommand};
|
||||
|
||||
#[test]
|
||||
fn char_module_success_status() -> io::Result<()> {
|
||||
let expected = format!("{} ", Color::Green.bold().paint("➜"));
|
||||
let expected = format!("{} ", Color::Green.bold().paint("❯"));
|
||||
|
||||
// Status code 0
|
||||
let output = common::render_module("character")
|
||||
@@ -24,7 +24,7 @@ fn char_module_success_status() -> io::Result<()> {
|
||||
|
||||
#[test]
|
||||
fn char_module_failure_status() -> io::Result<()> {
|
||||
let expected = format!("{} ", Color::Red.bold().paint("➜"));
|
||||
let expected = format!("{} ", Color::Red.bold().paint("❯"));
|
||||
|
||||
let exit_values = ["1", "54321", "-5000"];
|
||||
|
||||
@@ -41,7 +41,7 @@ fn char_module_failure_status() -> io::Result<()> {
|
||||
#[test]
|
||||
fn char_module_symbolyes_status() -> io::Result<()> {
|
||||
let expected_fail = format!("{} ", Color::Red.bold().paint("✖"));
|
||||
let expected_success = format!("{} ", Color::Green.bold().paint("➜"));
|
||||
let expected_success = format!("{} ", Color::Green.bold().paint("❯"));
|
||||
|
||||
let exit_values = ["1", "54321", "-5000"];
|
||||
|
||||
@@ -72,3 +72,79 @@ fn char_module_symbolyes_status() -> io::Result<()> {
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn char_module_zsh_keymap() -> io::Result<()> {
|
||||
let expected_vicmd = "❮";
|
||||
// TODO make this less... well, stupid when ANSI escapes can be mocked out
|
||||
let expected_specified = "I HIGHLY DOUBT THIS WILL SHOW UP IN OTHER OUTPUT";
|
||||
let expected_other = "❯";
|
||||
|
||||
// zle keymap is vicmd
|
||||
let output = common::render_module("character")
|
||||
.env("STARSHIP_SHELL", "zsh")
|
||||
.arg("--keymap=vicmd")
|
||||
.output()?;
|
||||
let actual = String::from_utf8(output.stdout).unwrap();
|
||||
assert!(actual.contains(&expected_vicmd));
|
||||
|
||||
// specified vicmd character
|
||||
let output = common::render_module("character")
|
||||
.use_config(toml::toml! {
|
||||
[character]
|
||||
vicmd_symbol = "I HIGHLY DOUBT THIS WILL SHOW UP IN OTHER OUTPUT"
|
||||
})
|
||||
.env("STARSHIP_SHELL", "zsh")
|
||||
.arg("--keymap=vicmd")
|
||||
.output()?;
|
||||
let actual = String::from_utf8(output.stdout).unwrap();
|
||||
assert!(actual.contains(&expected_specified));
|
||||
|
||||
// zle keymap is other
|
||||
let output = common::render_module("character")
|
||||
.env("STARSHIP_SHELL", "zsh")
|
||||
.arg("--keymap=visual")
|
||||
.output()?;
|
||||
let actual = String::from_utf8(output.stdout).unwrap();
|
||||
assert!(actual.contains(&expected_other));
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn char_module_fish_keymap() -> io::Result<()> {
|
||||
let expected_vicmd = "❮";
|
||||
// TODO make this less... well, stupid when ANSI escapes can be mocked out
|
||||
let expected_specified = "I HIGHLY DOUBT THIS WILL SHOW UP IN OTHER OUTPUT";
|
||||
let expected_other = "❯";
|
||||
|
||||
// fish keymap is default
|
||||
let output = common::render_module("character")
|
||||
.env("STARSHIP_SHELL", "fish")
|
||||
.arg("--keymap=default")
|
||||
.output()?;
|
||||
let actual = String::from_utf8(output.stdout).unwrap();
|
||||
assert!(actual.contains(&expected_vicmd));
|
||||
|
||||
// specified vicmd character
|
||||
let output = common::render_module("character")
|
||||
.use_config(toml::toml! {
|
||||
[character]
|
||||
vicmd_symbol = "I HIGHLY DOUBT THIS WILL SHOW UP IN OTHER OUTPUT"
|
||||
})
|
||||
.env("STARSHIP_SHELL", "fish")
|
||||
.arg("--keymap=default")
|
||||
.output()?;
|
||||
let actual = String::from_utf8(output.stdout).unwrap();
|
||||
assert!(actual.contains(&expected_specified));
|
||||
|
||||
// fish keymap is other
|
||||
let output = common::render_module("character")
|
||||
.env("STARSHIP_SHELL", "fish")
|
||||
.arg("--keymap=visual")
|
||||
.output()?;
|
||||
let actual = String::from_utf8(output.stdout).unwrap();
|
||||
assert!(actual.contains(&expected_other));
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
use ansi_term::Color;
|
||||
use std::fs;
|
||||
use std::io;
|
||||
use std::path::Path;
|
||||
use tempfile::TempDir;
|
||||
|
||||
use crate::common::{self, TestCommand};
|
||||
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
use lazy_static::lazy_static;
|
||||
use std::io::prelude::*;
|
||||
use std::io::{Error, ErrorKind};
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::{io, process};
|
||||
use std::process::Command;
|
||||
use std::{env, fs, io, process};
|
||||
|
||||
lazy_static! {
|
||||
static ref MANIFEST_DIR: &'static Path = Path::new(env!("CARGO_MANIFEST_DIR"));
|
||||
@@ -24,7 +26,8 @@ pub fn render_prompt() -> process::Command {
|
||||
|
||||
/// Render a specific starship module by name
|
||||
pub fn render_module(module_name: &str) -> process::Command {
|
||||
let mut command = process::Command::new("./target/debug/starship");
|
||||
let binary = fs::canonicalize("./target/debug/starship").unwrap();
|
||||
let mut command = process::Command::new(binary);
|
||||
|
||||
command
|
||||
.arg("module")
|
||||
@@ -43,6 +46,41 @@ pub fn new_tempdir() -> io::Result<tempfile::TempDir> {
|
||||
tempfile::tempdir_in("/tmp")
|
||||
}
|
||||
|
||||
/// Create a repo from the fixture to be used in git module tests
|
||||
pub fn create_fixture_repo() -> io::Result<PathBuf> {
|
||||
let fixture_repo_path = new_tempdir()?.path().join("fixture");
|
||||
let repo_path = new_tempdir()?.path().join("rocket");
|
||||
let fixture_path = env::current_dir()?.join("tests/fixtures/rocket.bundle");
|
||||
|
||||
let fixture_repo_dir = path_str(&fixture_repo_path)?;
|
||||
let repo_dir = path_str(&repo_path)?;
|
||||
let fixture = path_str(&fixture_path)?;
|
||||
|
||||
Command::new("git")
|
||||
.args(&["clone", "-b", "master", fixture, fixture_repo_dir])
|
||||
.output()?;
|
||||
|
||||
git2::Repository::clone(fixture_repo_dir, repo_dir).ok();
|
||||
|
||||
Command::new("git")
|
||||
.args(&["config", "--local", "user.email", "starship@example.com"])
|
||||
.current_dir(repo_dir)
|
||||
.output()?;
|
||||
|
||||
Command::new("git")
|
||||
.args(&["config", "--local", "user.name", "starship"])
|
||||
.current_dir(repo_dir)
|
||||
.output()?;
|
||||
|
||||
Ok(repo_path)
|
||||
}
|
||||
|
||||
fn path_str(repo_dir: &PathBuf) -> io::Result<&str> {
|
||||
repo_dir
|
||||
.to_str()
|
||||
.ok_or_else(|| Error::from(ErrorKind::Other))
|
||||
}
|
||||
|
||||
/// Extends `std::process::Command` with methods for testing
|
||||
pub trait TestCommand {
|
||||
fn use_config(&mut self, toml: toml::value::Value) -> &mut process::Command;
|
||||
|
||||
+229
-12
@@ -10,7 +10,13 @@ use crate::common::{self, TestCommand};
|
||||
|
||||
#[test]
|
||||
fn home_directory() -> io::Result<()> {
|
||||
let output = common::render_module("dir").arg("--path=~").output()?;
|
||||
let output = common::render_module("directory")
|
||||
.arg("--path=~")
|
||||
.use_config(toml::toml! { // Necessary if homedir is a git repo
|
||||
[directory]
|
||||
truncate_to_repo = false
|
||||
})
|
||||
.output()?;
|
||||
let actual = String::from_utf8(output.stdout).unwrap();
|
||||
|
||||
let expected = format!("in {} ", Color::Cyan.bold().paint("~"));
|
||||
@@ -24,7 +30,7 @@ fn directory_in_home() -> io::Result<()> {
|
||||
let dir = home_dir().unwrap().join("starship/engine");
|
||||
fs::create_dir_all(&dir)?;
|
||||
|
||||
let output = common::render_module("dir")
|
||||
let output = common::render_module("directory")
|
||||
.arg("--path")
|
||||
.arg(dir)
|
||||
.output()?;
|
||||
@@ -41,7 +47,7 @@ fn truncated_directory_in_home() -> io::Result<()> {
|
||||
let dir = home_dir().unwrap().join("starship/engine/schematics");
|
||||
fs::create_dir_all(&dir)?;
|
||||
|
||||
let output = common::render_module("dir")
|
||||
let output = common::render_module("directory")
|
||||
.arg("--path")
|
||||
.arg(dir)
|
||||
.output()?;
|
||||
@@ -55,9 +61,33 @@ fn truncated_directory_in_home() -> io::Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore]
|
||||
fn fish_directory_in_home() -> io::Result<()> {
|
||||
let dir = home_dir().unwrap().join("starship/engine/schematics");
|
||||
fs::create_dir_all(&dir)?;
|
||||
|
||||
let output = common::render_module("directory")
|
||||
.use_config(toml::toml! {
|
||||
[directory]
|
||||
truncation_length = 1
|
||||
fish_style_pwd_dir_length = 2
|
||||
})
|
||||
.arg("--path")
|
||||
.arg(dir)
|
||||
.output()?;
|
||||
let actual = String::from_utf8(output.stdout).unwrap();
|
||||
|
||||
let expected = format!("in {} ", Color::Cyan.bold().paint("~/st/en/schematics"));
|
||||
assert_eq!(expected, actual);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn root_directory() -> io::Result<()> {
|
||||
let output = common::render_module("dir").arg("--path=/").output()?;
|
||||
let output = common::render_module("directory")
|
||||
.arg("--path=/")
|
||||
.output()?;
|
||||
let actual = String::from_utf8(output.stdout).unwrap();
|
||||
|
||||
let expected = format!("in {} ", Color::Cyan.bold().paint("/"));
|
||||
@@ -66,11 +96,25 @@ fn root_directory() -> io::Result<()> {
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
fn directory_in_root() -> io::Result<()> {
|
||||
let output = common::render_module("dir").arg("--path=/usr").output()?;
|
||||
let output = common::render_module("directory")
|
||||
.arg("--path=/etc")
|
||||
.output()?;
|
||||
let actual = String::from_utf8(output.stdout).unwrap();
|
||||
|
||||
let expected = format!("in {} ", Color::Cyan.bold().paint("/usr"));
|
||||
let expected = format!("in {} ", Color::Cyan.bold().paint("/etc"));
|
||||
assert_eq!(expected, actual);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(target_os = "windows")]
|
||||
fn directory_in_root() -> io::Result<()> {
|
||||
let output = common::render_module("dir").arg("--path=C:\\").output()?;
|
||||
let actual = String::from_utf8(output.stdout).unwrap();
|
||||
|
||||
let expected = format!("in {} ", Color::Cyan.bold().paint("/c"));
|
||||
assert_eq!(expected, actual);
|
||||
Ok(())
|
||||
}
|
||||
@@ -81,7 +125,7 @@ fn truncated_directory_in_root() -> io::Result<()> {
|
||||
let dir = Path::new("/tmp/starship/thrusters/rocket");
|
||||
fs::create_dir_all(&dir)?;
|
||||
|
||||
let output = common::render_module("dir")
|
||||
let output = common::render_module("directory")
|
||||
.arg("--path")
|
||||
.arg(dir)
|
||||
.output()?;
|
||||
@@ -101,7 +145,7 @@ fn truncated_directory_config_large() -> io::Result<()> {
|
||||
let dir = Path::new("/tmp/starship/thrusters/rocket");
|
||||
fs::create_dir_all(&dir)?;
|
||||
|
||||
let output = common::render_module("dir")
|
||||
let output = common::render_module("directory")
|
||||
.use_config(toml::toml! {
|
||||
[directory]
|
||||
truncation_length = 100
|
||||
@@ -119,13 +163,38 @@ fn truncated_directory_config_large() -> io::Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore]
|
||||
fn fish_style_directory_config_large() -> io::Result<()> {
|
||||
let dir = Path::new("/tmp/starship/thrusters/rocket");
|
||||
fs::create_dir_all(&dir)?;
|
||||
|
||||
let output = common::render_module("directory")
|
||||
.use_config(toml::toml! {
|
||||
[directory]
|
||||
truncation_length = 1
|
||||
fish_style_pwd_dir_length = 100
|
||||
})
|
||||
.arg("--path")
|
||||
.arg(dir)
|
||||
.output()?;
|
||||
let actual = String::from_utf8(output.stdout).unwrap();
|
||||
|
||||
let expected = format!(
|
||||
"in {} ",
|
||||
Color::Cyan.bold().paint("/tmp/starship/thrusters/rocket")
|
||||
);
|
||||
assert_eq!(expected, actual);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore]
|
||||
fn truncated_directory_config_small() -> io::Result<()> {
|
||||
let dir = Path::new("/tmp/starship/thrusters/rocket");
|
||||
fs::create_dir_all(&dir)?;
|
||||
|
||||
let output = common::render_module("dir")
|
||||
let output = common::render_module("directory")
|
||||
.use_config(toml::toml! {
|
||||
[directory]
|
||||
truncation_length = 2
|
||||
@@ -140,6 +209,28 @@ fn truncated_directory_config_small() -> io::Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore]
|
||||
fn fish_directory_config_small() -> io::Result<()> {
|
||||
let dir = Path::new("/tmp/starship/thrusters/rocket");
|
||||
fs::create_dir_all(&dir)?;
|
||||
|
||||
let output = common::render_module("directory")
|
||||
.use_config(toml::toml! {
|
||||
[directory]
|
||||
truncation_length = 2
|
||||
fish_style_pwd_dir_length = 1
|
||||
})
|
||||
.arg("--path")
|
||||
.arg(dir)
|
||||
.output()?;
|
||||
let actual = String::from_utf8(output.stdout).unwrap();
|
||||
|
||||
let expected = format!("in {} ", Color::Cyan.bold().paint("/t/s/thrusters/rocket"));
|
||||
assert_eq!(expected, actual);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore]
|
||||
fn git_repo_root() -> io::Result<()> {
|
||||
@@ -151,7 +242,7 @@ fn git_repo_root() -> io::Result<()> {
|
||||
fs::create_dir(&repo_dir)?;
|
||||
Repository::init(&repo_dir).unwrap();
|
||||
|
||||
let output = common::render_module("dir")
|
||||
let output = common::render_module("directory")
|
||||
.arg("--path")
|
||||
.arg(repo_dir)
|
||||
.output()?;
|
||||
@@ -171,7 +262,7 @@ fn directory_in_git_repo() -> io::Result<()> {
|
||||
fs::create_dir_all(&dir)?;
|
||||
Repository::init(&repo_dir).unwrap();
|
||||
|
||||
let output = common::render_module("dir")
|
||||
let output = common::render_module("directory")
|
||||
.arg("--path")
|
||||
.arg(dir)
|
||||
.output()?;
|
||||
@@ -191,7 +282,7 @@ fn truncated_directory_in_git_repo() -> io::Result<()> {
|
||||
fs::create_dir_all(&dir)?;
|
||||
Repository::init(&repo_dir).unwrap();
|
||||
|
||||
let output = common::render_module("dir")
|
||||
let output = common::render_module("directory")
|
||||
.arg("--path")
|
||||
.arg(dir)
|
||||
.output()?;
|
||||
@@ -201,3 +292,129 @@ fn truncated_directory_in_git_repo() -> io::Result<()> {
|
||||
assert_eq!(expected, actual);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore]
|
||||
fn directory_in_git_repo_truncate_to_repo_false() -> io::Result<()> {
|
||||
let tmp_dir = TempDir::new_in(dirs::home_dir().unwrap())?;
|
||||
let repo_dir = tmp_dir.path().join("above-repo").join("rocket-controls");
|
||||
let dir = repo_dir.join("src/meters/fuel-gauge");
|
||||
fs::create_dir_all(&dir)?;
|
||||
Repository::init(&repo_dir).unwrap();
|
||||
|
||||
let output = common::render_module("directory")
|
||||
.use_config(toml::toml! {
|
||||
[directory]
|
||||
// Don't truncate the path at all.
|
||||
truncation_length = 5
|
||||
truncate_to_repo = false
|
||||
})
|
||||
.arg("--path")
|
||||
.arg(dir)
|
||||
.output()?;
|
||||
let actual = String::from_utf8(output.stdout).unwrap();
|
||||
|
||||
let expected = format!(
|
||||
"in {} ",
|
||||
Color::Cyan
|
||||
.bold()
|
||||
.paint("above-repo/rocket-controls/src/meters/fuel-gauge")
|
||||
);
|
||||
assert_eq!(expected, actual);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore]
|
||||
fn fish_path_directory_in_git_repo_truncate_to_repo_false() -> io::Result<()> {
|
||||
let tmp_dir = TempDir::new_in(dirs::home_dir().unwrap())?;
|
||||
let repo_dir = tmp_dir.path().join("above-repo").join("rocket-controls");
|
||||
let dir = repo_dir.join("src/meters/fuel-gauge");
|
||||
fs::create_dir_all(&dir)?;
|
||||
Repository::init(&repo_dir).unwrap();
|
||||
|
||||
let output = common::render_module("directory")
|
||||
.use_config(toml::toml! {
|
||||
[directory]
|
||||
// Don't truncate the path at all.
|
||||
truncation_length = 5
|
||||
truncate_to_repo = false
|
||||
fish_style_pwd_dir_length = 1
|
||||
})
|
||||
.arg("--path")
|
||||
.arg(dir)
|
||||
.output()?;
|
||||
let actual = String::from_utf8(output.stdout).unwrap();
|
||||
|
||||
let expected = format!(
|
||||
"in {} ",
|
||||
Color::Cyan
|
||||
.bold()
|
||||
.paint("~/.t/above-repo/rocket-controls/src/meters/fuel-gauge")
|
||||
);
|
||||
assert_eq!(expected, actual);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore]
|
||||
fn fish_path_directory_in_git_repo_truncate_to_repo_true() -> io::Result<()> {
|
||||
let tmp_dir = TempDir::new_in(dirs::home_dir().unwrap())?;
|
||||
let repo_dir = tmp_dir.path().join("above-repo").join("rocket-controls");
|
||||
let dir = repo_dir.join("src/meters/fuel-gauge");
|
||||
fs::create_dir_all(&dir)?;
|
||||
Repository::init(&repo_dir).unwrap();
|
||||
|
||||
let output = common::render_module("directory")
|
||||
.use_config(toml::toml! {
|
||||
[directory]
|
||||
// `truncate_to_repo = true` should display the truncated path
|
||||
truncation_length = 5
|
||||
truncate_to_repo = true
|
||||
fish_style_pwd_dir_length = 1
|
||||
})
|
||||
.arg("--path")
|
||||
.arg(dir)
|
||||
.output()?;
|
||||
let actual = String::from_utf8(output.stdout).unwrap();
|
||||
|
||||
let expected = format!(
|
||||
"in {} ",
|
||||
Color::Cyan
|
||||
.bold()
|
||||
.paint("~/.t/a/rocket-controls/src/meters/fuel-gauge")
|
||||
);
|
||||
assert_eq!(expected, actual);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore]
|
||||
fn directory_in_git_repo_truncate_to_repo_true() -> io::Result<()> {
|
||||
let tmp_dir = TempDir::new_in(dirs::home_dir().unwrap())?;
|
||||
let repo_dir = tmp_dir.path().join("above-repo").join("rocket-controls");
|
||||
let dir = repo_dir.join("src/meters/fuel-gauge");
|
||||
fs::create_dir_all(&dir)?;
|
||||
Repository::init(&repo_dir).unwrap();
|
||||
|
||||
let output = common::render_module("directory")
|
||||
.use_config(toml::toml! {
|
||||
[directory]
|
||||
// `truncate_to_repo = true` should display the truncated path
|
||||
truncation_length = 5
|
||||
truncate_to_repo = true
|
||||
})
|
||||
.arg("--path")
|
||||
.arg(dir)
|
||||
.output()?;
|
||||
let actual = String::from_utf8(output.stdout).unwrap();
|
||||
|
||||
let expected = format!(
|
||||
"in {} ",
|
||||
Color::Cyan
|
||||
.bold()
|
||||
.paint("rocket-controls/src/meters/fuel-gauge")
|
||||
);
|
||||
assert_eq!(expected, actual);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -0,0 +1,141 @@
|
||||
use ansi_term::Color;
|
||||
use git2::Repository;
|
||||
use std::env;
|
||||
use std::io;
|
||||
use std::process::Command;
|
||||
|
||||
use crate::common::{self, TestCommand};
|
||||
|
||||
#[test]
|
||||
fn test_changed_truncation_symbol() -> io::Result<()> {
|
||||
test_truncate_length_with_config(
|
||||
"1337_hello_world",
|
||||
15,
|
||||
"1337_hello_worl",
|
||||
"%",
|
||||
"truncation_symbol = \"%\"",
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_no_truncation_symbol() -> io::Result<()> {
|
||||
test_truncate_length_with_config(
|
||||
"1337_hello_world",
|
||||
15,
|
||||
"1337_hello_worl",
|
||||
"",
|
||||
"truncation_symbol = \"\"",
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_multi_char_truncation_symbol() -> io::Result<()> {
|
||||
test_truncate_length_with_config(
|
||||
"1337_hello_world",
|
||||
15,
|
||||
"1337_hello_worl",
|
||||
"a",
|
||||
"truncation_symbol = \"apple\"",
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_ascii_boundary_below() -> io::Result<()> {
|
||||
test_truncate_length("1337_hello_world", 15, "1337_hello_worl", "…")
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_ascii_boundary_on() -> io::Result<()> {
|
||||
test_truncate_length("1337_hello_world", 16, "1337_hello_world", "")
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_ascii_boundary_above() -> io::Result<()> {
|
||||
test_truncate_length("1337_hello_world", 17, "1337_hello_world", "")
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_one() -> io::Result<()> {
|
||||
test_truncate_length("1337_hello_world", 1, "1", "…")
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_zero() -> io::Result<()> {
|
||||
test_truncate_length("1337_hello_world", 0, "1337_hello_world", "")
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_negative() -> io::Result<()> {
|
||||
test_truncate_length("1337_hello_world", -1, "1337_hello_world", "")
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_hindi_truncation() -> io::Result<()> {
|
||||
test_truncate_length("नमस्ते", 3, "नमस्", "…")
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_hindi_truncation2() -> io::Result<()> {
|
||||
test_truncate_length("नमस्त", 3, "नमस्", "…")
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_japanese_truncation() -> io::Result<()> {
|
||||
test_truncate_length("がんばってね", 4, "がんばっ", "…")
|
||||
}
|
||||
|
||||
fn test_truncate_length(
|
||||
branch_name: &str,
|
||||
truncate_length: i64,
|
||||
expected_name: &str,
|
||||
truncation_symbol: &str,
|
||||
) -> io::Result<()> {
|
||||
test_truncate_length_with_config(
|
||||
branch_name,
|
||||
truncate_length,
|
||||
expected_name,
|
||||
truncation_symbol,
|
||||
"",
|
||||
)
|
||||
}
|
||||
|
||||
fn test_truncate_length_with_config(
|
||||
branch_name: &str,
|
||||
truncate_length: i64,
|
||||
expected_name: &str,
|
||||
truncation_symbol: &str,
|
||||
config_options: &str,
|
||||
) -> io::Result<()> {
|
||||
let repo_dir = common::create_fixture_repo()?;
|
||||
|
||||
Command::new("git")
|
||||
.args(&["checkout", "-b", branch_name])
|
||||
.current_dir(repo_dir.as_path())
|
||||
.output()?;
|
||||
|
||||
let output = common::render_module("git_branch")
|
||||
.use_config(
|
||||
toml::from_str(&format!(
|
||||
"
|
||||
[git_branch]
|
||||
truncation_length = {}
|
||||
{}
|
||||
",
|
||||
truncate_length, config_options
|
||||
))
|
||||
.unwrap(),
|
||||
)
|
||||
.arg("--path")
|
||||
.arg(repo_dir)
|
||||
.output()?;
|
||||
let actual = String::from_utf8(output.stdout).unwrap();
|
||||
|
||||
let expected = format!(
|
||||
"on {} ",
|
||||
Color::Purple
|
||||
.bold()
|
||||
.paint(format!("\u{e0a0} {}{}", expected_name, truncation_symbol)),
|
||||
);
|
||||
assert_eq!(expected, actual);
|
||||
Ok(())
|
||||
}
|
||||
@@ -0,0 +1,177 @@
|
||||
use super::common;
|
||||
use std::ffi::OsStr;
|
||||
use std::fs::OpenOptions;
|
||||
use std::io::{self, Error, ErrorKind, Write};
|
||||
use std::process::{Command, Stdio};
|
||||
|
||||
#[test]
|
||||
#[ignore]
|
||||
fn shows_rebasing() -> io::Result<()> {
|
||||
let repo_dir = create_repo_with_conflict()?;
|
||||
let path = path_str(&repo_dir)?;
|
||||
|
||||
run_git_cmd(&["rebase", "other-branch"], Some(path), false)?;
|
||||
|
||||
let output = common::render_module("git_state")
|
||||
.current_dir(path)
|
||||
.output()?;
|
||||
let text = String::from_utf8(output.stdout).unwrap();
|
||||
assert!(text.contains("REBASING 1/1"));
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore]
|
||||
fn shows_merging() -> io::Result<()> {
|
||||
let repo_dir = create_repo_with_conflict()?;
|
||||
let path = path_str(&repo_dir)?;
|
||||
|
||||
run_git_cmd(&["merge", "other-branch"], Some(path), false)?;
|
||||
|
||||
let output = common::render_module("git_state")
|
||||
.current_dir(path)
|
||||
.output()?;
|
||||
let text = String::from_utf8(output.stdout).unwrap();
|
||||
assert!(text.contains("MERGING"));
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore]
|
||||
fn shows_cherry_picking() -> io::Result<()> {
|
||||
let repo_dir = create_repo_with_conflict()?;
|
||||
let path = path_str(&repo_dir)?;
|
||||
|
||||
run_git_cmd(&["cherry-pick", "other-branch"], Some(path), false)?;
|
||||
|
||||
let output = common::render_module("git_state")
|
||||
.current_dir(path)
|
||||
.output()?;
|
||||
let text = String::from_utf8(output.stdout).unwrap();
|
||||
assert!(text.contains("CHERRY-PICKING"));
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore]
|
||||
fn shows_bisecting() -> io::Result<()> {
|
||||
let repo_dir = create_repo_with_conflict()?;
|
||||
let path = path_str(&repo_dir)?;
|
||||
|
||||
run_git_cmd(&["bisect", "start"], Some(path), false)?;
|
||||
|
||||
let output = common::render_module("git_state")
|
||||
.current_dir(path)
|
||||
.output()?;
|
||||
let text = String::from_utf8(output.stdout).unwrap();
|
||||
assert!(text.contains("BISECTING"));
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore]
|
||||
fn shows_reverting() -> io::Result<()> {
|
||||
let repo_dir = create_repo_with_conflict()?;
|
||||
let path = path_str(&repo_dir)?;
|
||||
|
||||
run_git_cmd(&["revert", "--no-commit", "HEAD~1"], Some(path), false)?;
|
||||
|
||||
let output = common::render_module("git_state")
|
||||
.current_dir(path)
|
||||
.output()?;
|
||||
let text = String::from_utf8(output.stdout).unwrap();
|
||||
assert!(text.contains("REVERTING"));
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn run_git_cmd<A, S>(args: A, dir: Option<&str>, expect_ok: bool) -> io::Result<()>
|
||||
where
|
||||
A: IntoIterator<Item = S>,
|
||||
S: AsRef<OsStr>,
|
||||
{
|
||||
let mut command = Command::new("git");
|
||||
command
|
||||
.args(args)
|
||||
.stdout(Stdio::null())
|
||||
.stderr(Stdio::null())
|
||||
.stdin(Stdio::null());
|
||||
|
||||
if let Some(dir) = dir {
|
||||
command.current_dir(dir);
|
||||
}
|
||||
|
||||
let status = command.status()?;
|
||||
|
||||
if expect_ok && !status.success() {
|
||||
Err(Error::from(ErrorKind::Other))
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
fn create_repo_with_conflict() -> io::Result<tempfile::TempDir> {
|
||||
let repo_dir = common::new_tempdir()?;
|
||||
let path = path_str(&repo_dir)?;
|
||||
let conflicted_file = repo_dir.path().join("the_file");
|
||||
|
||||
let write_file = |text: &str| {
|
||||
let mut file = OpenOptions::new()
|
||||
.write(true)
|
||||
.create(true)
|
||||
.truncate(true)
|
||||
.open(&conflicted_file)?;
|
||||
write!(file, "{}", text)
|
||||
};
|
||||
|
||||
// Initialise a new git repo
|
||||
run_git_cmd(&["init", "--quiet", path], None, true)?;
|
||||
|
||||
// Set local author info
|
||||
run_git_cmd(
|
||||
&["config", "--local", "user.email", "starship@example.com"],
|
||||
Some(path),
|
||||
true,
|
||||
)?;
|
||||
run_git_cmd(
|
||||
&["config", "--local", "user.name", "starship"],
|
||||
Some(path),
|
||||
true,
|
||||
)?;
|
||||
|
||||
// Write a file on master and commit it
|
||||
write_file("Version A")?;
|
||||
run_git_cmd(&["add", "the_file"], Some(path), true)?;
|
||||
run_git_cmd(&["commit", "--message", "Commit A"], Some(path), true)?;
|
||||
|
||||
// Switch to another branch, and commit a change to the file
|
||||
run_git_cmd(&["checkout", "-b", "other-branch"], Some(path), true)?;
|
||||
write_file("Version B")?;
|
||||
run_git_cmd(
|
||||
&["commit", "--all", "--message", "Commit B"],
|
||||
Some(path),
|
||||
true,
|
||||
)?;
|
||||
|
||||
// Switch back to master, and commit a third change to the file
|
||||
run_git_cmd(&["checkout", "master"], Some(path), true)?;
|
||||
write_file("Version C")?;
|
||||
run_git_cmd(
|
||||
&["commit", "--all", "--message", "Commit C"],
|
||||
Some(path),
|
||||
true,
|
||||
)?;
|
||||
|
||||
Ok(repo_dir)
|
||||
}
|
||||
|
||||
fn path_str(repo_dir: &tempfile::TempDir) -> io::Result<&str> {
|
||||
repo_dir
|
||||
.path()
|
||||
.to_str()
|
||||
.ok_or_else(|| Error::from(ErrorKind::Other))
|
||||
}
|
||||
@@ -0,0 +1,374 @@
|
||||
use ansi_term::Color;
|
||||
use git2::Repository;
|
||||
use std::env;
|
||||
use std::fs::{self, File};
|
||||
use std::io;
|
||||
use std::process::Command;
|
||||
|
||||
use crate::common::{self, TestCommand};
|
||||
|
||||
#[test]
|
||||
#[ignore]
|
||||
fn shows_behind() -> io::Result<()> {
|
||||
let repo_dir = common::create_fixture_repo()?;
|
||||
|
||||
Command::new("git")
|
||||
.args(&["reset", "--hard", "HEAD^"])
|
||||
.current_dir(repo_dir.as_path())
|
||||
.output()?;
|
||||
|
||||
let output = common::render_module("git_status")
|
||||
.arg("--path")
|
||||
.arg(repo_dir)
|
||||
.output()?;
|
||||
let actual = String::from_utf8(output.stdout).unwrap();
|
||||
let expected = Color::Red.bold().paint(format!("[{}] ", "⇣")).to_string();
|
||||
|
||||
assert_eq!(expected, actual);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore]
|
||||
fn shows_behind_with_count() -> io::Result<()> {
|
||||
let repo_dir = common::create_fixture_repo()?;
|
||||
|
||||
Command::new("git")
|
||||
.args(&["reset", "--hard", "HEAD^"])
|
||||
.current_dir(repo_dir.as_path())
|
||||
.output()?;
|
||||
|
||||
let output = common::render_module("git_status")
|
||||
.use_config(toml::toml! {
|
||||
[git_status]
|
||||
show_sync_count = true
|
||||
})
|
||||
.arg("--path")
|
||||
.arg(repo_dir)
|
||||
.output()?;
|
||||
let actual = String::from_utf8(output.stdout).unwrap();
|
||||
let expected = Color::Red
|
||||
.bold()
|
||||
.paint(format!("[{}] ", "⇣1"))
|
||||
.to_string();
|
||||
|
||||
assert_eq!(expected, actual);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore]
|
||||
fn shows_ahead() -> io::Result<()> {
|
||||
let repo_dir = common::create_fixture_repo()?;
|
||||
|
||||
File::create(repo_dir.join("readme.md"))?;
|
||||
|
||||
Command::new("git")
|
||||
.args(&["commit", "-am", "Update readme"])
|
||||
.current_dir(&repo_dir)
|
||||
.output()?;
|
||||
|
||||
let output = common::render_module("git_status")
|
||||
.arg("--path")
|
||||
.arg(repo_dir)
|
||||
.output()?;
|
||||
let actual = String::from_utf8(output.stdout).unwrap();
|
||||
let expected = Color::Red.bold().paint(format!("[{}] ", "⇡")).to_string();
|
||||
|
||||
assert_eq!(expected, actual);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore]
|
||||
fn shows_ahead_with_count() -> io::Result<()> {
|
||||
let repo_dir = common::create_fixture_repo()?;
|
||||
|
||||
File::create(repo_dir.join("readme.md"))?;
|
||||
|
||||
Command::new("git")
|
||||
.args(&["commit", "-am", "Update readme"])
|
||||
.current_dir(&repo_dir)
|
||||
.output()?;
|
||||
|
||||
let output = common::render_module("git_status")
|
||||
.use_config(toml::toml! {
|
||||
[git_status]
|
||||
show_sync_count = true
|
||||
})
|
||||
.arg("--path")
|
||||
.arg(repo_dir)
|
||||
.output()?;
|
||||
let actual = String::from_utf8(output.stdout).unwrap();
|
||||
let expected = Color::Red
|
||||
.bold()
|
||||
.paint(format!("[{}] ", "⇡1"))
|
||||
.to_string();
|
||||
|
||||
assert_eq!(expected, actual);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore]
|
||||
fn shows_diverged() -> io::Result<()> {
|
||||
let repo_dir = common::create_fixture_repo()?;
|
||||
|
||||
Command::new("git")
|
||||
.args(&["reset", "--hard", "HEAD^"])
|
||||
.current_dir(repo_dir.as_path())
|
||||
.output()?;
|
||||
|
||||
fs::write(repo_dir.join("Cargo.toml"), " ")?;
|
||||
|
||||
Command::new("git")
|
||||
.args(&["commit", "-am", "Update readme"])
|
||||
.current_dir(repo_dir.as_path())
|
||||
.output()?;
|
||||
|
||||
let output = common::render_module("git_status")
|
||||
.arg("--path")
|
||||
.arg(repo_dir)
|
||||
.output()?;
|
||||
let actual = String::from_utf8(output.stdout).unwrap();
|
||||
let expected = Color::Red.bold().paint(format!("[{}] ", "⇕")).to_string();
|
||||
|
||||
assert_eq!(expected, actual);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore]
|
||||
fn shows_diverged_with_count() -> io::Result<()> {
|
||||
let repo_dir = common::create_fixture_repo()?;
|
||||
|
||||
Command::new("git")
|
||||
.args(&["reset", "--hard", "HEAD^"])
|
||||
.current_dir(repo_dir.as_path())
|
||||
.output()?;
|
||||
|
||||
fs::write(repo_dir.join("Cargo.toml"), " ")?;
|
||||
|
||||
Command::new("git")
|
||||
.args(&["commit", "-am", "Update readme"])
|
||||
.current_dir(repo_dir.as_path())
|
||||
.output()?;
|
||||
|
||||
let output = common::render_module("git_status")
|
||||
.use_config(toml::toml! {
|
||||
[git_status]
|
||||
show_sync_count = true
|
||||
})
|
||||
.arg("--path")
|
||||
.arg(repo_dir)
|
||||
.output()?;
|
||||
let actual = String::from_utf8(output.stdout).unwrap();
|
||||
let expected = Color::Red
|
||||
.bold()
|
||||
.paint(format!("[{}] ", "⇕⇡1⇣1"))
|
||||
.to_string();
|
||||
|
||||
assert_eq!(expected, actual);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore]
|
||||
fn shows_conflicted() -> io::Result<()> {
|
||||
let repo_dir = common::create_fixture_repo()?;
|
||||
|
||||
Command::new("git")
|
||||
.args(&["reset", "--hard", "HEAD^"])
|
||||
.current_dir(repo_dir.as_path())
|
||||
.output()?;
|
||||
|
||||
fs::write(repo_dir.join("readme.md"), "# goodbye")?;
|
||||
|
||||
Command::new("git")
|
||||
.args(&["add", "."])
|
||||
.current_dir(repo_dir.as_path())
|
||||
.output()?;
|
||||
|
||||
Command::new("git")
|
||||
.args(&["commit", "-m", "Change readme"])
|
||||
.current_dir(repo_dir.as_path())
|
||||
.output()?;
|
||||
|
||||
Command::new("git")
|
||||
.args(&["pull", "--rebase"])
|
||||
.current_dir(repo_dir.as_path())
|
||||
.output()?;
|
||||
|
||||
let output = common::render_module("git_status")
|
||||
.arg("--path")
|
||||
.arg(repo_dir)
|
||||
.output()?;
|
||||
let actual = String::from_utf8(output.stdout).unwrap();
|
||||
let expected = Color::Red.bold().paint(format!("[{}] ", "=")).to_string();
|
||||
|
||||
assert_eq!(expected, actual);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore]
|
||||
fn shows_untracked_file() -> io::Result<()> {
|
||||
let repo_dir = common::create_fixture_repo()?;
|
||||
|
||||
File::create(repo_dir.join("license"))?;
|
||||
|
||||
let output = common::render_module("git_status")
|
||||
.arg("--path")
|
||||
.arg(repo_dir)
|
||||
.output()?;
|
||||
let actual = String::from_utf8(output.stdout).unwrap();
|
||||
let expected = Color::Red.bold().paint(format!("[{}] ", "?")).to_string();
|
||||
|
||||
assert_eq!(expected, actual);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore]
|
||||
fn doesnt_show_untracked_file_if_disabled() -> io::Result<()> {
|
||||
let repo_dir = common::create_fixture_repo()?;
|
||||
|
||||
File::create(repo_dir.join("license"))?;
|
||||
|
||||
Command::new("git")
|
||||
.args(&["config", "status.showUntrackedFiles", "no"])
|
||||
.current_dir(repo_dir.as_path())
|
||||
.output()?;
|
||||
|
||||
let output = common::render_module("git_status")
|
||||
.arg("--path")
|
||||
.arg(repo_dir)
|
||||
.output()?;
|
||||
let actual = String::from_utf8(output.stdout).unwrap();
|
||||
let expected = "";
|
||||
|
||||
assert_eq!(expected, actual);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore]
|
||||
fn shows_stashed() -> io::Result<()> {
|
||||
let repo_dir = common::create_fixture_repo()?;
|
||||
|
||||
File::create(repo_dir.join("readme.md"))?;
|
||||
|
||||
Command::new("git")
|
||||
.arg("stash")
|
||||
.current_dir(repo_dir.as_path())
|
||||
.output()?;
|
||||
|
||||
let output = common::render_module("git_status")
|
||||
.arg("--path")
|
||||
.arg(repo_dir)
|
||||
.output()?;
|
||||
let actual = String::from_utf8(output.stdout).unwrap();
|
||||
let expected = Color::Red.bold().paint(format!("[{}] ", "$")).to_string();
|
||||
|
||||
assert_eq!(expected, actual);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore]
|
||||
fn shows_modified() -> io::Result<()> {
|
||||
let repo_dir = common::create_fixture_repo()?;
|
||||
|
||||
File::create(repo_dir.join("readme.md"))?;
|
||||
|
||||
let output = common::render_module("git_status")
|
||||
.arg("--path")
|
||||
.arg(repo_dir)
|
||||
.output()?;
|
||||
let actual = String::from_utf8(output.stdout).unwrap();
|
||||
let expected = Color::Red.bold().paint(format!("[{}] ", "!")).to_string();
|
||||
|
||||
assert_eq!(expected, actual);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore]
|
||||
fn shows_staged_file() -> io::Result<()> {
|
||||
let repo_dir = common::create_fixture_repo()?;
|
||||
|
||||
File::create(repo_dir.join("license"))?;
|
||||
|
||||
Command::new("git")
|
||||
.args(&["add", "."])
|
||||
.current_dir(repo_dir.as_path())
|
||||
.output()?;
|
||||
|
||||
let output = common::render_module("git_status")
|
||||
.arg("--path")
|
||||
.arg(repo_dir)
|
||||
.output()?;
|
||||
let actual = String::from_utf8(output.stdout).unwrap();
|
||||
let expected = Color::Red.bold().paint(format!("[{}] ", "+")).to_string();
|
||||
|
||||
assert_eq!(expected, actual);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore]
|
||||
fn shows_renamed_file() -> io::Result<()> {
|
||||
let repo_dir = common::create_fixture_repo()?;
|
||||
|
||||
Command::new("git")
|
||||
.args(&["mv", "readme.md", "readme.md.bak"])
|
||||
.current_dir(repo_dir.as_path())
|
||||
.output()?;
|
||||
|
||||
Command::new("git")
|
||||
.args(&["add", "-A"])
|
||||
.current_dir(repo_dir.as_path())
|
||||
.output()?;
|
||||
|
||||
let output = common::render_module("git_status")
|
||||
.arg("--path")
|
||||
.arg(repo_dir)
|
||||
.output()?;
|
||||
let actual = String::from_utf8(output.stdout).unwrap();
|
||||
let expected = Color::Red.bold().paint(format!("[{}] ", "»")).to_string();
|
||||
|
||||
assert_eq!(expected, actual);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore]
|
||||
fn shows_deleted_file() -> io::Result<()> {
|
||||
let repo_dir = common::create_fixture_repo()?;
|
||||
|
||||
fs::remove_file(repo_dir.join("readme.md"))?;
|
||||
|
||||
let output = common::render_module("git_status")
|
||||
.arg("--path")
|
||||
.arg(repo_dir)
|
||||
.output()?;
|
||||
let actual = String::from_utf8(output.stdout).unwrap();
|
||||
let expected = Color::Red.bold().paint(format!("[{}] ", "✘")).to_string();
|
||||
|
||||
assert_eq!(expected, actual);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -2,7 +2,7 @@ use ansi_term::Color;
|
||||
use std::fs::{self, File};
|
||||
use std::io;
|
||||
|
||||
use crate::common;
|
||||
use crate::common::{self, TestCommand};
|
||||
|
||||
#[test]
|
||||
fn folder_without_go_files() -> io::Result<()> {
|
||||
@@ -31,7 +31,7 @@ fn folder_with_go_file() -> io::Result<()> {
|
||||
.output()?;
|
||||
let actual = String::from_utf8(output.stdout).unwrap();
|
||||
|
||||
let expected = format!("via {} ", Color::Cyan.bold().paint("🐹 v1.10"));
|
||||
let expected = format!("via {} ", Color::Cyan.bold().paint("🐹 v1.12.1"));
|
||||
assert_eq!(expected, actual);
|
||||
Ok(())
|
||||
}
|
||||
@@ -48,7 +48,7 @@ fn folder_with_go_mod() -> io::Result<()> {
|
||||
.output()?;
|
||||
let actual = String::from_utf8(output.stdout).unwrap();
|
||||
|
||||
let expected = format!("via {} ", Color::Cyan.bold().paint("🐹 v1.10"));
|
||||
let expected = format!("via {} ", Color::Cyan.bold().paint("🐹 v1.12.1"));
|
||||
assert_eq!(expected, actual);
|
||||
Ok(())
|
||||
}
|
||||
@@ -65,7 +65,7 @@ fn folder_with_go_sum() -> io::Result<()> {
|
||||
.output()?;
|
||||
let actual = String::from_utf8(output.stdout).unwrap();
|
||||
|
||||
let expected = format!("via {} ", Color::Cyan.bold().paint("🐹 v1.10"));
|
||||
let expected = format!("via {} ", Color::Cyan.bold().paint("🐹 v1.12.1"));
|
||||
assert_eq!(expected, actual);
|
||||
Ok(())
|
||||
}
|
||||
@@ -83,7 +83,7 @@ fn folder_with_godeps() -> io::Result<()> {
|
||||
.output()?;
|
||||
let actual = String::from_utf8(output.stdout).unwrap();
|
||||
|
||||
let expected = format!("via {} ", Color::Cyan.bold().paint("🐹 v1.10"));
|
||||
let expected = format!("via {} ", Color::Cyan.bold().paint("🐹 v1.12.1"));
|
||||
assert_eq!(expected, actual);
|
||||
Ok(())
|
||||
}
|
||||
@@ -100,7 +100,7 @@ fn folder_with_glide_yaml() -> io::Result<()> {
|
||||
.output()?;
|
||||
let actual = String::from_utf8(output.stdout).unwrap();
|
||||
|
||||
let expected = format!("via {} ", Color::Cyan.bold().paint("🐹 v1.10"));
|
||||
let expected = format!("via {} ", Color::Cyan.bold().paint("🐹 v1.12.1"));
|
||||
assert_eq!(expected, actual);
|
||||
Ok(())
|
||||
}
|
||||
@@ -117,7 +117,7 @@ fn folder_with_gopkg_yml() -> io::Result<()> {
|
||||
.output()?;
|
||||
let actual = String::from_utf8(output.stdout).unwrap();
|
||||
|
||||
let expected = format!("via {} ", Color::Cyan.bold().paint("🐹 v1.10"));
|
||||
let expected = format!("via {} ", Color::Cyan.bold().paint("🐹 v1.12.1"));
|
||||
assert_eq!(expected, actual);
|
||||
Ok(())
|
||||
}
|
||||
@@ -134,7 +134,28 @@ fn folder_with_gopkg_lock() -> io::Result<()> {
|
||||
.output()?;
|
||||
let actual = String::from_utf8(output.stdout).unwrap();
|
||||
|
||||
let expected = format!("via {} ", Color::Cyan.bold().paint("🐹 v1.10"));
|
||||
let expected = format!("via {} ", Color::Cyan.bold().paint("🐹 v1.12.1"));
|
||||
assert_eq!(expected, actual);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore]
|
||||
fn config_disabled() -> io::Result<()> {
|
||||
let dir = common::new_tempdir()?;
|
||||
File::create(dir.path().join("main.go"))?;
|
||||
|
||||
let output = common::render_module("golang")
|
||||
.use_config(toml::toml! {
|
||||
[golang]
|
||||
disabled = true
|
||||
})
|
||||
.arg("--path")
|
||||
.arg(dir.path())
|
||||
.output()?;
|
||||
let actual = String::from_utf8(output.stdout).unwrap();
|
||||
|
||||
let expected = "";
|
||||
assert_eq!(expected, actual);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -0,0 +1,117 @@
|
||||
use ansi_term::{Color, Style};
|
||||
use std::io;
|
||||
|
||||
use crate::common;
|
||||
use crate::common::TestCommand;
|
||||
|
||||
#[test]
|
||||
fn ssh_only_false() -> io::Result<()> {
|
||||
let hostname = match get_hostname() {
|
||||
Some(h) => h,
|
||||
None => return hostname_not_tested(),
|
||||
};
|
||||
let output = common::render_module("hostname")
|
||||
.env_clear()
|
||||
.use_config(toml::toml! {
|
||||
[hostname]
|
||||
ssh_only = false
|
||||
})
|
||||
.output()?;
|
||||
let actual = String::from_utf8(output.stdout).unwrap();
|
||||
let expected = format!("on {} ", style().paint(hostname));
|
||||
assert_eq!(expected, actual);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn no_ssh() -> io::Result<()> {
|
||||
let output = common::render_module("hostname")
|
||||
.env_clear()
|
||||
.use_config(toml::toml! {
|
||||
[hostname]
|
||||
ssh_only = true
|
||||
})
|
||||
.output()?;
|
||||
let actual = String::from_utf8(output.stdout).unwrap();
|
||||
assert_eq!("", actual);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn ssh() -> io::Result<()> {
|
||||
let hostname = match get_hostname() {
|
||||
Some(h) => h,
|
||||
None => return hostname_not_tested(),
|
||||
};
|
||||
let output = common::render_module("hostname")
|
||||
.env_clear()
|
||||
.use_config(toml::toml! {
|
||||
[hostname]
|
||||
ssh_only = true
|
||||
})
|
||||
.env("SSH_CONNECTION", "something")
|
||||
.output()?;
|
||||
let actual = String::from_utf8(output.stdout).unwrap();
|
||||
let expected = format!("on {} ", style().paint(hostname));
|
||||
assert_eq!(expected, actual);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn prefix() -> io::Result<()> {
|
||||
let hostname = match get_hostname() {
|
||||
Some(h) => h,
|
||||
None => return hostname_not_tested(),
|
||||
};
|
||||
let output = common::render_module("hostname")
|
||||
.env_clear()
|
||||
.use_config(toml::toml! {
|
||||
[hostname]
|
||||
ssh_only = false
|
||||
prefix = "<"
|
||||
})
|
||||
.output()?;
|
||||
let actual = String::from_utf8(output.stdout).unwrap();
|
||||
let expected = format!("on {} ", style().paint(format!("<{}", hostname)));
|
||||
assert_eq!(actual, expected);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn suffix() -> io::Result<()> {
|
||||
let hostname = match get_hostname() {
|
||||
Some(h) => h,
|
||||
None => return hostname_not_tested(),
|
||||
};
|
||||
let output = common::render_module("hostname")
|
||||
.env_clear()
|
||||
.use_config(toml::toml! {
|
||||
[hostname]
|
||||
ssh_only = false
|
||||
suffix = ">"
|
||||
})
|
||||
.output()?;
|
||||
let actual = String::from_utf8(output.stdout).unwrap();
|
||||
let expected = format!("on {} ", style().paint(format!("{}>", hostname)));
|
||||
assert_eq!(actual, expected);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn get_hostname() -> Option<String> {
|
||||
match gethostname::gethostname().into_string() {
|
||||
Ok(hostname) => Some(hostname),
|
||||
Err(_) => None,
|
||||
}
|
||||
}
|
||||
|
||||
fn style() -> Style {
|
||||
Color::Green.bold().dimmed()
|
||||
}
|
||||
|
||||
fn hostname_not_tested() -> io::Result<()> {
|
||||
println!(
|
||||
"hostname was not tested because gethostname failed! \
|
||||
This could be caused by your hostname containing invalid UTF."
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
@@ -1,8 +1,5 @@
|
||||
use ansi_term::Color;
|
||||
use std::fs;
|
||||
use std::io;
|
||||
use std::path::Path;
|
||||
use tempfile::TempDir;
|
||||
|
||||
use crate::common::{self, TestCommand};
|
||||
|
||||
|
||||
@@ -3,9 +3,16 @@ mod cmd_duration;
|
||||
mod common;
|
||||
mod configuration;
|
||||
mod directory;
|
||||
mod git_branch;
|
||||
mod git_state;
|
||||
mod git_status;
|
||||
mod golang;
|
||||
mod hostname;
|
||||
mod jobs;
|
||||
mod line_break;
|
||||
mod modules;
|
||||
mod nix_shell;
|
||||
mod nodejs;
|
||||
mod python;
|
||||
mod ruby;
|
||||
mod username;
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
use std::io;
|
||||
|
||||
use crate::common;
|
||||
|
||||
#[test]
|
||||
fn unknown_module_name() -> io::Result<()> {
|
||||
let unknown_module_name = "some_random_name";
|
||||
let output = common::render_module(unknown_module_name).output()?;
|
||||
let actual_stdout = String::from_utf8(output.stdout).unwrap();
|
||||
let actual_stderr = String::from_utf8(output.stderr).unwrap();
|
||||
let expected_stdout = "";
|
||||
let expected_stderr = format!(
|
||||
"Error: Unknown module {}. Use starship module --list to list out all supported modules.\n",
|
||||
unknown_module_name
|
||||
);
|
||||
assert_eq!(expected_stdout, actual_stdout);
|
||||
assert_eq!(expected_stderr, actual_stderr);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn known_module_name() -> io::Result<()> {
|
||||
let output = common::render_module("line_break").output()?;
|
||||
let actual_stdout = String::from_utf8(output.stdout).unwrap();
|
||||
let actual_stderr = String::from_utf8(output.stderr).unwrap();
|
||||
let expected_stdout = "\n";
|
||||
let expected_stderr = "";
|
||||
assert_eq!(expected_stdout, actual_stdout);
|
||||
assert_eq!(expected_stderr, actual_stderr);
|
||||
Ok(())
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
use ansi_term::Color;
|
||||
use std::io;
|
||||
|
||||
use crate::common;
|
||||
|
||||
#[test]
|
||||
fn no_env_variables() -> io::Result<()> {
|
||||
let output = common::render_module("nix_shell").output()?;
|
||||
let actual = String::from_utf8(output.stdout).unwrap();
|
||||
assert_eq!("", actual);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn invalid_env_variables() -> io::Result<()> {
|
||||
let output = common::render_module("nix_shell")
|
||||
.env("IN_NIX_SHELL", "something_wrong")
|
||||
.output()?;
|
||||
let actual = String::from_utf8(output.stdout).unwrap();
|
||||
assert_eq!("", actual);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn pure_shell() -> io::Result<()> {
|
||||
let output = common::render_module("nix_shell")
|
||||
.env("IN_NIX_SHELL", "pure")
|
||||
.output()?;
|
||||
let actual = String::from_utf8(output.stdout).unwrap();
|
||||
|
||||
let expected = format!("via {} ", Color::Red.bold().paint("pure"));
|
||||
assert_eq!(expected, actual);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn impure_shell() -> io::Result<()> {
|
||||
let output = common::render_module("nix_shell")
|
||||
.env("IN_NIX_SHELL", "impure")
|
||||
.output()?;
|
||||
let actual = String::from_utf8(output.stdout).unwrap();
|
||||
|
||||
let expected = format!("via {} ", Color::Red.bold().paint("impure"));
|
||||
assert_eq!(expected, actual);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn lorri_shell() -> io::Result<()> {
|
||||
let output = common::render_module("nix_shell")
|
||||
.env("IN_NIX_SHELL", "1")
|
||||
.output()?;
|
||||
let actual = String::from_utf8(output.stdout).unwrap();
|
||||
|
||||
let expected = format!("via {} ", Color::Red.bold().paint("impure"));
|
||||
assert_eq!(expected, actual);
|
||||
Ok(())
|
||||
}
|
||||
@@ -2,7 +2,7 @@ use ansi_term::Color;
|
||||
use std::fs::{self, File};
|
||||
use std::io;
|
||||
|
||||
use crate::common;
|
||||
use crate::common::{self, TestCommand};
|
||||
|
||||
#[test]
|
||||
fn folder_without_node_files() -> io::Result<()> {
|
||||
@@ -70,3 +70,24 @@ fn folder_with_node_modules() -> io::Result<()> {
|
||||
assert_eq!(expected, actual);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore]
|
||||
fn config_disabled() -> io::Result<()> {
|
||||
let dir = common::new_tempdir()?;
|
||||
File::create(dir.path().join("package.json"))?;
|
||||
|
||||
let output = common::render_module("nodejs")
|
||||
.use_config(toml::toml! {
|
||||
[nodejs]
|
||||
disabled = true
|
||||
})
|
||||
.arg("--path")
|
||||
.arg(dir.path())
|
||||
.output()?;
|
||||
let actual = String::from_utf8(output.stdout).unwrap();
|
||||
|
||||
let expected = "";
|
||||
assert_eq!(expected, actual);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
+17
-40
@@ -4,7 +4,6 @@ use std::io;
|
||||
use ansi_term::Color;
|
||||
|
||||
use crate::common;
|
||||
use crate::common::TestCommand;
|
||||
|
||||
#[test]
|
||||
#[ignore]
|
||||
@@ -57,6 +56,23 @@ fn folder_with_pyproject_toml() -> io::Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore]
|
||||
fn folder_with_pipfile() -> io::Result<()> {
|
||||
let dir = common::new_tempdir()?;
|
||||
File::create(dir.path().join("Pipfile"))?;
|
||||
|
||||
let output = common::render_module("python")
|
||||
.arg("--path")
|
||||
.arg(dir.path())
|
||||
.output()?;
|
||||
let actual = String::from_utf8(output.stdout).unwrap();
|
||||
|
||||
let expected = format!("via {} ", Color::Yellow.bold().paint("🐍 v3.6.9"));
|
||||
assert_eq!(expected, actual);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore]
|
||||
fn folder_with_py_file() -> io::Result<()> {
|
||||
@@ -93,42 +109,3 @@ fn with_virtual_env() -> io::Result<()> {
|
||||
assert_eq!(expected, actual);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore]
|
||||
fn with_pyenv() -> io::Result<()> {
|
||||
let dir = common::new_tempdir()?;
|
||||
File::create(dir.path().join("main.py"))?;
|
||||
let output = common::render_module("python")
|
||||
.use_config(toml::toml! {
|
||||
[python]
|
||||
pyenv_version_name = true
|
||||
})
|
||||
.env("VIRTUAL_ENV", "/foo/bar/my_venv")
|
||||
.arg("--path")
|
||||
.arg(dir.path())
|
||||
.output()?;
|
||||
let actual = String::from_utf8(output.stdout).unwrap();
|
||||
let expected = format!("via {} ", Color::Yellow.bold().paint("🐍 pyenv system"));
|
||||
assert_eq!(expected, actual);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore]
|
||||
fn with_pyenv_no_output() -> io::Result<()> {
|
||||
let dir = common::new_tempdir()?;
|
||||
File::create(dir.path().join("main.py"))?;
|
||||
let output = common::render_module("python")
|
||||
.use_config(toml::toml! {
|
||||
[python]
|
||||
pyenv_version_name = true
|
||||
})
|
||||
.env("PATH", "")
|
||||
.arg("--path")
|
||||
.arg(dir.path())
|
||||
.output()?;
|
||||
let actual = String::from_utf8(output.stdout).unwrap();
|
||||
assert_eq!("", actual);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
use ansi_term::Color;
|
||||
use std::fs::File;
|
||||
use std::io;
|
||||
|
||||
use crate::common;
|
||||
|
||||
#[test]
|
||||
fn folder_without_ruby_files() -> io::Result<()> {
|
||||
let dir = common::new_tempdir()?;
|
||||
|
||||
let output = common::render_module("ruby")
|
||||
.arg("--path")
|
||||
.arg(dir.path())
|
||||
.output()?;
|
||||
let actual = String::from_utf8(output.stdout).unwrap();
|
||||
|
||||
let expected = "";
|
||||
assert_eq!(expected, actual);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore]
|
||||
fn folder_with_gemfile() -> io::Result<()> {
|
||||
let dir = common::new_tempdir()?;
|
||||
File::create(dir.path().join("Gemfile"))?;
|
||||
|
||||
let output = common::render_module("ruby")
|
||||
.arg("--path")
|
||||
.arg(dir.path())
|
||||
.output()?;
|
||||
let actual = String::from_utf8(output.stdout).unwrap();
|
||||
|
||||
let expected = format!("via {} ", Color::Red.bold().paint("💎 v2.6.3"));
|
||||
assert_eq!(expected, actual);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore]
|
||||
fn folder_with_rb_file() -> io::Result<()> {
|
||||
let dir = common::new_tempdir()?;
|
||||
File::create(dir.path().join("any.rb"))?;
|
||||
|
||||
let output = common::render_module("ruby")
|
||||
.arg("--path")
|
||||
.arg(dir.path())
|
||||
.output()?;
|
||||
let actual = String::from_utf8(output.stdout).unwrap();
|
||||
|
||||
let expected = format!("via {} ", Color::Red.bold().paint("💎 v2.6.3"));
|
||||
assert_eq!(expected, actual);
|
||||
Ok(())
|
||||
}
|
||||
Reference in New Issue
Block a user