mirror of
https://github.com/JanDeDobbeleer/oh-my-posh.git
synced 2025-01-12 03:37:31 -08:00
Merge branch 'main' into main
This commit is contained in:
commit
d37994e18c
|
@ -2280,6 +2280,152 @@
|
|||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "gergelyk",
|
||||
"name": "Grzegorz Krasoń",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/11185582?v=4",
|
||||
"profile": "http://krason.dev/",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "rockyoung",
|
||||
"name": "rockyoung",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/1207971?v=4",
|
||||
"profile": "https://github.com/rockyoung",
|
||||
"contributions": [
|
||||
"code",
|
||||
"doc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "shravanasati",
|
||||
"name": "Shravan Asati",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/69118069?v=4",
|
||||
"profile": "https://github.com/shravanasati",
|
||||
"contributions": [
|
||||
"design"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "lzecca78",
|
||||
"name": "Luca Zecca",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/3881844?v=4",
|
||||
"profile": "https://github.com/lzecca78",
|
||||
"contributions": [
|
||||
"code",
|
||||
"design",
|
||||
"doc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "jreilly-lukava",
|
||||
"name": "Joshua Reilly",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/30353736?v=4",
|
||||
"profile": "https://github.com/jreilly-lukava",
|
||||
"contributions": [
|
||||
"code",
|
||||
"doc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "ivan-the-terrible",
|
||||
"name": "Ivan",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/56458442?v=4",
|
||||
"profile": "https://ivan-the-terrible.github.io/",
|
||||
"contributions": [
|
||||
"design",
|
||||
"doc",
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "mountcount",
|
||||
"name": "mountcount",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/166301065?v=4",
|
||||
"profile": "https://github.com/mountcount",
|
||||
"contributions": [
|
||||
"doc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "Bondrake",
|
||||
"name": "Bondrake",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/11696?v=4",
|
||||
"profile": "https://github.com/Bondrake",
|
||||
"contributions": [
|
||||
"design",
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "R00dRallec",
|
||||
"name": "R00dRallec",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/9081954?v=4",
|
||||
"profile": "https://github.com/R00dRallec",
|
||||
"contributions": [
|
||||
"code",
|
||||
"doc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "publicfacingusername",
|
||||
"name": "Justin Wolfington",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/13956145?v=4",
|
||||
"profile": "https://github.com/publicfacingusername",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "jtracey93",
|
||||
"name": "Jack Tracey",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/41163455?v=4",
|
||||
"profile": "https://bio.link/jacktracey",
|
||||
"contributions": [
|
||||
"design"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "MarkDaveny",
|
||||
"name": "MarkDaveny",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/168091250?v=4",
|
||||
"profile": "https://github.com/MarkDaveny",
|
||||
"contributions": [
|
||||
"code",
|
||||
"design",
|
||||
"doc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "tiwahu",
|
||||
"name": "Timothy Huber",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/590564?v=4",
|
||||
"profile": "http://www.tiwahu.com/",
|
||||
"contributions": [
|
||||
"design"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "YashJM",
|
||||
"name": "Yash Mistry",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/63824041?v=4",
|
||||
"profile": "http://yashjmistry.me",
|
||||
"contributions": [
|
||||
"design"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "jlabonski",
|
||||
"name": "Jeffrey Labonski",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/2981369?v=4",
|
||||
"profile": "https://github.com/jlabonski",
|
||||
"contributions": [
|
||||
"code",
|
||||
"doc"
|
||||
]
|
||||
}
|
||||
],
|
||||
"contributorsPerLine": 7,
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
// Update the VARIANT arg to pick a version of Go: 1, 1.16, 1.17
|
||||
// Append -bullseye or -buster to pin to an OS version.
|
||||
// Use -bullseye variants on local arm64/Apple Silicon.
|
||||
"VARIANT": "1-1.21-bullseye",
|
||||
"VARIANT": "1-1.22.3-bullseye",
|
||||
|
||||
// Options:
|
||||
"POSH_THEME": "/workspaces/oh-my-posh/themes/jandedobbeleer.omp.json",
|
||||
|
|
3
.github/holopin.yml
vendored
3
.github/holopin.yml
vendored
|
@ -4,3 +4,6 @@ stickers:
|
|||
-
|
||||
id: clg0u51g681700fmfr086ofc6
|
||||
alias: wizard
|
||||
-
|
||||
id: clu72f66x59170fjoo6t2b7zs
|
||||
alias: helping
|
||||
|
|
2
.github/workflows/android.yml
vendored
2
.github/workflows/android.yml
vendored
|
@ -9,7 +9,7 @@ jobs:
|
|||
container: ghcr.io/jandedobbeleer/golang-android-container:latest
|
||||
steps:
|
||||
- name: Checkout code 👋
|
||||
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11
|
||||
uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29
|
||||
- name: Build
|
||||
run: |
|
||||
VERSION=$(echo "${{ github.event.release.name }}" | cut -c2-)
|
||||
|
|
6
.github/workflows/build_code.yml
vendored
6
.github/workflows/build_code.yml
vendored
|
@ -17,18 +17,18 @@ jobs:
|
|||
shell: pwsh
|
||||
steps:
|
||||
- name: Checkout code 👋
|
||||
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11
|
||||
uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29
|
||||
- name: Install Go 🗳
|
||||
uses: ./.github/workflows/composite/bootstrap-go
|
||||
- name: Run GoReleaser 🚀
|
||||
uses: goreleaser/goreleaser-action@7ec5c2b0c6cdda6e8bbb49444bc797dd33d74dd8
|
||||
uses: goreleaser/goreleaser-action@5742e2a039330cbb23ebf35f046f814d4c6ff811
|
||||
with:
|
||||
distribution: goreleaser
|
||||
version: latest
|
||||
args: build --clean --snapshot --skip=post-hooks --skip=before
|
||||
workdir: src
|
||||
- name: Archive production artifacts
|
||||
uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3
|
||||
uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808
|
||||
with:
|
||||
name: builds
|
||||
retention-days: 1
|
||||
|
|
2
.github/workflows/close_themes_pr.yml
vendored
2
.github/workflows/close_themes_pr.yml
vendored
|
@ -9,7 +9,7 @@ jobs:
|
|||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout code 👋
|
||||
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11
|
||||
uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29
|
||||
- name: Check and close 🔐
|
||||
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea
|
||||
with:
|
||||
|
|
6
.github/workflows/code.yml
vendored
6
.github/workflows/code.yml
vendored
|
@ -20,14 +20,14 @@ jobs:
|
|||
working-directory: ${{ github.workspace }}/src
|
||||
steps:
|
||||
- name: Install Go
|
||||
uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491
|
||||
uses: actions/setup-go@cdcb36043654635271a94b9a6d1392de5bb323a7
|
||||
with:
|
||||
go-version: 1.21
|
||||
cache-dependency-path: src/go.sum
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11
|
||||
uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29
|
||||
- name: Golang CI
|
||||
uses: golangci/golangci-lint-action@3cfe3a4abbb849e10058ce4af15d205b6da42804
|
||||
uses: golangci/golangci-lint-action@a4f60bb28d35aeee14e6880718e0c85ff1882e64
|
||||
with:
|
||||
working-directory: src
|
||||
- name: Unit Tests
|
||||
|
|
10
.github/workflows/codeql.yml
vendored
10
.github/workflows/codeql.yml
vendored
|
@ -20,17 +20,17 @@ jobs:
|
|||
working-directory: ${{ github.workspace }}/src
|
||||
steps:
|
||||
- name: Install Go
|
||||
uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491
|
||||
uses: actions/setup-go@cdcb36043654635271a94b9a6d1392de5bb323a7
|
||||
with:
|
||||
go-version: 1.21
|
||||
cache-dependency-path: src/go.sum
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11
|
||||
uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@cdcdbb579706841c47f7063dda365e292e5cad7a
|
||||
uses: github/codeql-action/init@9fdb3e49720b44c48891d036bb502feb25684276
|
||||
with:
|
||||
languages: go
|
||||
- name: Autobuild
|
||||
uses: github/codeql-action/autobuild@cdcdbb579706841c47f7063dda365e292e5cad7a
|
||||
uses: github/codeql-action/autobuild@9fdb3e49720b44c48891d036bb502feb25684276
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@cdcdbb579706841c47f7063dda365e292e5cad7a
|
||||
uses: github/codeql-action/analyze@9fdb3e49720b44c48891d036bb502feb25684276
|
||||
|
|
|
@ -9,4 +9,4 @@ runs:
|
|||
steps:
|
||||
- uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491
|
||||
with:
|
||||
go-version: '1.22.0'
|
||||
go-version: '1.22.3'
|
||||
|
|
8
.github/workflows/docs.yml
vendored
8
.github/workflows/docs.yml
vendored
|
@ -18,12 +18,12 @@ jobs:
|
|||
runs-on: ubuntu-latest
|
||||
name: Build and Deploy
|
||||
steps:
|
||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11
|
||||
- uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29
|
||||
with:
|
||||
submodules: true
|
||||
persist-credentials: false
|
||||
- name: Install Go
|
||||
uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491
|
||||
uses: actions/setup-go@cdcb36043654635271a94b9a6d1392de5bb323a7
|
||||
with:
|
||||
go-version: 1.21
|
||||
cache-dependency-path: src/go.sum
|
||||
|
@ -34,7 +34,7 @@ jobs:
|
|||
# Images are defined on every Kind release
|
||||
# See https://github.com/kubernetes-sigs/kind/releases
|
||||
- name: Create k8s v1.23 Kind Cluster
|
||||
uses: helm/kind-action@99576bfa6ddf9a8e612d83b513da5a75875caced
|
||||
uses: helm/kind-action@0025e74a8c7512023d06dc019c617aa3cf561fde
|
||||
with:
|
||||
node_image: kindest/node:v1.23.4@sha256:0e34f0d0fd448aa2f2819cfd74e99fe5793a6e4938b328f657c8e3f81ee0dfb9
|
||||
cluster_name: posh
|
||||
|
@ -44,7 +44,7 @@ jobs:
|
|||
- name: Set default Kubernetes namespace
|
||||
run: |
|
||||
kubectl config set-context posh --namespace demo
|
||||
- uses: azure/login@cb79c773a3cfa27f31f25eb3f677781210c9ce3d
|
||||
- uses: azure/login@6b2456866fc08b011acb422a92a4aa20e2c4de32
|
||||
with:
|
||||
creds: ${{ secrets.AZURE_CREDENTIALS }}
|
||||
- name: Build oh-my-posh 🔧
|
||||
|
|
4
.github/workflows/gomod.yml
vendored
4
.github/workflows/gomod.yml
vendored
|
@ -10,12 +10,12 @@ jobs:
|
|||
working-directory: ${{ github.workspace }}/src
|
||||
steps:
|
||||
- name: Install Go
|
||||
uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491
|
||||
uses: actions/setup-go@cdcb36043654635271a94b9a6d1392de5bb323a7
|
||||
with:
|
||||
go-version: 1.21
|
||||
cache-dependency-path: src/go.sum
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11
|
||||
uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29
|
||||
- name: Check for unused dependencies
|
||||
run: |
|
||||
go mod tidy
|
||||
|
|
2
.github/workflows/inno.yml
vendored
2
.github/workflows/inno.yml
vendored
|
@ -15,7 +15,7 @@ jobs:
|
|||
working-directory: ${{ github.workspace }}/packages/inno
|
||||
steps:
|
||||
- name: Checkout code 👋
|
||||
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11
|
||||
uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29
|
||||
- name: Build installer 📦
|
||||
id: build
|
||||
env:
|
||||
|
|
2
.github/workflows/lock.yml
vendored
2
.github/workflows/lock.yml
vendored
|
@ -16,7 +16,7 @@ jobs:
|
|||
steps:
|
||||
- uses: dessant/lock-threads@1bf7ec25051fe7c00bdd17e6a7cf3d7bfb7dc771
|
||||
with:
|
||||
issue-inactive-days: '182'
|
||||
issue-inactive-days: '90'
|
||||
issue-comment: >
|
||||
This issue has been automatically locked since there
|
||||
has not been any recent activity (i.e. last half year) after it was closed.
|
||||
|
|
2
.github/workflows/markdown.yml
vendored
2
.github/workflows/markdown.yml
vendored
|
@ -7,7 +7,7 @@ jobs:
|
|||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11
|
||||
uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29
|
||||
- name: Lint files
|
||||
uses: articulate/actions-markdownlint@17b8abe7407cd17590c006ecc837c35e1ac3ed83
|
||||
with:
|
||||
|
|
2
.github/workflows/merge_contributions_pr.yml
vendored
2
.github/workflows/merge_contributions_pr.yml
vendored
|
@ -10,7 +10,7 @@ jobs:
|
|||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout code 👋
|
||||
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11
|
||||
uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29
|
||||
- name: Check and merge ⛙
|
||||
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea
|
||||
with:
|
||||
|
|
12
.github/workflows/release.yml
vendored
12
.github/workflows/release.yml
vendored
|
@ -19,10 +19,10 @@ jobs:
|
|||
skipped: ${{ steps.changelog.outputs.skipped }}
|
||||
steps:
|
||||
- name: Checkout code 👋
|
||||
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11
|
||||
uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29
|
||||
- name: Create changelog ✍️
|
||||
id: changelog
|
||||
uses: TriPSs/conventional-changelog-action@f04dac1fd07687cec8ea302937ca588b33786e98
|
||||
uses: TriPSs/conventional-changelog-action@3a392e9aa44a72686b0fc13259a90d287dd0877c
|
||||
with:
|
||||
github-token: ${{ secrets.github_token }}
|
||||
skip-version-file: "true"
|
||||
|
@ -41,7 +41,7 @@ jobs:
|
|||
working-directory: ${{ github.workspace }}/src
|
||||
steps:
|
||||
- name: Checkout code 👋
|
||||
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11
|
||||
uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29
|
||||
- name: Install Go 🗳
|
||||
uses: ./.github/workflows/composite/bootstrap-go
|
||||
- name: Tag HEAD 😸
|
||||
|
@ -50,7 +50,7 @@ jobs:
|
|||
git config --global user.email "41898282+github-actions[bot]@users.noreply.github.com"
|
||||
git tag ${{ needs.changelog.outputs.tag }}
|
||||
- name: Install cosign 🔑
|
||||
uses: sigstore/cosign-installer@e1523de7571e31dbe865fd2e80c5c7c23ae71eb4
|
||||
uses: sigstore/cosign-installer@59acb6260d9c0ba8f4a2f9d9b48431a222b68e20
|
||||
with:
|
||||
cosign-release: 'v1.4.0'
|
||||
- name: Private Key 🔐
|
||||
|
@ -60,7 +60,7 @@ jobs:
|
|||
env:
|
||||
COSIGN_KEY: ${{secrets.COSIGN_KEY}}
|
||||
- name: Run GoReleaser 🚀
|
||||
uses: goreleaser/goreleaser-action@7ec5c2b0c6cdda6e8bbb49444bc797dd33d74dd8
|
||||
uses: goreleaser/goreleaser-action@5742e2a039330cbb23ebf35f046f814d4c6ff811
|
||||
with:
|
||||
distribution: goreleaser
|
||||
version: latest
|
||||
|
@ -85,7 +85,7 @@ jobs:
|
|||
}
|
||||
shell: pwsh
|
||||
- name: Release 🎓
|
||||
uses: softprops/action-gh-release@de2c0eb89ae2a093876385947365aca7b0e5f844
|
||||
uses: softprops/action-gh-release@69320dbe05506a9a39fc8ae11030b214ec2d1f87
|
||||
with:
|
||||
tag_name: ${{ needs.changelog.outputs.tag }}
|
||||
body: ${{ needs.changelog.outputs.body }}
|
||||
|
|
2
.github/workflows/scoop.yml
vendored
2
.github/workflows/scoop.yml
vendored
|
@ -18,7 +18,7 @@ jobs:
|
|||
working-directory: ${{ github.workspace }}/packages/scoop
|
||||
steps:
|
||||
- name: Checkout code 👋
|
||||
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11
|
||||
uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29
|
||||
- name: Update Template ✍️
|
||||
run: |
|
||||
./build.ps1 -Version ${{ github.event.inputs.version }}
|
||||
|
|
2
.github/workflows/winget.yml
vendored
2
.github/workflows/winget.yml
vendored
|
@ -17,7 +17,7 @@ jobs:
|
|||
WINGETCREATE_TOKEN: ${{ secrets.WINGETCREATE_TOKEN }}
|
||||
steps:
|
||||
- name: Checkout code 👋
|
||||
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11
|
||||
uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29
|
||||
- name: Create manifest and submit PR 📦
|
||||
run: |
|
||||
./build.ps1 -Version "${{ github.event.inputs.version }}" -Token $env:WINGETCREATE_TOKEN
|
||||
|
|
11
.vscode/launch.json
vendored
11
.vscode/launch.json
vendored
|
@ -77,6 +77,17 @@
|
|||
"--print"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Export Config",
|
||||
"type": "go",
|
||||
"request": "launch",
|
||||
"mode": "debug",
|
||||
"program": "${workspaceRoot}/src",
|
||||
"args": [
|
||||
"config",
|
||||
"export"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Export Image",
|
||||
"type": "go",
|
||||
|
|
|
@ -8,7 +8,6 @@ linters:
|
|||
- dupl
|
||||
- errcheck
|
||||
- exhaustive
|
||||
- gochecknoinits
|
||||
- goconst
|
||||
- gocritic
|
||||
- gocyclo
|
||||
|
@ -36,13 +35,11 @@ linters-settings:
|
|||
gocritic:
|
||||
enabled-tags:
|
||||
- diagnostic
|
||||
- experimental
|
||||
# - experimental
|
||||
- opinionated
|
||||
- performance
|
||||
- style
|
||||
disabled-tags:
|
||||
- experimental
|
||||
disabled-checks:
|
||||
- ifElseChain
|
||||
lll:
|
||||
line-length: 180
|
||||
|
|
|
@ -9,7 +9,7 @@ import (
|
|||
"github.com/mattn/go-runewidth"
|
||||
)
|
||||
|
||||
func init() { //nolint:gochecknoinits
|
||||
func init() {
|
||||
runewidth.DefaultCondition.EastAsianWidth = false
|
||||
}
|
||||
|
||||
|
@ -36,8 +36,8 @@ type style struct {
|
|||
}
|
||||
|
||||
type Colors struct {
|
||||
Background string `json:"background"`
|
||||
Foreground string `json:"foreground"`
|
||||
Background string `json:"background" toml:"background"`
|
||||
Foreground string `json:"foreground" toml:"foreground"`
|
||||
}
|
||||
|
||||
const (
|
||||
|
@ -114,6 +114,10 @@ type Writer struct {
|
|||
hyperlinkStart string
|
||||
hyperlinkCenter string
|
||||
hyperlinkEnd string
|
||||
|
||||
iTermPromptMark string
|
||||
iTermCurrentDir string
|
||||
iTermRemoteHost string
|
||||
}
|
||||
|
||||
func (w *Writer) Init(shellName string) {
|
||||
|
@ -137,6 +141,9 @@ func (w *Writer) Init(shellName string) {
|
|||
w.osc99 = "\\[\x1b]9;9;%s\x1b\\\\\\]"
|
||||
w.osc7 = "\\[\x1b]7;file://%s/%s\x1b\\\\\\]"
|
||||
w.osc51 = "\\[\x1b]51;A;%s@%s:%s\x1b\\\\\\]"
|
||||
w.iTermPromptMark = "\\[$(iterm2_prompt_mark)\\]"
|
||||
w.iTermCurrentDir = "\\[\x1b]1337;CurrentDir=%s\x07\\]"
|
||||
w.iTermRemoteHost = "\\[\x1b]1337;RemoteHost=%s@%s\x07\\]"
|
||||
case shell.ZSH, shell.TCSH:
|
||||
w.format = "%%{%s%%}"
|
||||
w.linechange = "%%{\x1b[%d%s%%}"
|
||||
|
@ -154,6 +161,9 @@ func (w *Writer) Init(shellName string) {
|
|||
w.osc99 = "%%{\x1b]9;9;%s\x1b\\%%}"
|
||||
w.osc7 = "%%{\x1b]7;file://%s/%s\x1b\\%%}"
|
||||
w.osc51 = "%%{\x1b]51;A%s@%s:%s\x1b\\%%}"
|
||||
w.iTermPromptMark = "%{$(iterm2_prompt_mark)%}"
|
||||
w.iTermCurrentDir = "%%{\x1b]1337;CurrentDir=%s\x07%%}"
|
||||
w.iTermRemoteHost = "%%{\x1b]1337;RemoteHost=%s@%s\x07%%}"
|
||||
default:
|
||||
w.linechange = "\x1b[%d%s"
|
||||
w.left = "\x1b[%dD"
|
||||
|
@ -171,6 +181,8 @@ func (w *Writer) Init(shellName string) {
|
|||
w.osc99 = "\x1b]9;9;%s\x1b\\"
|
||||
w.osc7 = "\x1b]7;file://%s/%s\x1b\\"
|
||||
w.osc51 = "\x1b]51;A%s@%s:%s\x1b\\"
|
||||
w.iTermCurrentDir = "\x1b]1337;CurrentDir=%s\x07"
|
||||
w.iTermRemoteHost = "\x1b]1337;RemoteHost=%s@%s\x07"
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -428,7 +440,7 @@ func (w *Writer) writeSegmentColors() {
|
|||
return
|
||||
}
|
||||
|
||||
if fg.IsTransparent() && len(w.TerminalBackground) != 0 {
|
||||
if fg.IsTransparent() && len(w.TerminalBackground) != 0 { //nolint: gocritic
|
||||
background := w.getAnsiFromColorString(w.TerminalBackground, false)
|
||||
w.writeEscapedAnsiString(fmt.Sprintf(colorise, background))
|
||||
w.writeEscapedAnsiString(fmt.Sprintf(colorise, bg.ToForeground()))
|
||||
|
|
51
src/ansi/iterm.go
Normal file
51
src/ansi/iterm.go
Normal file
|
@ -0,0 +1,51 @@
|
|||
package ansi
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"slices"
|
||||
"strings"
|
||||
|
||||
"github.com/jandedobbeleer/oh-my-posh/src/shell"
|
||||
)
|
||||
|
||||
type iTermFeature string
|
||||
|
||||
const (
|
||||
PromptMark iTermFeature = "prompt_mark"
|
||||
CurrentDir iTermFeature = "current_dir"
|
||||
RemoteHost iTermFeature = "remote_host"
|
||||
)
|
||||
|
||||
type ITermFeatures []iTermFeature
|
||||
|
||||
func (f ITermFeatures) Contains(feature iTermFeature) bool {
|
||||
for _, item := range f {
|
||||
if item == feature {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func (w *Writer) RenderItermFeatures(features ITermFeatures, sh, pwd, user, host string) string {
|
||||
supportedShells := []string{shell.BASH, shell.ZSH}
|
||||
|
||||
var result strings.Builder
|
||||
for _, feature := range features {
|
||||
switch feature {
|
||||
case PromptMark:
|
||||
if !slices.Contains(supportedShells, sh) {
|
||||
continue
|
||||
}
|
||||
|
||||
result.WriteString(w.iTermPromptMark)
|
||||
case CurrentDir:
|
||||
result.WriteString(fmt.Sprintf(w.iTermCurrentDir, pwd))
|
||||
case RemoteHost:
|
||||
result.WriteString(fmt.Sprintf(w.iTermRemoteHost, user, host))
|
||||
}
|
||||
}
|
||||
|
||||
return result.String()
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
package ansi
|
||||
|
||||
type Palettes struct {
|
||||
Template string `json:"template,omitempty"`
|
||||
List map[string]Palette `json:"list,omitempty"`
|
||||
Template string `json:"template,omitempty" toml:"template,omitempty"`
|
||||
List map[string]Palette `json:"list,omitempty" toml:"list,omitempty"`
|
||||
}
|
||||
|
|
|
@ -57,7 +57,7 @@ You can do the following:
|
|||
},
|
||||
}
|
||||
|
||||
func init() { //nolint:gochecknoinits
|
||||
func init() {
|
||||
RootCmd.AddCommand(getCache)
|
||||
}
|
||||
|
||||
|
|
|
@ -39,6 +39,6 @@ You can export, migrate or edit the config.`,
|
|||
},
|
||||
}
|
||||
|
||||
func init() { //nolint:gochecknoinits
|
||||
func init() {
|
||||
RootCmd.AddCommand(configCmd)
|
||||
}
|
||||
|
|
|
@ -2,7 +2,9 @@ package cli
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"slices"
|
||||
"strings"
|
||||
|
||||
"github.com/jandedobbeleer/oh-my-posh/src/engine"
|
||||
|
@ -42,15 +44,41 @@ Exports the ~/myconfig.omp.json config file to toml and prints the result to std
|
|||
env.Init()
|
||||
defer env.Close()
|
||||
cfg := engine.LoadConfig(env)
|
||||
|
||||
if len(output) == 0 && len(format) == 0 {
|
||||
// usage error
|
||||
os.Exit(2)
|
||||
}
|
||||
|
||||
formats := []string{"json", "jsonc", "toml", "tml", "yaml", "yml"}
|
||||
if len(format) != 0 && !slices.Contains(formats, format) {
|
||||
// usage error
|
||||
os.Exit(2)
|
||||
}
|
||||
|
||||
if len(output) == 0 {
|
||||
fmt.Print(cfg.Export(format))
|
||||
return
|
||||
}
|
||||
|
||||
cfg.Output = cleanOutputPath(output, env)
|
||||
format := strings.TrimPrefix(filepath.Ext(output), ".")
|
||||
if format == "yml" {
|
||||
format = engine.YAML
|
||||
|
||||
if len(format) == 0 {
|
||||
format = strings.TrimPrefix(filepath.Ext(output), ".")
|
||||
}
|
||||
|
||||
switch format {
|
||||
case "json", "jsonc":
|
||||
format = engine.JSON
|
||||
case "toml", "tml":
|
||||
format = engine.TOML
|
||||
case "yaml", "yml":
|
||||
format = engine.YAML
|
||||
default:
|
||||
// data error
|
||||
os.Exit(65)
|
||||
}
|
||||
|
||||
cfg.Write(format)
|
||||
},
|
||||
}
|
||||
|
@ -68,7 +96,7 @@ func cleanOutputPath(path string, env platform.Environment) string {
|
|||
return filepath.Clean(path)
|
||||
}
|
||||
|
||||
func init() { //nolint:gochecknoinits
|
||||
func init() {
|
||||
exportCmd.Flags().StringVarP(&format, "format", "f", "json", "config format to migrate to")
|
||||
exportCmd.Flags().StringVarP(&output, "output", "o", "", "config file to export to")
|
||||
configCmd.AddCommand(exportCmd)
|
||||
|
|
|
@ -106,11 +106,9 @@ Exports the config to an image file using customized output options.`,
|
|||
},
|
||||
}
|
||||
|
||||
func init() { //nolint:gochecknoinits
|
||||
func init() {
|
||||
imageCmd.Flags().StringVar(&author, "author", "", "config author")
|
||||
imageCmd.Flags().StringVar(&bgColor, "background-color", "", "image background color")
|
||||
// imageCmd.Flags().IntVar(&cursorPadding, "cursor-padding", 0, "prompt cursor padding")
|
||||
// imageCmd.Flags().IntVar(&rPromptOffset, "rprompt-offset", 0, "right prompt offset")
|
||||
imageCmd.Flags().StringVarP(&outputImage, "output", "o", "", "image file (.png) to export to")
|
||||
exportCmd.AddCommand(imageCmd)
|
||||
}
|
||||
|
|
|
@ -57,7 +57,7 @@ A backup of the current config can be found at ~/myconfig.omp.json.bak.`,
|
|||
},
|
||||
}
|
||||
|
||||
func init() { //nolint:gochecknoinits
|
||||
func init() {
|
||||
migrateCmd.Flags().BoolVarP(&write, "write", "w", false, "write the migrated config back to the config file")
|
||||
migrateCmd.Flags().StringVarP(&format, "format", "f", "json", "the config format to migrate to")
|
||||
configCmd.AddCommand(migrateCmd)
|
||||
|
|
|
@ -59,7 +59,7 @@ A backup of the current config can be found at ~/myconfig.omp.json.bak.`,
|
|||
},
|
||||
}
|
||||
|
||||
func init() { //nolint:gochecknoinits
|
||||
func init() {
|
||||
migrateGlyphsCmd.Flags().BoolVarP(&write, "write", "w", false, "write the migrated config back to the config file")
|
||||
migrateGlyphsCmd.Flags().StringVarP(&format, "format", "f", "", "the config format to migrate to")
|
||||
migrateCmd.AddCommand(migrateGlyphsCmd)
|
||||
|
|
|
@ -60,7 +60,7 @@ var debugCmd = &cobra.Command{
|
|||
},
|
||||
}
|
||||
|
||||
func init() { //nolint:gochecknoinits
|
||||
func init() {
|
||||
debugCmd.Flags().StringVar(&pwd, "pwd", "", "current working directory")
|
||||
debugCmd.Flags().StringVar(&shellName, "shell", "", "the shell to print for")
|
||||
debugCmd.Flags().BoolVarP(&plain, "plain", "p", false, "plain text output (no ANSI)")
|
||||
|
|
|
@ -22,6 +22,6 @@ var disableCmd = &cobra.Command{
|
|||
},
|
||||
}
|
||||
|
||||
func init() { //nolint:gochecknoinits
|
||||
func init() {
|
||||
RootCmd.AddCommand(disableCmd)
|
||||
}
|
||||
|
|
|
@ -37,7 +37,7 @@ var enableCmd = &cobra.Command{
|
|||
},
|
||||
}
|
||||
|
||||
func init() { //nolint:gochecknoinits
|
||||
func init() {
|
||||
RootCmd.AddCommand(enableCmd)
|
||||
}
|
||||
|
||||
|
@ -55,6 +55,7 @@ func toggleFeature(cmd *cobra.Command, feature string, enable bool) {
|
|||
env.Cache().Delete(upgrade.CACHEKEY)
|
||||
return
|
||||
}
|
||||
|
||||
env.Cache().Set(upgrade.CACHEKEY, "disabled", -1)
|
||||
default:
|
||||
_ = cmd.Help()
|
||||
|
|
|
@ -65,7 +65,7 @@ This command is used to install fonts and configure the font in your terminal.
|
|||
}
|
||||
)
|
||||
|
||||
func init() { //nolint:gochecknoinits
|
||||
func init() {
|
||||
RootCmd.AddCommand(fontCmd)
|
||||
fontCmd.Flags().BoolVar(&user, "user", false, "install font as user")
|
||||
}
|
||||
|
|
|
@ -91,7 +91,7 @@ This command is used to get the value of the following variables:
|
|||
},
|
||||
}
|
||||
|
||||
func init() { //nolint:gochecknoinits
|
||||
func init() {
|
||||
RootCmd.AddCommand(getCmd)
|
||||
getCmd.Flags().StringVar(&shellName, "shell", "", "the shell to print for")
|
||||
}
|
||||
|
|
|
@ -3,9 +3,11 @@ package cli
|
|||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/jandedobbeleer/oh-my-posh/src/ansi"
|
||||
"github.com/jandedobbeleer/oh-my-posh/src/engine"
|
||||
"github.com/jandedobbeleer/oh-my-posh/src/platform"
|
||||
"github.com/jandedobbeleer/oh-my-posh/src/shell"
|
||||
"github.com/jandedobbeleer/oh-my-posh/src/upgrade"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
@ -44,7 +46,7 @@ See the documentation to initialize your shell: https://ohmyposh.dev/docs/instal
|
|||
}
|
||||
)
|
||||
|
||||
func init() { //nolint:gochecknoinits
|
||||
func init() {
|
||||
initCmd.Flags().BoolVarP(&printOutput, "print", "p", false, "print the init script")
|
||||
initCmd.Flags().BoolVarP(&strict, "strict", "s", false, "run in strict mode")
|
||||
initCmd.Flags().BoolVarP(&manual, "manual", "m", false, "enable/disable manual mode")
|
||||
|
@ -63,11 +65,15 @@ func runInit(shellName string) {
|
|||
}
|
||||
env.Init()
|
||||
defer env.Close()
|
||||
|
||||
cfg := engine.LoadConfig(env)
|
||||
|
||||
shell.Transient = cfg.TransientPrompt != nil
|
||||
shell.ErrorLine = cfg.ErrorLine != nil || cfg.ValidLine != nil
|
||||
shell.Tooltips = len(cfg.Tooltips) > 0
|
||||
shell.ShellIntegration = cfg.ShellIntegration
|
||||
shell.PromptMark = shellName == shell.FISH && cfg.ITermFeatures != nil && cfg.ITermFeatures.Contains(ansi.PromptMark)
|
||||
|
||||
for i, block := range cfg.Blocks {
|
||||
// only fetch cursor position when relevant
|
||||
if !cfg.DisableCursorPositioning && (i == 0 && block.Newline) {
|
||||
|
@ -77,11 +83,18 @@ func runInit(shellName string) {
|
|||
shell.RPrompt = true
|
||||
}
|
||||
}
|
||||
|
||||
// allow overriding the upgrade notice from the config
|
||||
if cfg.DisableNotice {
|
||||
env.Cache().Set(upgrade.CACHEKEY, "disabled", -1)
|
||||
}
|
||||
|
||||
if printOutput {
|
||||
init := shell.PrintInit(env)
|
||||
fmt.Print(init)
|
||||
return
|
||||
}
|
||||
|
||||
init := shell.Init(env)
|
||||
fmt.Print(init)
|
||||
}
|
||||
|
|
|
@ -27,6 +27,6 @@ var noticeCmd = &cobra.Command{
|
|||
},
|
||||
}
|
||||
|
||||
func init() { //nolint:gochecknoinits
|
||||
func init() {
|
||||
RootCmd.AddCommand(noticeCmd)
|
||||
}
|
||||
|
|
|
@ -94,7 +94,7 @@ var printCmd = &cobra.Command{
|
|||
},
|
||||
}
|
||||
|
||||
func init() { //nolint:gochecknoinits
|
||||
func init() {
|
||||
printCmd.Flags().StringVar(&pwd, "pwd", "", "current working directory")
|
||||
printCmd.Flags().StringVar(&pswd, "pswd", "", "current working directory (according to pwsh)")
|
||||
printCmd.Flags().StringVar(&shellName, "shell", "", "the shell to print for")
|
||||
|
|
|
@ -15,7 +15,7 @@ var promptCmd = &cobra.Command{
|
|||
},
|
||||
}
|
||||
|
||||
func init() { //nolint:gochecknoinits
|
||||
func init() {
|
||||
// legacy support
|
||||
promptCmd.AddCommand(initCmd)
|
||||
promptCmd.AddCommand(debugCmd)
|
||||
|
|
|
@ -36,7 +36,8 @@ on getting started, have a look at the docs at https://ohmyposh.dev`,
|
|||
|
||||
func Execute() {
|
||||
if err := RootCmd.Execute(); err != nil {
|
||||
os.Exit(1)
|
||||
// software error
|
||||
os.Exit(70)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -46,7 +47,7 @@ var (
|
|||
initialize bool
|
||||
)
|
||||
|
||||
func init() { //nolint:gochecknoinits
|
||||
func init() {
|
||||
RootCmd.PersistentFlags().StringVarP(&config, "config", "c", "", "config file path")
|
||||
RootCmd.Flags().BoolVarP(&initialize, "init", "i", false, "init (deprecated)")
|
||||
RootCmd.Flags().BoolVar(&displayVersion, "version", false, "version")
|
||||
|
|
|
@ -49,6 +49,6 @@ var toggleCmd = &cobra.Command{
|
|||
},
|
||||
}
|
||||
|
||||
func init() { //nolint:gochecknoinits
|
||||
func init() {
|
||||
RootCmd.AddCommand(toggleCmd)
|
||||
}
|
||||
|
|
|
@ -27,7 +27,7 @@ var versionCmd = &cobra.Command{
|
|||
},
|
||||
}
|
||||
|
||||
func init() { //nolint:gochecknoinits
|
||||
func init() {
|
||||
versionCmd.Flags().BoolVarP(&verbose, "verbose", "v", false, "write verbose output")
|
||||
RootCmd.AddCommand(versionCmd)
|
||||
}
|
||||
|
|
|
@ -38,19 +38,19 @@ const (
|
|||
|
||||
// Block defines a part of the prompt with optional segments
|
||||
type Block struct {
|
||||
Type BlockType `json:"type,omitempty"`
|
||||
Alignment BlockAlignment `json:"alignment,omitempty"`
|
||||
Segments []*Segment `json:"segments,omitempty"`
|
||||
Newline bool `json:"newline,omitempty"`
|
||||
Filler string `json:"filler,omitempty"`
|
||||
Overflow Overflow `json:"overflow,omitempty"`
|
||||
Type BlockType `json:"type,omitempty" toml:"type,omitempty"`
|
||||
Alignment BlockAlignment `json:"alignment,omitempty" toml:"alignment,omitempty"`
|
||||
Segments []*Segment `json:"segments,omitempty" toml:"segments,omitempty"`
|
||||
Newline bool `json:"newline,omitempty" toml:"newline,omitempty"`
|
||||
Filler string `json:"filler,omitempty" toml:"filler,omitempty"`
|
||||
Overflow Overflow `json:"overflow,omitempty" toml:"overflow,omitempty"`
|
||||
|
||||
// Deprecated: keep the logic for legacy purposes
|
||||
HorizontalOffset int `json:"horizontal_offset,omitempty"`
|
||||
VerticalOffset int `json:"vertical_offset,omitempty"`
|
||||
HorizontalOffset int `json:"horizontal_offset,omitempty" toml:"horizontal_offset,omitempty"`
|
||||
VerticalOffset int `json:"vertical_offset,omitempty" toml:"vertical_offset,omitempty"`
|
||||
|
||||
MaxWidth int `json:"max_width,omitempty"`
|
||||
MinWidth int `json:"min_width,omitempty"`
|
||||
MaxWidth int `json:"max_width,omitempty" toml:"max_width,omitempty"`
|
||||
MinWidth int `json:"min_width,omitempty" toml:"min_width,omitempty"`
|
||||
|
||||
env platform.Environment
|
||||
writer *ansi.Writer
|
||||
|
@ -176,38 +176,70 @@ func (b *Block) writeSeparator(final bool) {
|
|||
if isPreviousDiamond {
|
||||
b.adjustTrailingDiamondColorOverrides()
|
||||
}
|
||||
|
||||
if isPreviousDiamond && isCurrentDiamond && len(b.activeSegment.LeadingDiamond) == 0 {
|
||||
b.writer.Write(ansi.Background, ansi.ParentBackground, b.previousActiveSegment.TrailingDiamond)
|
||||
return
|
||||
}
|
||||
|
||||
if isPreviousDiamond && len(b.previousActiveSegment.TrailingDiamond) > 0 {
|
||||
b.writer.Write(ansi.Transparent, ansi.ParentBackground, b.previousActiveSegment.TrailingDiamond)
|
||||
}
|
||||
|
||||
resolvePowerlineSymbol := func() string {
|
||||
var symbol string
|
||||
if b.activeSegment.isPowerline() {
|
||||
symbol = b.activeSegment.PowerlineSymbol
|
||||
} else if b.previousActiveSegment != nil && b.previousActiveSegment.isPowerline() {
|
||||
symbol = b.previousActiveSegment.PowerlineSymbol
|
||||
isPowerline := b.activeSegment.isPowerline()
|
||||
|
||||
shouldOverridePowerlineLeadingSymbol := func() bool {
|
||||
if !isPowerline {
|
||||
return false
|
||||
}
|
||||
return symbol
|
||||
|
||||
if isPowerline && len(b.activeSegment.LeadingPowerlineSymbol) == 0 {
|
||||
return false
|
||||
}
|
||||
|
||||
if b.previousActiveSegment != nil && b.previousActiveSegment.isPowerline() {
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
if shouldOverridePowerlineLeadingSymbol() {
|
||||
b.writer.Write(ansi.Transparent, ansi.Background, b.activeSegment.LeadingPowerlineSymbol)
|
||||
return
|
||||
}
|
||||
|
||||
resolvePowerlineSymbol := func() string {
|
||||
if isPowerline {
|
||||
return b.activeSegment.PowerlineSymbol
|
||||
}
|
||||
|
||||
if b.previousActiveSegment != nil && b.previousActiveSegment.isPowerline() {
|
||||
return b.previousActiveSegment.PowerlineSymbol
|
||||
}
|
||||
|
||||
return ""
|
||||
}
|
||||
|
||||
symbol := resolvePowerlineSymbol()
|
||||
if len(symbol) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
bgColor := ansi.Background
|
||||
if final || !b.activeSegment.isPowerline() {
|
||||
if final || !isPowerline {
|
||||
bgColor = ansi.Transparent
|
||||
}
|
||||
|
||||
if b.activeSegment.style() == Diamond && len(b.activeSegment.LeadingDiamond) == 0 {
|
||||
bgColor = ansi.Background
|
||||
}
|
||||
|
||||
if b.activeSegment.InvertPowerline {
|
||||
b.writer.Write(b.getPowerlineColor(), bgColor, symbol)
|
||||
return
|
||||
}
|
||||
|
||||
b.writer.Write(bgColor, b.getPowerlineColor(), symbol)
|
||||
}
|
||||
|
||||
|
|
|
@ -2,7 +2,6 @@ package engine
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
json2 "encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
|
@ -10,18 +9,16 @@ import (
|
|||
"strings"
|
||||
"time"
|
||||
|
||||
json "github.com/goccy/go-json"
|
||||
yaml "github.com/goccy/go-yaml"
|
||||
"github.com/gookit/goutil/jsonutil"
|
||||
"github.com/jandedobbeleer/oh-my-posh/src/ansi"
|
||||
"github.com/jandedobbeleer/oh-my-posh/src/platform"
|
||||
"github.com/jandedobbeleer/oh-my-posh/src/properties"
|
||||
"github.com/jandedobbeleer/oh-my-posh/src/segments"
|
||||
"github.com/jandedobbeleer/oh-my-posh/src/shell"
|
||||
"github.com/jandedobbeleer/oh-my-posh/src/template"
|
||||
|
||||
"github.com/gookit/config/v2"
|
||||
"github.com/gookit/config/v2/json"
|
||||
"github.com/gookit/config/v2/toml"
|
||||
yaml "github.com/gookit/config/v2/yamlv3"
|
||||
"github.com/mitchellh/mapstructure"
|
||||
toml "github.com/pelletier/go-toml/v2"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -34,33 +31,35 @@ const (
|
|||
|
||||
// Config holds all the theme for rendering the prompt
|
||||
type Config struct {
|
||||
Version int `json:"version"`
|
||||
FinalSpace bool `json:"final_space,omitempty"`
|
||||
ConsoleTitleTemplate string `json:"console_title_template,omitempty"`
|
||||
TerminalBackground string `json:"terminal_background,omitempty"`
|
||||
AccentColor string `json:"accent_color,omitempty"`
|
||||
Blocks []*Block `json:"blocks,omitempty"`
|
||||
Tooltips []*Segment `json:"tooltips,omitempty"`
|
||||
TransientPrompt *Segment `json:"transient_prompt,omitempty"`
|
||||
ValidLine *Segment `json:"valid_line,omitempty"`
|
||||
ErrorLine *Segment `json:"error_line,omitempty"`
|
||||
SecondaryPrompt *Segment `json:"secondary_prompt,omitempty"`
|
||||
DebugPrompt *Segment `json:"debug_prompt,omitempty"`
|
||||
Palette ansi.Palette `json:"palette,omitempty"`
|
||||
Palettes *ansi.Palettes `json:"palettes,omitempty"`
|
||||
Cycle ansi.Cycle `json:"cycle,omitempty"`
|
||||
ShellIntegration bool `json:"shell_integration,omitempty"`
|
||||
PWD string `json:"pwd,omitempty"`
|
||||
Var map[string]any `json:"var,omitempty"`
|
||||
DisableCursorPositioning bool `json:"disable_cursor_positioning,omitempty"`
|
||||
PatchPwshBleed bool `json:"patch_pwsh_bleed,omitempty"`
|
||||
Version int `json:"version" toml:"version"`
|
||||
FinalSpace bool `json:"final_space,omitempty" toml:"final_space,omitempty"`
|
||||
ConsoleTitleTemplate string `json:"console_title_template,omitempty" toml:"console_title_template,omitempty"`
|
||||
TerminalBackground string `json:"terminal_background,omitempty" toml:"terminal_background,omitempty"`
|
||||
AccentColor string `json:"accent_color,omitempty" toml:"accent_color,omitempty"`
|
||||
Blocks []*Block `json:"blocks,omitempty" toml:"blocks,omitempty"`
|
||||
Tooltips []*Segment `json:"tooltips,omitempty" toml:"tooltips,omitempty"`
|
||||
TransientPrompt *Segment `json:"transient_prompt,omitempty" toml:"transient_prompt,omitempty"`
|
||||
ValidLine *Segment `json:"valid_line,omitempty" toml:"valid_line,omitempty"`
|
||||
ErrorLine *Segment `json:"error_line,omitempty" toml:"error_line,omitempty"`
|
||||
SecondaryPrompt *Segment `json:"secondary_prompt,omitempty" toml:"secondary_prompt,omitempty"`
|
||||
DebugPrompt *Segment `json:"debug_prompt,omitempty" toml:"debug_prompt,omitempty"`
|
||||
Palette ansi.Palette `json:"palette,omitempty" toml:"palette,omitempty"`
|
||||
Palettes *ansi.Palettes `json:"palettes,omitempty" toml:"palettes,omitempty"`
|
||||
Cycle ansi.Cycle `json:"cycle,omitempty" toml:"cycle,omitempty"`
|
||||
ShellIntegration bool `json:"shell_integration,omitempty" toml:"shell_integration,omitempty"`
|
||||
PWD string `json:"pwd,omitempty" toml:"pwd,omitempty"`
|
||||
Var map[string]any `json:"var,omitempty" toml:"var,omitempty"`
|
||||
DisableCursorPositioning bool `json:"disable_cursor_positioning,omitempty" toml:"disable_cursor_positioning,omitempty"`
|
||||
PatchPwshBleed bool `json:"patch_pwsh_bleed,omitempty" toml:"patch_pwsh_bleed,omitempty"`
|
||||
DisableNotice bool `json:"disable_notice,omitempty" toml:"disable_notice,omitempty"`
|
||||
ITermFeatures ansi.ITermFeatures `json:"iterm_features,omitempty" toml:"iterm_features,omitempty"`
|
||||
|
||||
// Deprecated
|
||||
OSC99 bool `json:"osc99,omitempty"`
|
||||
OSC99 bool `json:"osc99,omitempty" toml:"osc99,omitempty"`
|
||||
|
||||
Output string `json:"-"`
|
||||
MigrateGlyphs bool `json:"-"`
|
||||
Format string `json:"-"`
|
||||
Output string `json:"-" toml:"-"`
|
||||
MigrateGlyphs bool `json:"-" toml:"-"`
|
||||
Format string `json:"-" toml:"-"`
|
||||
|
||||
origin string
|
||||
// eval bool
|
||||
|
@ -135,94 +134,80 @@ func loadConfig(env platform.Environment) *Config {
|
|||
cfg.Format = strings.TrimPrefix(filepath.Ext(configFile), ".")
|
||||
cfg.env = env
|
||||
|
||||
// support different extensions
|
||||
switch cfg.Format {
|
||||
case "yml":
|
||||
cfg.Format = YAML
|
||||
case "jsonc":
|
||||
cfg.Format = JSON
|
||||
}
|
||||
|
||||
config.AddDriver(yaml.Driver.WithAliases("yaml", "yml"))
|
||||
config.AddDriver(json.Driver.WithAliases("json", "jsonc"))
|
||||
config.AddDriver(toml.Driver)
|
||||
|
||||
if config.Default().IsEmpty() {
|
||||
config.WithOptions(func(opt *config.Options) {
|
||||
opt.DecoderConfig = &mapstructure.DecoderConfig{
|
||||
TagName: "json",
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
err := config.LoadFiles(configFile)
|
||||
data, err := os.ReadFile(configFile)
|
||||
if err != nil {
|
||||
env.Error(err)
|
||||
env.DebugF("error reading config file: %s", err)
|
||||
return defaultConfig(env, true)
|
||||
}
|
||||
|
||||
err = config.BindStruct("", &cfg)
|
||||
switch cfg.Format {
|
||||
case "yml", "yaml":
|
||||
cfg.Format = YAML
|
||||
err = yaml.Unmarshal(data, &cfg)
|
||||
case "jsonc", "json":
|
||||
cfg.Format = JSON
|
||||
|
||||
str := jsonutil.StripComments(string(data))
|
||||
data = []byte(str)
|
||||
|
||||
decoder := json.NewDecoder(bytes.NewReader(data))
|
||||
err = decoder.Decode(&cfg)
|
||||
case "toml", "tml":
|
||||
cfg.Format = TOML
|
||||
err = toml.Unmarshal(data, &cfg)
|
||||
default:
|
||||
err = fmt.Errorf("unsupported config file format: %s", cfg.Format)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
env.Error(err)
|
||||
env.DebugF("error decoding config file: %s", err)
|
||||
return defaultConfig(env, true)
|
||||
}
|
||||
|
||||
return &cfg
|
||||
}
|
||||
|
||||
func (cfg *Config) sync() {
|
||||
if !cfg.updated {
|
||||
return
|
||||
}
|
||||
var structMap map[string]any
|
||||
inrec, err := json2.Marshal(cfg)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
err = json2.Unmarshal(inrec, &structMap)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
// remove empty structs
|
||||
for k, v := range structMap {
|
||||
if smap, OK := v.(map[string]any); OK && len(smap) == 0 {
|
||||
delete(structMap, k)
|
||||
}
|
||||
}
|
||||
config.SetData(structMap)
|
||||
}
|
||||
|
||||
func (cfg *Config) Export(format string) string {
|
||||
cfg.sync()
|
||||
|
||||
if len(format) != 0 {
|
||||
cfg.Format = format
|
||||
}
|
||||
|
||||
config.AddDriver(yaml.Driver)
|
||||
config.AddDriver(toml.Driver)
|
||||
|
||||
var result bytes.Buffer
|
||||
|
||||
if cfg.Format == JSON {
|
||||
jsonEncoder := json2.NewEncoder(&result)
|
||||
switch cfg.Format {
|
||||
case YAML:
|
||||
prefix := "# yaml-language-server: $schema=https://raw.githubusercontent.com/JanDeDobbeleer/oh-my-posh/main/themes/schema.json\n\n"
|
||||
yamlEncoder := yaml.NewEncoder(&result)
|
||||
|
||||
err := yamlEncoder.Encode(cfg)
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
return prefix + result.String()
|
||||
case JSON:
|
||||
jsonEncoder := json.NewEncoder(&result)
|
||||
jsonEncoder.SetEscapeHTML(false)
|
||||
jsonEncoder.SetIndent("", " ")
|
||||
_ = jsonEncoder.Encode(cfg)
|
||||
prefix := "{\n \"$schema\": \"https://raw.githubusercontent.com/JanDeDobbeleer/oh-my-posh/main/themes/schema.json\","
|
||||
data := strings.Replace(result.String(), "{", prefix, 1)
|
||||
return escapeGlyphs(data, cfg.MigrateGlyphs)
|
||||
case TOML:
|
||||
prefix := "#:schema https://raw.githubusercontent.com/JanDeDobbeleer/oh-my-posh/main/themes/schema.json\n\n"
|
||||
tomlEncoder := toml.NewEncoder(&result)
|
||||
tomlEncoder.SetIndentTables(true)
|
||||
|
||||
err := tomlEncoder.Encode(cfg)
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
return prefix + result.String()
|
||||
}
|
||||
|
||||
_, _ = config.DumpTo(&result, cfg.Format)
|
||||
var prefix string
|
||||
switch cfg.Format {
|
||||
case YAML:
|
||||
prefix = "# yaml-language-server: $schema=https://raw.githubusercontent.com/JanDeDobbeleer/oh-my-posh/main/themes/schema.json\n\n"
|
||||
case TOML:
|
||||
prefix = "#:schema https://raw.githubusercontent.com/JanDeDobbeleer/oh-my-posh/main/themes/schema.json\n\n"
|
||||
}
|
||||
return prefix + escapeGlyphs(result.String(), cfg.MigrateGlyphs)
|
||||
// unsupported format
|
||||
return ""
|
||||
}
|
||||
|
||||
func (cfg *Config) BackupAndMigrate() {
|
||||
|
@ -233,19 +218,30 @@ func (cfg *Config) BackupAndMigrate() {
|
|||
|
||||
func (cfg *Config) Write(format string) {
|
||||
content := cfg.Export(format)
|
||||
if len(content) == 0 {
|
||||
// we are unable to perform the export
|
||||
os.Exit(65)
|
||||
return
|
||||
}
|
||||
|
||||
destination := cfg.Output
|
||||
if len(destination) == 0 {
|
||||
destination = cfg.origin
|
||||
}
|
||||
f, err := os.OpenFile(destination, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0755)
|
||||
|
||||
f, err := os.OpenFile(destination, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0644)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
defer func() {
|
||||
_ = f.Close()
|
||||
}()
|
||||
|
||||
_, err = f.WriteString(content)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
_ = f.Close()
|
||||
}
|
||||
|
||||
func (cfg *Config) Backup() {
|
||||
|
|
|
@ -6,46 +6,12 @@ import (
|
|||
"github.com/jandedobbeleer/oh-my-posh/src/ansi"
|
||||
"github.com/jandedobbeleer/oh-my-posh/src/mock"
|
||||
"github.com/jandedobbeleer/oh-my-posh/src/platform"
|
||||
"github.com/jandedobbeleer/oh-my-posh/src/segments"
|
||||
|
||||
"github.com/gookit/config/v2"
|
||||
"github.com/mitchellh/mapstructure"
|
||||
"github.com/stretchr/testify/assert"
|
||||
mock2 "github.com/stretchr/testify/mock"
|
||||
)
|
||||
|
||||
func testClearDefaultConfig() {
|
||||
config.Default().ClearAll()
|
||||
}
|
||||
|
||||
func TestParseMappedLocations(t *testing.T) {
|
||||
defer testClearDefaultConfig()
|
||||
cases := []struct {
|
||||
Case string
|
||||
JSON string
|
||||
}{
|
||||
{Case: "new format", JSON: `{ "properties": { "mapped_locations": {"folder1": "one","folder2": "two"} } }`},
|
||||
{Case: "old format", JSON: `{ "properties": { "mapped_locations": [["folder1", "one"], ["folder2", "two"]] } }`},
|
||||
}
|
||||
for _, tc := range cases {
|
||||
config.ClearAll()
|
||||
config.WithOptions(func(opt *config.Options) {
|
||||
opt.DecoderConfig = &mapstructure.DecoderConfig{
|
||||
TagName: "config",
|
||||
}
|
||||
})
|
||||
err := config.LoadStrings(config.JSON, tc.JSON)
|
||||
assert.NoError(t, err)
|
||||
var segment Segment
|
||||
err = config.BindStruct("", &segment)
|
||||
assert.NoError(t, err)
|
||||
mappedLocations := segment.Properties.GetKeyValueMap(segments.MappedLocations, make(map[string]string))
|
||||
assert.Equal(t, "two", mappedLocations["folder2"])
|
||||
}
|
||||
}
|
||||
|
||||
func TestEscapeGlyphs(t *testing.T) {
|
||||
defer testClearDefaultConfig()
|
||||
cases := []struct {
|
||||
Input string
|
||||
Expected string
|
||||
|
|
|
@ -132,6 +132,10 @@ func (e *Engine) isWarp() bool {
|
|||
return e.Env.Getenv("TERM_PROGRAM") == "WarpTerminal"
|
||||
}
|
||||
|
||||
func (e *Engine) isIterm() bool {
|
||||
return e.Env.Getenv("TERM_PROGRAM") == "iTerm.app"
|
||||
}
|
||||
|
||||
func (e *Engine) shouldFill(filler string, remaining, blockLength int) (string, bool) {
|
||||
if len(filler) == 0 {
|
||||
return "", false
|
||||
|
@ -222,14 +226,6 @@ func (e *Engine) renderBlock(block *Block, cancelNewline bool) bool {
|
|||
return false
|
||||
}
|
||||
|
||||
// in ZSH, RPROMPT is printed with a trailing space
|
||||
// to ensure alignment, we need to print a space here
|
||||
// see https://github.com/JanDeDobbeleer/oh-my-posh/issues/4327
|
||||
if e.Env.Shell() == shell.ZSH {
|
||||
text += " "
|
||||
length++
|
||||
}
|
||||
|
||||
space, OK := e.canWriteRightBlock(false)
|
||||
// we can't print the right block as there's not enough room available
|
||||
if !OK {
|
||||
|
|
|
@ -113,7 +113,6 @@ func engineRender() {
|
|||
defer env.Close()
|
||||
|
||||
cfg := LoadConfig(env)
|
||||
defer testClearDefaultConfig()
|
||||
|
||||
writerColors := cfg.MakeColors()
|
||||
writer := &ansi.Writer{
|
||||
|
|
|
@ -42,8 +42,8 @@ import (
|
|||
|
||||
"github.com/esimov/stackblur-go"
|
||||
"github.com/fogleman/gg"
|
||||
"github.com/golang/freetype/truetype"
|
||||
"golang.org/x/image/font"
|
||||
"golang.org/x/image/font/opentype"
|
||||
)
|
||||
|
||||
type ConnectionError struct {
|
||||
|
@ -217,7 +217,7 @@ func (ir *ImageRenderer) loadFonts() error {
|
|||
|
||||
// Download font if not cached
|
||||
if data == nil {
|
||||
url := "https://github.com/ryanoasis/nerd-fonts/releases/download/v3.1.0/Hack.zip"
|
||||
url := "https://github.com/ryanoasis/nerd-fonts/releases/download/v3.2.1/Hack.zip"
|
||||
var err error
|
||||
|
||||
data, err = fontCLI.Download(url)
|
||||
|
@ -237,7 +237,7 @@ func (ir *ImageRenderer) loadFonts() error {
|
|||
return err
|
||||
}
|
||||
|
||||
fontFaceOptions := &truetype.Options{Size: 2.0 * 12, DPI: 144}
|
||||
fontFaceOptions := &opentype.FaceOptions{Size: 2.0 * 12, DPI: 144}
|
||||
|
||||
parseFont := func(file *zip.File) (font.Face, error) {
|
||||
rc, err := file.Open()
|
||||
|
@ -252,12 +252,16 @@ func (ir *ImageRenderer) loadFonts() error {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
font, err := truetype.Parse(data)
|
||||
font, err := opentype.Parse(data)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return truetype.NewFace(font, fontFaceOptions), nil
|
||||
fontFace, err := opentype.NewFace(font, fontFaceOptions)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return fontFace, nil
|
||||
}
|
||||
|
||||
for _, file := range zipReader.File {
|
||||
|
|
|
@ -2,9 +2,10 @@ package engine
|
|||
|
||||
import (
|
||||
"context"
|
||||
"encoding/csv"
|
||||
"io"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/jandedobbeleer/oh-my-posh/src/platform"
|
||||
|
@ -30,23 +31,29 @@ func getGlyphCodePoints() (codePoints, error) {
|
|||
|
||||
defer response.Body.Close()
|
||||
|
||||
lines, err := csv.NewReader(response.Body).ReadAll()
|
||||
bytes, err := io.ReadAll(response.Body)
|
||||
if err != nil {
|
||||
return codePoints, err
|
||||
}
|
||||
|
||||
lines := strings.Split(string(bytes), "\n")
|
||||
|
||||
for _, line := range lines {
|
||||
if len(line) < 2 {
|
||||
fields := strings.Split(line, ",")
|
||||
if len(fields) < 2 {
|
||||
continue
|
||||
}
|
||||
oldGlyph, err := strconv.ParseUint(line[0], 16, 32)
|
||||
|
||||
oldGlyph, err := strconv.ParseUint(fields[0], 16, 32)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
newGlyph, err := strconv.ParseUint(line[1], 16, 32)
|
||||
|
||||
newGlyph, err := strconv.ParseUint(fields[1], 16, 32)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
codePoints[oldGlyph] = newGlyph
|
||||
}
|
||||
|
||||
|
|
|
@ -68,6 +68,11 @@ func (e *Engine) Primary() string {
|
|||
e.currentLineLength++
|
||||
}
|
||||
|
||||
if e.Config.ITermFeatures != nil && e.isIterm() {
|
||||
host, _ := e.Env.Host()
|
||||
e.write(e.Writer.RenderItermFeatures(e.Config.ITermFeatures, e.Env.Shell(), e.Env.Pwd(), e.Env.User(), host))
|
||||
}
|
||||
|
||||
if e.Config.ShellIntegration && e.Config.TransientPrompt == nil {
|
||||
e.write(e.Writer.CommandStart())
|
||||
}
|
||||
|
|
|
@ -20,28 +20,29 @@ import (
|
|||
|
||||
// Segment represent a single segment and it's configuration
|
||||
type Segment struct {
|
||||
Type SegmentType `json:"type,omitempty"`
|
||||
Tips []string `json:"tips,omitempty"`
|
||||
Style SegmentStyle `json:"style,omitempty"`
|
||||
PowerlineSymbol string `json:"powerline_symbol,omitempty"`
|
||||
InvertPowerline bool `json:"invert_powerline,omitempty"`
|
||||
Foreground string `json:"foreground,omitempty"`
|
||||
ForegroundTemplates template.List `json:"foreground_templates,omitempty"`
|
||||
Background string `json:"background,omitempty"`
|
||||
BackgroundTemplates template.List `json:"background_templates,omitempty"`
|
||||
LeadingDiamond string `json:"leading_diamond,omitempty"`
|
||||
TrailingDiamond string `json:"trailing_diamond,omitempty"`
|
||||
Template string `json:"template,omitempty"`
|
||||
Templates template.List `json:"templates,omitempty"`
|
||||
TemplatesLogic template.Logic `json:"templates_logic,omitempty"`
|
||||
Properties properties.Map `json:"properties,omitempty"`
|
||||
Interactive bool `json:"interactive,omitempty"`
|
||||
Alias string `json:"alias,omitempty"`
|
||||
MaxWidth int `json:"max_width,omitempty"`
|
||||
MinWidth int `json:"min_width,omitempty"`
|
||||
Filler string `json:"filler,omitempty"`
|
||||
Type SegmentType `json:"type,omitempty" toml:"type,omitempty"`
|
||||
Tips []string `json:"tips,omitempty" toml:"tips,omitempty"`
|
||||
Style SegmentStyle `json:"style,omitempty" toml:"style,omitempty"`
|
||||
PowerlineSymbol string `json:"powerline_symbol,omitempty" toml:"powerline_symbol,omitempty"`
|
||||
LeadingPowerlineSymbol string `json:"leading_powerline_symbol,omitempty" toml:"leading_powerline_symbol,omitempty"`
|
||||
InvertPowerline bool `json:"invert_powerline,omitempty" toml:"invert_powerline,omitempty"`
|
||||
Foreground string `json:"foreground,omitempty" toml:"foreground,omitempty"`
|
||||
ForegroundTemplates template.List `json:"foreground_templates,omitempty" toml:"foreground_templates,omitempty"`
|
||||
Background string `json:"background,omitempty" toml:"background,omitempty"`
|
||||
BackgroundTemplates template.List `json:"background_templates,omitempty" toml:"background_templates,omitempty"`
|
||||
LeadingDiamond string `json:"leading_diamond,omitempty" toml:"leading_diamond,omitempty"`
|
||||
TrailingDiamond string `json:"trailing_diamond,omitempty" toml:"trailing_diamond,omitempty"`
|
||||
Template string `json:"template,omitempty" toml:"template,omitempty"`
|
||||
Templates template.List `json:"templates,omitempty" toml:"templates,omitempty"`
|
||||
TemplatesLogic template.Logic `json:"templates_logic,omitempty" toml:"templates_logic,omitempty"`
|
||||
Properties properties.Map `json:"properties,omitempty" toml:"properties,omitempty"`
|
||||
Interactive bool `json:"interactive,omitempty" toml:"interactive,omitempty"`
|
||||
Alias string `json:"alias,omitempty" toml:"alias,omitempty"`
|
||||
MaxWidth int `json:"max_width,omitempty" toml:"max_width,omitempty"`
|
||||
MinWidth int `json:"min_width,omitempty" toml:"min_width,omitempty"`
|
||||
Filler string `json:"filler,omitempty" toml:"filler,omitempty"`
|
||||
|
||||
Enabled bool `json:"-"`
|
||||
Enabled bool `json:"-" toml:"-"`
|
||||
|
||||
colors *ansi.Colors
|
||||
env platform.Environment
|
||||
|
@ -146,6 +147,8 @@ const (
|
|||
FOSSIL SegmentType = "fossil"
|
||||
// GCP writes the active GCP context
|
||||
GCP SegmentType = "gcp"
|
||||
// FIREBASE writes the active firebase project
|
||||
FIREBASE SegmentType = "firebase"
|
||||
// GIT represents the git status and information
|
||||
GIT SegmentType = "git"
|
||||
// GITVERSION represents the gitversion information
|
||||
|
@ -158,8 +161,6 @@ const (
|
|||
HELM SegmentType = "helm"
|
||||
// IPIFY segment
|
||||
IPIFY SegmentType = "ipify"
|
||||
// ITERM inserts the Shell Integration prompt mark on iTerm zsh/bash/fish
|
||||
ITERM SegmentType = "iterm"
|
||||
// JAVA writes the active java version
|
||||
JAVA SegmentType = "java"
|
||||
// JULIA writes which julia version is currently active
|
||||
|
@ -202,6 +203,8 @@ const (
|
|||
PLASTIC SegmentType = "plastic"
|
||||
// Project version
|
||||
PROJECT SegmentType = "project"
|
||||
// PULUMI writes the pulumi user, store and stack
|
||||
PULUMI SegmentType = "pulumi"
|
||||
// PYTHON writes the virtual env name
|
||||
PYTHON SegmentType = "python"
|
||||
// QUASAR writes the QUASAR version and context
|
||||
|
@ -236,6 +239,8 @@ const (
|
|||
SWIFT SegmentType = "swift"
|
||||
// SYSTEMINFO writes system information (memory, cpu, load)
|
||||
SYSTEMINFO SegmentType = "sysinfo"
|
||||
// TALOSCTL writes the talosctl context
|
||||
TALOSCTL SegmentType = "talosctl"
|
||||
// TERRAFORM writes the terraform workspace we're currently in
|
||||
TERRAFORM SegmentType = "terraform"
|
||||
// TEXT writes a text
|
||||
|
@ -294,13 +299,13 @@ var Segments = map[SegmentType]func() SegmentWriter{
|
|||
FLUTTER: func() SegmentWriter { return &segments.Flutter{} },
|
||||
FOSSIL: func() SegmentWriter { return &segments.Fossil{} },
|
||||
GCP: func() SegmentWriter { return &segments.Gcp{} },
|
||||
FIREBASE: func() SegmentWriter { return &segments.Firebase{} },
|
||||
GIT: func() SegmentWriter { return &segments.Git{} },
|
||||
GITVERSION: func() SegmentWriter { return &segments.GitVersion{} },
|
||||
GOLANG: func() SegmentWriter { return &segments.Golang{} },
|
||||
HASKELL: func() SegmentWriter { return &segments.Haskell{} },
|
||||
HELM: func() SegmentWriter { return &segments.Helm{} },
|
||||
IPIFY: func() SegmentWriter { return &segments.IPify{} },
|
||||
ITERM: func() SegmentWriter { return &segments.ITerm{} },
|
||||
JAVA: func() SegmentWriter { return &segments.Java{} },
|
||||
JULIA: func() SegmentWriter { return &segments.Julia{} },
|
||||
KOTLIN: func() SegmentWriter { return &segments.Kotlin{} },
|
||||
|
@ -322,6 +327,7 @@ var Segments = map[SegmentType]func() SegmentWriter{
|
|||
PHP: func() SegmentWriter { return &segments.Php{} },
|
||||
PLASTIC: func() SegmentWriter { return &segments.Plastic{} },
|
||||
PROJECT: func() SegmentWriter { return &segments.Project{} },
|
||||
PULUMI: func() SegmentWriter { return &segments.Pulumi{} },
|
||||
PYTHON: func() SegmentWriter { return &segments.Python{} },
|
||||
QUASAR: func() SegmentWriter { return &segments.Quasar{} },
|
||||
R: func() SegmentWriter { return &segments.R{} },
|
||||
|
@ -339,6 +345,7 @@ var Segments = map[SegmentType]func() SegmentWriter{
|
|||
SVN: func() SegmentWriter { return &segments.Svn{} },
|
||||
SWIFT: func() SegmentWriter { return &segments.Swift{} },
|
||||
SYSTEMINFO: func() SegmentWriter { return &segments.SystemInfo{} },
|
||||
TALOSCTL: func() SegmentWriter { return &segments.TalosCTL{} },
|
||||
TERRAFORM: func() SegmentWriter { return &segments.Terraform{} },
|
||||
TEXT: func() SegmentWriter { return &segments.Text{} },
|
||||
TIME: func() SegmentWriter { return &segments.Time{} },
|
||||
|
|
|
@ -98,12 +98,13 @@ func (m *main) buildFontList(nerdFonts []*Asset) {
|
|||
}
|
||||
|
||||
func getFontsList() {
|
||||
nerdFonts, err := Nerds()
|
||||
fonts, err := Fonts()
|
||||
if err != nil {
|
||||
program.Send(errMsg(err))
|
||||
return
|
||||
}
|
||||
program.Send(loadMsg(nerdFonts))
|
||||
|
||||
program.Send(loadMsg(fonts))
|
||||
}
|
||||
|
||||
func downloadFontZip(location string) {
|
||||
|
@ -272,6 +273,6 @@ func Run(font string, system bool) {
|
|||
program = tea.NewProgram(main)
|
||||
if _, err := program.Run(); err != nil {
|
||||
print("Error running program: %v", err)
|
||||
os.Exit(1)
|
||||
os.Exit(70)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,7 +4,9 @@ import (
|
|||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"sort"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
|
@ -23,30 +25,57 @@ type Asset struct {
|
|||
|
||||
func (a Asset) FilterValue() string { return a.Name }
|
||||
|
||||
func Nerds() ([]*Asset, error) {
|
||||
ctx, cancelF := context.WithTimeout(context.Background(), time.Second*time.Duration(20))
|
||||
defer cancelF()
|
||||
req, err := http.NewRequestWithContext(ctx, "GET", "https://api.github.com/repos/ryanoasis/nerd-fonts/releases/latest", nil)
|
||||
func Fonts() ([]*Asset, error) {
|
||||
assets, err := fetchFontAssets("ryanoasis/nerd-fonts")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
cascadiaCode, err := fetchFontAssets("microsoft/cascadia-code")
|
||||
if err != nil {
|
||||
return assets, nil
|
||||
}
|
||||
|
||||
assets = append(assets, cascadiaCode...)
|
||||
sort.Slice(assets, func(i, j int) bool { return assets[i].Name < assets[j].Name })
|
||||
|
||||
return assets, nil
|
||||
}
|
||||
|
||||
func CascadiaCode() ([]*Asset, error) {
|
||||
return fetchFontAssets("microsoft/cascadia-code")
|
||||
}
|
||||
|
||||
func fetchFontAssets(repo string) ([]*Asset, error) {
|
||||
ctx, cancelF := context.WithTimeout(context.Background(), time.Second*time.Duration(20))
|
||||
defer cancelF()
|
||||
|
||||
repoURL := "https://api.github.com/repos/" + repo + "/releases/latest"
|
||||
req, err := http.NewRequestWithContext(ctx, "GET", repoURL, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
req.Header.Add("Accept", "application/vnd.github.v3+json")
|
||||
response, err := platform.Client.Do(req)
|
||||
if err != nil || response.StatusCode != http.StatusOK {
|
||||
return nil, errors.New("failed to get nerd fonts release")
|
||||
return nil, fmt.Errorf("failed to get %s release", repo)
|
||||
}
|
||||
|
||||
defer response.Body.Close()
|
||||
var release release
|
||||
err = json.NewDecoder(response.Body).Decode(&release)
|
||||
if err != nil {
|
||||
return nil, errors.New("failed to parse nerd fonts release")
|
||||
}
|
||||
var nerdFonts []*Asset
|
||||
|
||||
var fonts []*Asset
|
||||
for _, asset := range release.Assets {
|
||||
if asset.State == "uploaded" && strings.HasSuffix(asset.Name, ".zip") {
|
||||
asset.Name = strings.TrimSuffix(asset.Name, ".zip")
|
||||
nerdFonts = append(nerdFonts, asset)
|
||||
fonts = append(fonts, asset)
|
||||
}
|
||||
}
|
||||
return nerdFonts, nil
|
||||
|
||||
return fonts, nil
|
||||
}
|
59
src/go.mod
59
src/go.mod
|
@ -1,57 +1,56 @@
|
|||
module github.com/jandedobbeleer/oh-my-posh/src
|
||||
|
||||
go 1.21
|
||||
go 1.22.3
|
||||
|
||||
require (
|
||||
github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161
|
||||
github.com/Masterminds/sprig/v3 v3.2.3
|
||||
github.com/alecthomas/assert v1.0.0
|
||||
github.com/alecthomas/colour v0.1.0 // indirect
|
||||
github.com/alecthomas/repr v0.2.0 // indirect
|
||||
github.com/alecthomas/repr v0.4.0 // indirect
|
||||
github.com/esimov/stackblur-go v1.1.0
|
||||
github.com/fogleman/gg v1.3.0
|
||||
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0
|
||||
github.com/google/uuid v1.6.0 // indirect
|
||||
github.com/gookit/color v1.5.4
|
||||
github.com/gookit/config/v2 v2.2.5
|
||||
github.com/gookit/goutil v0.6.15 // indirect
|
||||
github.com/huandu/xstrings v1.4.0 // indirect
|
||||
github.com/mitchellh/copystructure v1.2.0 // indirect
|
||||
github.com/mitchellh/mapstructure v1.5.0
|
||||
github.com/sergi/go-diff v1.3.1 // indirect
|
||||
github.com/shirou/gopsutil/v3 v3.24.1
|
||||
github.com/stretchr/objx v0.5.1 // indirect
|
||||
github.com/stretchr/testify v1.8.4
|
||||
github.com/shirou/gopsutil/v3 v3.24.4
|
||||
github.com/stretchr/objx v0.5.2 // indirect
|
||||
github.com/stretchr/testify v1.9.0
|
||||
github.com/wayneashleyberry/terminal-dimensions v1.1.0
|
||||
golang.org/x/crypto v0.19.0 // indirect
|
||||
golang.org/x/image v0.15.0
|
||||
golang.org/x/sys v0.17.0
|
||||
golang.org/x/text v0.14.0
|
||||
golang.org/x/crypto v0.21.0 // indirect
|
||||
golang.org/x/image v0.16.0
|
||||
golang.org/x/sys v0.20.0
|
||||
golang.org/x/text v0.15.0
|
||||
gopkg.in/ini.v1 v1.67.0
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/ConradIrwin/font v0.0.0-20210318200717-ce8d41cc0732
|
||||
github.com/charmbracelet/bubbles v0.18.0
|
||||
github.com/charmbracelet/bubbletea v0.25.0
|
||||
github.com/charmbracelet/lipgloss v0.9.1
|
||||
github.com/hashicorp/hcl/v2 v2.20.0
|
||||
github.com/charmbracelet/bubbletea v0.26.2
|
||||
github.com/charmbracelet/lipgloss v0.10.0
|
||||
github.com/goccy/go-json v0.10.3
|
||||
github.com/goccy/go-yaml v1.11.3
|
||||
github.com/gookit/goutil v0.6.15
|
||||
github.com/hashicorp/hcl/v2 v2.20.1
|
||||
github.com/mattn/go-runewidth v0.0.15
|
||||
github.com/pelletier/go-toml/v2 v2.2.2
|
||||
github.com/spf13/cobra v1.8.0
|
||||
github.com/spf13/pflag v1.0.5
|
||||
golang.org/x/exp v0.0.0-20240205201215-2c58cdc269a3
|
||||
golang.org/x/mod v0.15.0
|
||||
golang.org/x/exp v0.0.0-20240222234643-814bf88cf225
|
||||
golang.org/x/mod v0.17.0
|
||||
gopkg.in/yaml.v3 v3.0.1
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/BurntSushi/toml v1.3.2
|
||||
github.com/Masterminds/goutils v1.1.1 // indirect
|
||||
github.com/Masterminds/semver/v3 v3.2.1 // indirect
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/go-ole/go-ole v1.3.0 // indirect
|
||||
github.com/imdario/mergo v0.3.16 // indirect
|
||||
github.com/lufia/plan9stats v0.0.0-20231016141302-07b5767bb0ed // indirect
|
||||
github.com/lufia/plan9stats v0.0.0-20240226150601-1dcf7310316a // indirect
|
||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||
github.com/mitchellh/reflectwalk v1.0.2 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
|
@ -62,17 +61,15 @@ require (
|
|||
)
|
||||
|
||||
require (
|
||||
dario.cat/mergo v1.0.0 // indirect
|
||||
dmitri.shuralyov.com/font/woff2 v0.0.0-20180220214647-957792cbbdab // indirect
|
||||
github.com/agext/levenshtein v1.2.3 // indirect
|
||||
github.com/apparentlymart/go-textseg/v15 v15.0.0 // indirect
|
||||
github.com/atotto/clipboard v0.1.4 // indirect
|
||||
github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect
|
||||
github.com/containerd/console v1.0.4 // indirect
|
||||
github.com/dsnet/compress v0.0.1 // indirect
|
||||
github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f // indirect
|
||||
github.com/fatih/color v1.16.0 // indirect
|
||||
github.com/goccy/go-json v0.10.2 // indirect
|
||||
github.com/goccy/go-yaml v1.11.3 // indirect
|
||||
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect
|
||||
github.com/google/go-cmp v0.6.0 // indirect
|
||||
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
||||
github.com/lucasb-eyer/go-colorful v1.2.0 // indirect
|
||||
|
@ -83,16 +80,16 @@ require (
|
|||
github.com/muesli/cancelreader v0.2.2 // indirect
|
||||
github.com/muesli/reflow v0.3.0 // indirect
|
||||
github.com/muesli/termenv v0.15.2 // indirect
|
||||
github.com/power-devops/perfstat v0.0.0-20221212215047-62379fc7944b // indirect
|
||||
github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 // indirect
|
||||
github.com/rivo/uniseg v0.4.7 // indirect
|
||||
github.com/sahilm/fuzzy v0.1.1-0.20230530133925-c48e322e2a8f // indirect
|
||||
github.com/sahilm/fuzzy v0.1.1 // indirect
|
||||
github.com/shoenig/go-m1cpu v0.1.6 // indirect
|
||||
github.com/shopspring/decimal v1.3.1 // indirect
|
||||
github.com/yusufpapurcu/wmi v1.2.4 // indirect
|
||||
github.com/zclconf/go-cty v1.14.2 // indirect
|
||||
golang.org/x/sync v0.6.0 // indirect
|
||||
golang.org/x/term v0.17.0 // indirect
|
||||
golang.org/x/tools v0.17.0 // indirect
|
||||
github.com/zclconf/go-cty v1.14.3 // indirect
|
||||
golang.org/x/sync v0.7.0 // indirect
|
||||
golang.org/x/term v0.20.0 // indirect
|
||||
golang.org/x/tools v0.19.0 // indirect
|
||||
golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 // indirect
|
||||
)
|
||||
|
||||
|
@ -100,4 +97,4 @@ replace github.com/atotto/clipboard v0.1.4 => github.com/jandedobbeleer/clipboar
|
|||
|
||||
replace github.com/shirou/gopsutil/v3 v3.23.9 => github.com/jandedobbeleer/gopsutil/v3 v3.23.9-1
|
||||
|
||||
replace github.com/goccy/go-yaml v1.10.0 => github.com/jandedobbeleer/go-yaml v1.10.0-4
|
||||
replace github.com/goccy/go-yaml v1.11.3 => github.com/jandedobbeleer/go-yaml v1.11.3-2
|
||||
|
|
110
src/go.sum
110
src/go.sum
|
@ -1,11 +1,7 @@
|
|||
dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk=
|
||||
dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk=
|
||||
dmitri.shuralyov.com/font/woff2 v0.0.0-20180220214647-957792cbbdab h1:Ew70NL+wL6v9looOiJJthlqA41VzoJS+q9AyjHJe6/g=
|
||||
dmitri.shuralyov.com/font/woff2 v0.0.0-20180220214647-957792cbbdab/go.mod h1:FvHgTMJanm43G7B3MVSjS/jim5ytVqAJNAOpRhnuHJc=
|
||||
github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 h1:L/gRVlceqvL25UVaW/CKtUDjefjrs0SPonmDGUVOYP0=
|
||||
github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E=
|
||||
github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8=
|
||||
github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
|
||||
github.com/ConradIrwin/font v0.0.0-20210318200717-ce8d41cc0732 h1:0EDePskeF4vNFCk70ATaFHQzjmwXsk+VImnMJttecNU=
|
||||
github.com/ConradIrwin/font v0.0.0-20210318200717-ce8d41cc0732/go.mod h1:krTLO7JWu6g8RMxG8sl+T1Hf8W93XQacBKJmqFZ2MFY=
|
||||
github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI=
|
||||
|
@ -21,20 +17,18 @@ github.com/alecthomas/assert v1.0.0 h1:3XmGh/PSuLzDbK3W2gUbRXwgW5lqPkuqvRgeQ30FI
|
|||
github.com/alecthomas/assert v1.0.0/go.mod h1:va/d2JC+M7F6s+80kl/R3G7FUiW6JzUO+hPhLyJ36ZY=
|
||||
github.com/alecthomas/colour v0.1.0 h1:nOE9rJm6dsZ66RGWYSFrXw461ZIt9A6+nHgL7FRrDUk=
|
||||
github.com/alecthomas/colour v0.1.0/go.mod h1:QO9JBoKquHd+jz9nshCh40fOfO+JzsoXy8qTHF68zU0=
|
||||
github.com/alecthomas/repr v0.2.0 h1:HAzS41CIzNW5syS8Mf9UwXhNH1J9aix/BvDRf1Ml2Yk=
|
||||
github.com/alecthomas/repr v0.2.0/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4=
|
||||
github.com/alecthomas/repr v0.4.0 h1:GhI2A8MACjfegCPVq9f1FLvIBS+DrQ2KQBFZP1iFzXc=
|
||||
github.com/alecthomas/repr v0.4.0/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4=
|
||||
github.com/apparentlymart/go-textseg/v15 v15.0.0 h1:uYvfpb3DyLSCGWnctWKGj857c6ew1u1fNQOlOtuGxQY=
|
||||
github.com/apparentlymart/go-textseg/v15 v15.0.0/go.mod h1:K8XmNZdhEBkdlyDdvbmmsvpAG721bKi0joRfFdHIWJ4=
|
||||
github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k=
|
||||
github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8=
|
||||
github.com/charmbracelet/bubbles v0.18.0 h1:PYv1A036luoBGroX6VWjQIE9Syf2Wby2oOl/39KLfy0=
|
||||
github.com/charmbracelet/bubbles v0.18.0/go.mod h1:08qhZhtIwzgrtBjAcJnij1t1H0ZRjwHyGsy6AL11PSw=
|
||||
github.com/charmbracelet/bubbletea v0.25.0 h1:bAfwk7jRz7FKFl9RzlIULPkStffg5k6pNt5dywy4TcM=
|
||||
github.com/charmbracelet/bubbletea v0.25.0/go.mod h1:EN3QDR1T5ZdWmdfDzYcqOCAps45+QIJbLOBxmVNWNNg=
|
||||
github.com/charmbracelet/lipgloss v0.9.1 h1:PNyd3jvaJbg4jRHKWXnCj1akQm4rh8dbEzN1p/u1KWg=
|
||||
github.com/charmbracelet/lipgloss v0.9.1/go.mod h1:1mPmG4cxScwUQALAAnacHaigiiHB9Pmr+v1VEawJl6I=
|
||||
github.com/containerd/console v1.0.4 h1:F2g4+oChYvBTsASRTz8NP6iIAi97J3TtSAsLbIFn4ro=
|
||||
github.com/containerd/console v1.0.4/go.mod h1:YynlIjWYF8myEu6sdkwKIvGQq+cOckRm6So2avqoYAk=
|
||||
github.com/charmbracelet/bubbletea v0.26.2 h1:Eeb+n75Om9gQ+I6YpbCXQRKHt5Pn4vMwusQpwLiEgJQ=
|
||||
github.com/charmbracelet/bubbletea v0.26.2/go.mod h1:6I0nZ3YHUrQj7YHIHlM8RySX4ZIthTliMY+W8X8b+Gs=
|
||||
github.com/charmbracelet/lipgloss v0.10.0 h1:KWeXFSexGcfahHX+54URiZGkBFazf70JNMtwg/AFW3s=
|
||||
github.com/charmbracelet/lipgloss v0.10.0/go.mod h1:Wig9DSfvANsxqkRsqj6x87irdy123SR4dOXlKa91ciE=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
|
@ -42,6 +36,8 @@ github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs
|
|||
github.com/dsnet/compress v0.0.1 h1:PlZu0n3Tuv04TzpfPbrnI0HW/YwodEXDS+oPKahKF0Q=
|
||||
github.com/dsnet/compress v0.0.1/go.mod h1:Aw8dCMJ7RioblQeTqt88akK31OvO8Dhf5JflhBbQEHo=
|
||||
github.com/dsnet/golib v0.0.0-20171103203638-1ea166775780/go.mod h1:Lj+Z9rebOhdfkVLjJ8T6VcRQv3SXugXy999NBtR9aFY=
|
||||
github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f h1:Y/CXytFA4m6baUTXGLOoWe4PQhGxaX0KpnayAqC48p4=
|
||||
github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f/go.mod h1:vw97MGsxSvLiUE2X8qFplwetxpGLQrlU1Q9AUEIzCaM=
|
||||
github.com/esimov/stackblur-go v1.1.0 h1:fwnZJC/7sHFzu4CDMgdJ1QxMN/q3k5MGILuoU4hH6oQ=
|
||||
github.com/esimov/stackblur-go v1.1.0/go.mod h1:7PcTPCHHKStxbZvBkUlQJjRclqjnXtQ0NoORZt1AlHE=
|
||||
github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM=
|
||||
|
@ -61,10 +57,8 @@ github.com/go-playground/validator/v10 v10.4.1 h1:pH2c5ADXtd66mxoE0Zm9SUhxE20r7a
|
|||
github.com/go-playground/validator/v10 v10.4.1/go.mod h1:nlOn6nFhuKACm19sB/8EGNn9GlaMV7XkbRSipzJ0Ii4=
|
||||
github.com/go-test/deep v1.0.3 h1:ZrJSEWsXzPOxaZnFteGEfooLba+ju3FYIbOrS+rQd68=
|
||||
github.com/go-test/deep v1.0.3/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA=
|
||||
github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=
|
||||
github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
|
||||
github.com/goccy/go-yaml v1.11.3 h1:B3W9IdWbvrUu2OYQGwvU1nZtvMQJPBKgBUuweJjLj6I=
|
||||
github.com/goccy/go-yaml v1.11.3/go.mod h1:wKnAMd44+9JAAnGQpWVEgBzGt3YuTaQ4uXoHvE4m7WU=
|
||||
github.com/goccy/go-json v0.10.3 h1:KZ5WoDbxAIgm2HNbYckL0se1fHD6rz5j4ywS6ebzDqA=
|
||||
github.com/goccy/go-json v0.10.3/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M=
|
||||
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 h1:DACJavvAHhabrF08vX0COfcOBJRhZ8lUbR+ZWIs0Y5g=
|
||||
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k=
|
||||
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
|
@ -76,14 +70,10 @@ github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
|||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/gookit/color v1.5.4 h1:FZmqs7XOyGgCAxmWyPslpiok1k05wmY3SJTytgvYFs0=
|
||||
github.com/gookit/color v1.5.4/go.mod h1:pZJOeOS8DM43rXbp4AZo1n9zCU2qjpcRko0b6/QJi9w=
|
||||
github.com/gookit/config/v2 v2.2.5 h1:RECbYYbtherywmzn3LNeu9NA5ZqhD7MSKEMsJ7l+MpU=
|
||||
github.com/gookit/config/v2 v2.2.5/go.mod h1:NeX+yiNYn6Ei10eJvCQFXuHEPIE/IPS8bqaFIsszzaM=
|
||||
github.com/gookit/goutil v0.6.15 h1:mMQ0ElojNZoyPD0eVROk5QXJPh2uKR4g06slgPDF5Jo=
|
||||
github.com/gookit/goutil v0.6.15/go.mod h1:qdKdYEHQdEtyH+4fNdQNZfJHhI0jUZzHxQVAV3DaMDY=
|
||||
github.com/gookit/ini/v2 v2.2.3 h1:nSbN+x9OfQPcMObTFP+XuHt8ev6ndv/fWWqxFhPMu2E=
|
||||
github.com/gookit/ini/v2 v2.2.3/go.mod h1:Vu6p7P7xcfmb8KYu3L0ek8bqu/Im63N81q208SCCZY4=
|
||||
github.com/hashicorp/hcl/v2 v2.20.0 h1:l++cRs/5jQOiKVvqXZm/P1ZEfVXJmvLS9WSVxkaeTb4=
|
||||
github.com/hashicorp/hcl/v2 v2.20.0/go.mod h1:WmcD/Ym72MDOOx5F62Ly+leloeu6H7m0pG7VBiU6pQk=
|
||||
github.com/hashicorp/hcl/v2 v2.20.1 h1:M6hgdyz7HYt1UN9e61j+qKJBqR3orTWbI1HKBJEdxtc=
|
||||
github.com/hashicorp/hcl/v2 v2.20.1/go.mod h1:TZDqQ4kNKCbh1iJp99FdPiUaVDDUPivbqxZulxDYqL4=
|
||||
github.com/huandu/xstrings v1.3.3/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE=
|
||||
github.com/huandu/xstrings v1.4.0 h1:D17IlohoQq4UcpqD7fDk80P7l+lwAmlFaBHgOipl2FU=
|
||||
github.com/huandu/xstrings v1.4.0/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE=
|
||||
|
@ -94,6 +84,8 @@ github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2
|
|||
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
|
||||
github.com/jandedobbeleer/clipboard v0.1.4-1 h1:rJehm5W0a3hvjcxyB3snqLBV4yvMBBc12JyMP7ngNQw=
|
||||
github.com/jandedobbeleer/clipboard v0.1.4-1/go.mod h1:ZY9tmq7sm5xIbd9bOK4onWV4S6X0u6GY7Vn0Yu86PYI=
|
||||
github.com/jandedobbeleer/go-yaml v1.11.3-2 h1:mz6E/lRl29RqwYkb4HC03C2YwF5tVDNdfiPWa1hYRdo=
|
||||
github.com/jandedobbeleer/go-yaml v1.11.3-2/go.mod h1:wKnAMd44+9JAAnGQpWVEgBzGt3YuTaQ4uXoHvE4m7WU=
|
||||
github.com/klauspost/compress v1.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
|
||||
github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
|
@ -110,8 +102,8 @@ github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgx
|
|||
github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY=
|
||||
github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
|
||||
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I=
|
||||
github.com/lufia/plan9stats v0.0.0-20231016141302-07b5767bb0ed h1:036IscGBfJsFIgJQzlui7nK1Ncm0tp2ktmPj8xO4N/0=
|
||||
github.com/lufia/plan9stats v0.0.0-20231016141302-07b5767bb0ed/go.mod h1:ilwx/Dta8jXAgpFYFvSWEMwxmbWXyiUHkd5FwyKhb5k=
|
||||
github.com/lufia/plan9stats v0.0.0-20240226150601-1dcf7310316a h1:3Bm7EwfUQUvhNeKIkUct/gl9eod1TcXuj8stxvi/GoI=
|
||||
github.com/lufia/plan9stats v0.0.0-20240226150601-1dcf7310316a/go.mod h1:ilwx/Dta8jXAgpFYFvSWEMwxmbWXyiUHkd5FwyKhb5k=
|
||||
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
|
||||
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
|
||||
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
||||
|
@ -127,8 +119,6 @@ github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa1
|
|||
github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s=
|
||||
github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0=
|
||||
github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0=
|
||||
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
|
||||
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
||||
github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
|
||||
github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ=
|
||||
github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
|
||||
|
@ -140,11 +130,13 @@ github.com/muesli/reflow v0.3.0 h1:IFsN6K9NfGtjeggFP+68I4chLZV2yIKsXJFNZ+eWh6s=
|
|||
github.com/muesli/reflow v0.3.0/go.mod h1:pbwTDkVPibjO2kyvBQRBxTWEEGDGq0FlB1BIKtnHY/8=
|
||||
github.com/muesli/termenv v0.15.2 h1:GohcuySI0QmI3wN8Ok9PtKGkgkFIk7y6Vpb5PvrY+Wo=
|
||||
github.com/muesli/termenv v0.15.2/go.mod h1:Epx+iuz8sNs7mNKhxzH4fWXGNpZwUaJKRS1noLXviQ8=
|
||||
github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM=
|
||||
github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE=
|
||||
github.com/power-devops/perfstat v0.0.0-20221212215047-62379fc7944b h1:0LFwY6Q3gMACTjAbMZBjXAqTOzOwFaj2Ld6cjeQ7Rig=
|
||||
github.com/power-devops/perfstat v0.0.0-20221212215047-62379fc7944b/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE=
|
||||
github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 h1:o4JXh1EVt9k/+g42oCprj/FisM4qX9L3sZB3upGN2ZU=
|
||||
github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE=
|
||||
github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
|
||||
|
@ -152,12 +144,12 @@ github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUc
|
|||
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
|
||||
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
|
||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/sahilm/fuzzy v0.1.1-0.20230530133925-c48e322e2a8f h1:MvTmaQdww/z0Q4wrYjDSCcZ78NoftLQyHBSLW/Cx79Y=
|
||||
github.com/sahilm/fuzzy v0.1.1-0.20230530133925-c48e322e2a8f/go.mod h1:VFvziUEIMCrT6A6tw2RFIXPXXmzXbOsSHF0DOI8ZK9Y=
|
||||
github.com/sahilm/fuzzy v0.1.1 h1:ceu5RHF8DGgoi+/dR5PsECjCDH1BE3Fnmpo7aVXOdRA=
|
||||
github.com/sahilm/fuzzy v0.1.1/go.mod h1:VFvziUEIMCrT6A6tw2RFIXPXXmzXbOsSHF0DOI8ZK9Y=
|
||||
github.com/sergi/go-diff v1.3.1 h1:xkr+Oxo4BOQKmkn/B9eMK0g5Kg/983T9DqqPHwYqD+8=
|
||||
github.com/sergi/go-diff v1.3.1/go.mod h1:aMJSSKb2lpPvRNec0+w3fl7LP9IOFzdc9Pa4NFbPK1I=
|
||||
github.com/shirou/gopsutil/v3 v3.24.1 h1:R3t6ondCEvmARp3wxODhXMTLC/klMa87h2PHUw5m7QI=
|
||||
github.com/shirou/gopsutil/v3 v3.24.1/go.mod h1:UU7a2MSBQa+kW1uuDq8DeEBS8kmrnQwsv2b5O513rwU=
|
||||
github.com/shirou/gopsutil/v3 v3.24.4 h1:dEHgzZXt4LMNm+oYELpzl9YCqV65Yr/6SfrvgRBtXeU=
|
||||
github.com/shirou/gopsutil/v3 v3.24.4/go.mod h1:lTd2mdiOspcqLgAnr9/nGi71NkeMpWKdmhuxm9GusH8=
|
||||
github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM=
|
||||
github.com/shoenig/go-m1cpu v0.1.6/go.mod h1:1JJMcUBvfNwpq05QDQVAnx3gUHr9IYF7GNg9SUEw2VQ=
|
||||
github.com/shoenig/test v0.6.4 h1:kVTaSd7WLz5WZ2IaoM0RSzRsUD+m8wRR+5qvntpn4LU=
|
||||
|
@ -177,16 +169,16 @@ github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An
|
|||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||
github.com/stretchr/objx v0.5.1 h1:4VhoImhV/Bm0ToFkXFi8hXNXwpDRZ/ynw3amt82mzq0=
|
||||
github.com/stretchr/objx v0.5.1/go.mod h1:/iHQpkQwBD6DLUmQ4pE+s1TXdob1mORJ4/UFdrifcy0=
|
||||
github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
|
||||
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
|
||||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
|
||||
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||
github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI=
|
||||
github.com/tklauser/go-sysconf v0.3.13 h1:GBUpcahXSpR2xN01jhkNAbTLRk2Yzgggk8IM08lq3r4=
|
||||
github.com/tklauser/go-sysconf v0.3.13/go.mod h1:zwleP4Q4OehZHGn4CYZDipCgg9usW5IJePewFCGVEa0=
|
||||
|
@ -199,37 +191,39 @@ github.com/wayneashleyberry/terminal-dimensions v1.1.0/go.mod h1:2lc/0eWCObmhRcz
|
|||
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e h1:JVG44RsyaB9T2KIHavMF/ppJZNG9ZpyihvCd0w101no=
|
||||
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e/go.mod h1:RbqR21r5mrJuqunuUZ/Dhy/avygyECGrLceyNeo4LiM=
|
||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||
github.com/yusufpapurcu/wmi v1.2.3/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
|
||||
github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0=
|
||||
github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
|
||||
github.com/zclconf/go-cty v1.14.2 h1:kTG7lqmBou0Zkx35r6HJHUQTvaRPr5bIAf3AoHS0izI=
|
||||
github.com/zclconf/go-cty v1.14.2/go.mod h1:VvMs5i0vgZdhYawQNq5kePSpLAoz8u1xvZgrPIxfnZE=
|
||||
github.com/zclconf/go-cty v1.14.3 h1:1JXy1XroaGrzZuG6X9dt7HL6s9AwbY+l4UNL8o5B6ho=
|
||||
github.com/zclconf/go-cty v1.14.3/go.mod h1:VvMs5i0vgZdhYawQNq5kePSpLAoz8u1xvZgrPIxfnZE=
|
||||
github.com/zclconf/go-cty-debug v0.0.0-20191215020915-b22d67c1ba0b h1:FosyBZYxY34Wul7O/MSKey3txpPYyCqVO5ZyceuQJEI=
|
||||
github.com/zclconf/go-cty-debug v0.0.0-20191215020915-b22d67c1ba0b/go.mod h1:ZRKQfBXbGkpdV6QMzT3rU1kSTAnfu1dO8dPKjYprgj8=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4=
|
||||
golang.org/x/crypto v0.19.0 h1:ENy+Az/9Y1vSrlrvBSyna3PITt4tiZLf7sgCjZBX7Wo=
|
||||
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
|
||||
golang.org/x/exp v0.0.0-20240205201215-2c58cdc269a3 h1:/RIbNt/Zr7rVhIkQhooTxCxFcdWLGIKnZA4IXNFSrvo=
|
||||
golang.org/x/exp v0.0.0-20240205201215-2c58cdc269a3/go.mod h1:idGWGoKP1toJGkd5/ig9ZLuPcZBC3ewk7SzmH0uou08=
|
||||
golang.org/x/image v0.15.0 h1:kOELfmgrmJlw4Cdb7g/QGuB3CvDrXbqEIww/pNtNBm8=
|
||||
golang.org/x/image v0.15.0/go.mod h1:HUYqC05R2ZcZ3ejNQsIHQDQiwWM4JBqmm6MKANTp4LE=
|
||||
golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA=
|
||||
golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs=
|
||||
golang.org/x/exp v0.0.0-20240222234643-814bf88cf225 h1:LfspQV/FYTatPTr/3HzIcmiUFH7PGP+OQ6mgDYo3yuQ=
|
||||
golang.org/x/exp v0.0.0-20240222234643-814bf88cf225/go.mod h1:CxmFvTBINI24O/j8iY7H1xHzx2i4OsyguNBmN/uPtqc=
|
||||
golang.org/x/image v0.16.0 h1:9kloLAKhUufZhA12l5fwnx2NZW39/we1UhBesW433jw=
|
||||
golang.org/x/image v0.16.0/go.mod h1:ugSZItdV4nOxyqp56HmXwH0Ry0nBCpjnZdpDaIHdoPs=
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||
golang.org/x/mod v0.15.0 h1:SernR4v+D55NyBH2QiEQrlBAnj1ECL6AGrA5+dPaMY8=
|
||||
golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||
golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA=
|
||||
golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ=
|
||||
golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M=
|
||||
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
|
@ -238,26 +232,26 @@ golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y=
|
||||
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y=
|
||||
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc=
|
||||
golang.org/x/term v0.17.0 h1:mkTF7LCd6WGJNL3K1Ad7kwxNfYAW6a8a8QqtMblp/4U=
|
||||
golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
|
||||
golang.org/x/term v0.20.0 h1:VnkxpohqXaOBYJtBmEppKUG6mXpi+4O6purfc2+sMhw=
|
||||
golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
|
||||
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
golang.org/x/text v0.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk=
|
||||
golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||
golang.org/x/tools v0.17.0 h1:FvmRgNOcs3kOa+T20R1uhfP9F6HgG2mfxDv1vrx1Htc=
|
||||
golang.org/x/tools v0.17.0/go.mod h1:xsh6VxdV005rRVaS6SSAf9oiAqljS7UZUacMZ8Bnsps=
|
||||
golang.org/x/tools v0.19.0 h1:tfGCXNR1OsFG+sVdLAitlpjAvD/I6dHDKnYrpEZUHkw=
|
||||
golang.org/x/tools v0.19.0/go.mod h1:qoJWxmGSIBmAeriMx19ogtrEPrGtDbPK634QFIcLAhc=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 h1:+cNy6SZtPcJQH3LJVLOSmiC7MMxXNOb3PU/VUEz+EhU=
|
||||
|
|
|
@ -144,9 +144,11 @@ func systemGet(idx int) (*battery, error) {
|
|||
2|16, // DIGCF_PRESENT|DIGCF_DEVICEINTERFACE
|
||||
0, 0,
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
defer func() {
|
||||
_, _, _ = syscall.Syscall(setupDiDestroyDeviceInfoList.Addr(), 1, hdev, 0, 0) //nolint:staticcheck
|
||||
}()
|
||||
|
@ -163,12 +165,15 @@ func systemGet(idx int) (*battery, error) {
|
|||
uintptr(unsafe.Pointer(&did)),
|
||||
0,
|
||||
)
|
||||
|
||||
if errno == 259 { // ERROR_NO_MORE_ITEMS
|
||||
return nil, ErrNotFound
|
||||
}
|
||||
|
||||
if errno != 0 {
|
||||
return nil, errno
|
||||
}
|
||||
|
||||
var cbRequired uint32
|
||||
errno = setupDiCall(
|
||||
setupDiGetDeviceInterfaceDetailW,
|
||||
|
@ -180,9 +185,11 @@ func systemGet(idx int) (*battery, error) {
|
|||
uintptr(unsafe.Pointer(&cbRequired)),
|
||||
0,
|
||||
)
|
||||
|
||||
if errno != 0 && errno != 122 { // ERROR_INSUFFICIENT_BUFFER
|
||||
return nil, errno
|
||||
}
|
||||
|
||||
// The god damn struct with ANYSIZE_ARRAY of utf16 in it is crazy.
|
||||
// So... let's emulate it with array of uint16 ;-D.
|
||||
// Keep in mind that the first two elements are actually cbSize.
|
||||
|
@ -193,6 +200,7 @@ func systemGet(idx int) (*battery, error) {
|
|||
} else {
|
||||
*cbSize = 6
|
||||
}
|
||||
|
||||
errno = setupDiCall(
|
||||
setupDiGetDeviceInterfaceDetailW,
|
||||
6,
|
||||
|
@ -203,9 +211,11 @@ func systemGet(idx int) (*battery, error) {
|
|||
uintptr(unsafe.Pointer(&cbRequired)),
|
||||
0,
|
||||
)
|
||||
|
||||
if errno != 0 {
|
||||
return nil, errno
|
||||
}
|
||||
|
||||
devicePath := &didd[2:][0]
|
||||
|
||||
handle, err := windows.CreateFile(
|
||||
|
@ -217,9 +227,11 @@ func systemGet(idx int) (*battery, error) {
|
|||
windows.FILE_ATTRIBUTE_NORMAL,
|
||||
0,
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
defer func() {
|
||||
_ = windows.CloseHandle(handle)
|
||||
}()
|
||||
|
@ -238,9 +250,11 @@ func systemGet(idx int) (*battery, error) {
|
|||
&dwOut,
|
||||
nil,
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if bqi.BatteryTag == 0 {
|
||||
return nil, errors.New("BatteryTag not returned")
|
||||
}
|
||||
|
@ -258,6 +272,7 @@ func systemGet(idx int) (*battery, error) {
|
|||
&dwOut,
|
||||
nil,
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -276,6 +291,7 @@ func systemGet(idx int) (*battery, error) {
|
|||
&dwOut,
|
||||
nil,
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -283,9 +299,11 @@ func systemGet(idx int) (*battery, error) {
|
|||
if b.Current, err = uint32ToFloat64(bs.Capacity); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if b.Voltage, err = uint32ToFloat64(bs.Voltage); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
b.Voltage /= 1000
|
||||
b.State = readState(bs.PowerState)
|
||||
|
||||
|
|
|
@ -37,7 +37,7 @@ func mapMostLogicalState(currentState, newState State) State {
|
|||
return newState
|
||||
}
|
||||
|
||||
// GetAll returns information about all batteries in the system.
|
||||
// Get returns information about all batteries in the system.
|
||||
//
|
||||
// If error != nil, it will be either ErrFatal or Errors.
|
||||
// If error is of type Errors, it is guaranteed that length of both returned slices is the same and that i-th error coresponds with i-th battery structure.
|
||||
|
|
|
@ -2,15 +2,46 @@ package platform
|
|||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
type Cache interface {
|
||||
Init(home string)
|
||||
Close()
|
||||
// Gets the value for a given key.
|
||||
// Returns the value and a boolean indicating if the key was found.
|
||||
// In case the ttl expired, the function returns false.
|
||||
Get(key string) (string, bool)
|
||||
// Sets a value for a given key.
|
||||
// The ttl indicates how many minutes to cache the value.
|
||||
Set(key, value string, ttl int)
|
||||
// Deletes a key from the cache.
|
||||
Delete(key string)
|
||||
}
|
||||
|
||||
const (
|
||||
CacheFile = "/omp.cache"
|
||||
)
|
||||
|
||||
func pid() string {
|
||||
pid := os.Getenv("POSH_PID")
|
||||
if len(pid) == 0 {
|
||||
pid = strconv.Itoa(os.Getppid())
|
||||
}
|
||||
return pid
|
||||
}
|
||||
|
||||
var (
|
||||
TEMPLATECACHE = fmt.Sprintf("template_cache_%s", pid())
|
||||
TOGGLECACHE = fmt.Sprintf("toggle_cache_%s", pid())
|
||||
PROMPTCOUNTCACHE = fmt.Sprintf("prompt_count_cache_%s", pid())
|
||||
)
|
||||
|
||||
type cacheObject struct {
|
||||
Value string `json:"value"`
|
||||
Timestamp int64 `json:"timestamp"`
|
||||
|
@ -91,3 +122,50 @@ func (fc *fileCache) Delete(key string) {
|
|||
fc.cache.Delete(key)
|
||||
fc.dirty = true
|
||||
}
|
||||
|
||||
type commandCache struct {
|
||||
commands *ConcurrentMap
|
||||
}
|
||||
|
||||
func (c *commandCache) set(command, path string) {
|
||||
c.commands.Set(command, path)
|
||||
}
|
||||
|
||||
func (c *commandCache) get(command string) (string, bool) {
|
||||
cacheCommand, found := c.commands.Get(command)
|
||||
if !found {
|
||||
return "", false
|
||||
}
|
||||
command, ok := cacheCommand.(string)
|
||||
return command, ok
|
||||
}
|
||||
|
||||
type TemplateCache struct {
|
||||
Root bool
|
||||
PWD string
|
||||
Folder string
|
||||
Shell string
|
||||
ShellVersion string
|
||||
UserName string
|
||||
HostName string
|
||||
Code int
|
||||
Env map[string]string
|
||||
Var SimpleMap
|
||||
OS string
|
||||
WSL bool
|
||||
PromptCount int
|
||||
SHLVL int
|
||||
Segments *ConcurrentMap
|
||||
SegmentsCache SimpleMap
|
||||
|
||||
initialized bool
|
||||
sync.RWMutex
|
||||
}
|
||||
|
||||
func (t *TemplateCache) AddSegmentData(key string, value any) {
|
||||
t.Segments.Set(key, value)
|
||||
}
|
||||
|
||||
func (t *TemplateCache) RemoveSegmentData(key string) {
|
||||
t.Segments.Delete(key)
|
||||
}
|
||||
|
|
|
@ -37,20 +37,6 @@ const (
|
|||
CMD = "cmd"
|
||||
)
|
||||
|
||||
func pid() string {
|
||||
pid := os.Getenv("POSH_PID")
|
||||
if len(pid) == 0 {
|
||||
pid = strconv.Itoa(os.Getppid())
|
||||
}
|
||||
return pid
|
||||
}
|
||||
|
||||
var (
|
||||
TEMPLATECACHE = fmt.Sprintf("template_cache_%s", pid())
|
||||
TOGGLECACHE = fmt.Sprintf("toggle_cache_%s", pid())
|
||||
PROMPTCOUNTCACHE = fmt.Sprintf("prompt_count_cache_%s", pid())
|
||||
)
|
||||
|
||||
type Flags struct {
|
||||
ErrorCode int
|
||||
PipeStatus string
|
||||
|
@ -92,20 +78,6 @@ type FileInfo struct {
|
|||
IsDir bool
|
||||
}
|
||||
|
||||
type Cache interface {
|
||||
Init(home string)
|
||||
Close()
|
||||
// Gets the value for a given key.
|
||||
// Returns the value and a boolean indicating if the key was found.
|
||||
// In case the ttl expired, the function returns false.
|
||||
Get(key string) (string, bool)
|
||||
// Sets a value for a given key.
|
||||
// The ttl indicates how many minutes to cache the value.
|
||||
Set(key, value string, ttl int)
|
||||
// Deletes a key from the cache.
|
||||
Delete(key string)
|
||||
}
|
||||
|
||||
type HTTPRequestModifier func(request *http.Request)
|
||||
|
||||
type WindowsRegistryValueType string
|
||||
|
@ -168,36 +140,6 @@ type SystemInfo struct {
|
|||
Disks map[string]disk.IOCountersStat
|
||||
}
|
||||
|
||||
type TemplateCache struct {
|
||||
Root bool
|
||||
PWD string
|
||||
Folder string
|
||||
Shell string
|
||||
ShellVersion string
|
||||
UserName string
|
||||
HostName string
|
||||
Code int
|
||||
Env map[string]string
|
||||
Var SimpleMap
|
||||
OS string
|
||||
WSL bool
|
||||
PromptCount int
|
||||
SHLVL int
|
||||
Segments *ConcurrentMap
|
||||
SegmentsCache SimpleMap
|
||||
|
||||
initialized bool
|
||||
sync.RWMutex
|
||||
}
|
||||
|
||||
func (t *TemplateCache) AddSegmentData(key string, value any) {
|
||||
t.Segments.Set(key, value)
|
||||
}
|
||||
|
||||
func (t *TemplateCache) RemoveSegmentData(key string) {
|
||||
t.Segments.Delete(key)
|
||||
}
|
||||
|
||||
type Environment interface {
|
||||
Getenv(key string) string
|
||||
Pwd() string
|
||||
|
@ -253,34 +195,20 @@ type Environment interface {
|
|||
Trace(start time.Time, args ...string)
|
||||
}
|
||||
|
||||
type commandCache struct {
|
||||
commands *ConcurrentMap
|
||||
}
|
||||
|
||||
func (c *commandCache) set(command, path string) {
|
||||
c.commands.Set(command, path)
|
||||
}
|
||||
|
||||
func (c *commandCache) get(command string) (string, bool) {
|
||||
cacheCommand, found := c.commands.Get(command)
|
||||
if !found {
|
||||
return "", false
|
||||
}
|
||||
command, ok := cacheCommand.(string)
|
||||
return command, ok
|
||||
}
|
||||
|
||||
type Shell struct {
|
||||
CmdFlags *Flags
|
||||
Var SimpleMap
|
||||
|
||||
cwd string
|
||||
host string
|
||||
cmdCache *commandCache
|
||||
fileCache *fileCache
|
||||
tmplCache *TemplateCache
|
||||
networks []*Connection
|
||||
|
||||
sync.RWMutex
|
||||
|
||||
lsDirMap ConcurrentMap
|
||||
}
|
||||
|
||||
func (env *Shell) Init() {
|
||||
|
@ -430,20 +358,37 @@ func (env *Shell) Pwd() string {
|
|||
}
|
||||
|
||||
func (env *Shell) HasFiles(pattern string) bool {
|
||||
return env.HasFilesInDir(env.Pwd(), pattern)
|
||||
}
|
||||
|
||||
func (env *Shell) HasFilesInDir(dir, pattern string) bool {
|
||||
defer env.Trace(time.Now(), pattern)
|
||||
|
||||
cwd := env.Pwd()
|
||||
fileSystem := os.DirFS(cwd)
|
||||
fileSystem := os.DirFS(dir)
|
||||
var dirEntries []fs.DirEntry
|
||||
|
||||
matches, err := fs.ReadDir(fileSystem, ".")
|
||||
if err != nil {
|
||||
env.Error(err)
|
||||
env.Debug("false")
|
||||
return false
|
||||
if files, OK := env.lsDirMap.Get(dir); OK {
|
||||
dirEntries, _ = files.([]fs.DirEntry)
|
||||
}
|
||||
|
||||
if len(dirEntries) == 0 {
|
||||
var err error
|
||||
dirEntries, err = fs.ReadDir(fileSystem, ".")
|
||||
if err != nil {
|
||||
env.Error(err)
|
||||
env.Debug("false")
|
||||
return false
|
||||
}
|
||||
|
||||
env.lsDirMap.Set(dir, dirEntries)
|
||||
}
|
||||
|
||||
pattern = strings.ToLower(pattern)
|
||||
for _, match := range matches {
|
||||
|
||||
env.RWMutex.RLock()
|
||||
defer env.RWMutex.RUnlock()
|
||||
|
||||
for _, match := range dirEntries {
|
||||
if match.IsDir() {
|
||||
continue
|
||||
}
|
||||
|
@ -465,20 +410,6 @@ func (env *Shell) HasFiles(pattern string) bool {
|
|||
return false
|
||||
}
|
||||
|
||||
func (env *Shell) HasFilesInDir(dir, pattern string) bool {
|
||||
defer env.Trace(time.Now(), pattern)
|
||||
fileSystem := os.DirFS(dir)
|
||||
matches, err := fs.Glob(fileSystem, pattern)
|
||||
if err != nil {
|
||||
env.Error(err)
|
||||
env.Debug("false")
|
||||
return false
|
||||
}
|
||||
hasFilesInDir := len(matches) > 0
|
||||
env.DebugF("%t", hasFilesInDir)
|
||||
return hasFilesInDir
|
||||
}
|
||||
|
||||
func (env *Shell) HasFileInParentDirs(pattern string, depth uint) bool {
|
||||
defer env.Trace(time.Now(), pattern, fmt.Sprint(depth))
|
||||
currentFolder := env.Pwd()
|
||||
|
@ -566,13 +497,20 @@ func (env *Shell) User() string {
|
|||
|
||||
func (env *Shell) Host() (string, error) {
|
||||
defer env.Trace(time.Now())
|
||||
if len(env.host) != 0 {
|
||||
return env.host, nil
|
||||
}
|
||||
|
||||
hostName, err := os.Hostname()
|
||||
if err != nil {
|
||||
env.Error(err)
|
||||
return "", err
|
||||
}
|
||||
|
||||
hostName = cleanHostName(hostName)
|
||||
env.Debug(hostName)
|
||||
env.host = hostName
|
||||
|
||||
return hostName, nil
|
||||
}
|
||||
|
||||
|
|
|
@ -33,8 +33,8 @@ func (c *Bazel) Init(props properties.Properties, env platform.Environment) {
|
|||
regex: `bazel (?P<version>((?P<major>[0-9]+).(?P<minor>[0-9]+).(?P<patch>[0-9]+)))`,
|
||||
},
|
||||
},
|
||||
// Use the correct URL for Bazel 6.x. it does not have the docs subdomain.
|
||||
versionURLTemplate: "https://{{ if ne .Major \"6\" }}docs.{{ end }}bazel.build/versions/{{ .Major }}.{{ .Minor }}.{{ .Patch }}",
|
||||
// Use the correct URL for Bazel >5.4.1, since they do not have the docs subdomain.
|
||||
versionURLTemplate: "https://{{ if lt .Major 6 }}docs.{{ end }}bazel.build/versions/{{ .Major }}.{{ .Minor }}.{{ .Patch }}",
|
||||
}
|
||||
c.Icon = props.GetString(Icon, "\ue63a")
|
||||
}
|
||||
|
|
|
@ -14,9 +14,12 @@ func TestBazel(t *testing.T) {
|
|||
Version string
|
||||
Template string
|
||||
}{
|
||||
{Case: "bazel 4.0.0", ExpectedString: "<LINK>https://docs.bazel.build/versions/4.0.0<TEXT>\ue63a</TEXT></LINK> 4.0.0", Version: "bazel 4.0.0", Template: ""},
|
||||
{Case: "bazel 5.4.1", ExpectedString: "<LINK>https://docs.bazel.build/versions/5.4.1<TEXT>\ue63a</TEXT></LINK> 5.4.1", Version: "bazel 5.4.1", Template: ""},
|
||||
{Case: "bazel 6.4.0", ExpectedString: "<LINK>https://bazel.build/versions/6.4.0<TEXT>\ue63a</TEXT></LINK> 6.4.0", Version: "bazel 6.4.0", Template: ""},
|
||||
{Case: "bazel 10.11.12", ExpectedString: "<LINK>https://docs.bazel.build/versions/3.7.0<TEXT>\ue63a</TEXT></LINK> 3.7.0", Version: "bazel 3.7.0"},
|
||||
{Case: "", ExpectedString: "\ue63a err parsing info from bazel with", Version: ""},
|
||||
{Case: "bazel 7.1.1", ExpectedString: "<LINK>https://bazel.build/versions/7.1.1<TEXT>\ue63a</TEXT></LINK> 7.1.1", Version: "bazel 7.1.1", Template: ""},
|
||||
{Case: "bazel 10.11.12", ExpectedString: "<LINK>https://bazel.build/versions/10.11.12<TEXT>\ue63a</TEXT></LINK> 10.11.12", Version: "bazel 10.11.12", Template: ""},
|
||||
{Case: "", ExpectedString: "\ue63a err parsing info from bazel with", Version: "", Template: ""},
|
||||
}
|
||||
for _, tc := range cases {
|
||||
params := &mockedLanguageParams{
|
||||
|
|
|
@ -21,6 +21,8 @@ const (
|
|||
Command properties.Property = "command"
|
||||
// Command to execute
|
||||
Script properties.Property = "script"
|
||||
// Interpret execution, or not
|
||||
Interpret properties.Property = "interpret"
|
||||
)
|
||||
|
||||
func (c *Cmd) Template() string {
|
||||
|
@ -32,18 +34,28 @@ func (c *Cmd) Enabled() bool {
|
|||
if !c.env.HasCommand(shell) {
|
||||
return false
|
||||
}
|
||||
|
||||
command := c.props.GetString(Command, "")
|
||||
if len(command) != 0 {
|
||||
return c.runCommand(shell, command)
|
||||
}
|
||||
|
||||
script := c.props.GetString(Script, "")
|
||||
if len(script) != 0 {
|
||||
return c.runScript(shell, script)
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func (c *Cmd) runCommand(shell, command string) bool {
|
||||
interpret := c.props.GetBool(Interpret, true)
|
||||
|
||||
if !interpret {
|
||||
c.Output = c.env.RunShellCommand(shell, command)
|
||||
return len(c.Output) != 0
|
||||
}
|
||||
|
||||
if strings.Contains(command, "||") {
|
||||
commands := strings.Split(command, "||")
|
||||
for _, cmd := range commands {
|
||||
|
@ -54,6 +66,7 @@ func (c *Cmd) runCommand(shell, command string) bool {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
if strings.Contains(command, "&&") {
|
||||
var output string
|
||||
commands := strings.Split(command, "&&")
|
||||
|
@ -63,6 +76,7 @@ func (c *Cmd) runCommand(shell, command string) bool {
|
|||
c.Output = output
|
||||
return len(c.Output) != 0
|
||||
}
|
||||
|
||||
c.Output = c.env.RunShellCommand(shell, strings.TrimSpace(command))
|
||||
return len(c.Output) != 0
|
||||
}
|
||||
|
|
|
@ -136,6 +136,23 @@ func TestExecuteMultipleCommandsOrDisabled(t *testing.T) {
|
|||
assert.False(t, enabled)
|
||||
}
|
||||
|
||||
func TestExecuteNonInterpretedCommand(t *testing.T) {
|
||||
env := new(mock.MockedEnvironment)
|
||||
env.On("HasCommand", "bash").Return(true)
|
||||
env.On("RunShellCommand", "bash", "echo hello && echo world").Return("hello world")
|
||||
props := properties.Map{
|
||||
Command: "echo hello && echo world",
|
||||
Interpret: false,
|
||||
}
|
||||
c := &Cmd{
|
||||
props: props,
|
||||
env: env,
|
||||
}
|
||||
enabled := c.Enabled()
|
||||
assert.True(t, enabled)
|
||||
assert.Equal(t, "hello world", renderTemplate(env, c.Template(), c))
|
||||
}
|
||||
|
||||
func TestExecuteScript(t *testing.T) {
|
||||
cases := []struct {
|
||||
Case string
|
||||
|
|
84
src/segments/firebase.go
Normal file
84
src/segments/firebase.go
Normal file
|
@ -0,0 +1,84 @@
|
|||
package segments
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/jandedobbeleer/oh-my-posh/src/platform"
|
||||
"github.com/jandedobbeleer/oh-my-posh/src/properties"
|
||||
)
|
||||
|
||||
const (
|
||||
FIREBASENOACTIVECONFIG = "NO ACTIVE CONFIG FOUND"
|
||||
)
|
||||
|
||||
type Firebase struct {
|
||||
props properties.Properties
|
||||
env platform.Environment
|
||||
|
||||
Project string
|
||||
}
|
||||
|
||||
type FirebaseData struct {
|
||||
ActiveProject map[string]string `json:"activeProjects"`
|
||||
}
|
||||
|
||||
func (f *Firebase) Template() string {
|
||||
return " {{ .Project}} "
|
||||
}
|
||||
|
||||
func (f *Firebase) Init(props properties.Properties, env platform.Environment) {
|
||||
f.props = props
|
||||
f.env = env
|
||||
}
|
||||
|
||||
func (f *Firebase) Enabled() bool {
|
||||
cfgDir := filepath.Join(f.env.Home(), ".config", "configstore")
|
||||
configFile, err := f.getActiveConfig(cfgDir)
|
||||
if err != nil {
|
||||
f.env.Error(err)
|
||||
return false
|
||||
}
|
||||
|
||||
data, err := f.getFirebaseData(configFile)
|
||||
if err != nil {
|
||||
f.env.Error(err)
|
||||
return false
|
||||
}
|
||||
|
||||
// Within the activeProjects is a key value pair
|
||||
// of the path to the project and the project name
|
||||
|
||||
// Test if the current directory is a project path
|
||||
// and if it is, return the project name
|
||||
for key, value := range data.ActiveProject {
|
||||
if strings.HasPrefix(f.env.Pwd(), key) {
|
||||
f.Project = value
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func (f *Firebase) getActiveConfig(cfgDir string) (string, error) {
|
||||
activeConfigFile := filepath.Join(cfgDir, "firebase-tools.json")
|
||||
activeConfigData := f.env.FileContent(activeConfigFile)
|
||||
if len(activeConfigData) == 0 {
|
||||
return "", errors.New(FIREBASENOACTIVECONFIG)
|
||||
}
|
||||
return activeConfigData, nil
|
||||
}
|
||||
|
||||
func (f *Firebase) getFirebaseData(configFile string) (*FirebaseData, error) {
|
||||
var data FirebaseData
|
||||
|
||||
err := json.Unmarshal([]byte(configFile), &data)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &data, nil
|
||||
}
|
116
src/segments/firebase_test.go
Normal file
116
src/segments/firebase_test.go
Normal file
|
@ -0,0 +1,116 @@
|
|||
package segments
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"github.com/jandedobbeleer/oh-my-posh/src/mock"
|
||||
"github.com/stretchr/testify/assert"
|
||||
mock2 "github.com/stretchr/testify/mock"
|
||||
)
|
||||
|
||||
func TestFirebaseSegment(t *testing.T) {
|
||||
config := `{
|
||||
"activeProjects": {
|
||||
"path": "project-name"
|
||||
}
|
||||
}`
|
||||
cases := []struct {
|
||||
Case string
|
||||
ActiveConfig string
|
||||
ActivePath string
|
||||
ExpectedEnabled bool
|
||||
ExpectedString string
|
||||
}{
|
||||
{
|
||||
Case: "happy path",
|
||||
ExpectedEnabled: true,
|
||||
ActiveConfig: config,
|
||||
ActivePath: "path",
|
||||
ExpectedString: "project-name",
|
||||
},
|
||||
{
|
||||
Case: "happy subpath",
|
||||
ExpectedEnabled: true,
|
||||
ActiveConfig: config,
|
||||
ActivePath: "path/subpath",
|
||||
ExpectedString: "project-name",
|
||||
},
|
||||
{
|
||||
Case: "no active config",
|
||||
ExpectedEnabled: false,
|
||||
},
|
||||
{
|
||||
Case: "empty config",
|
||||
ActiveConfig: "{}",
|
||||
ExpectedEnabled: false,
|
||||
},
|
||||
{
|
||||
Case: "bad config",
|
||||
ActiveConfig: "{bad}",
|
||||
ExpectedEnabled: false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
env := new(mock.MockedEnvironment)
|
||||
env.On("Home").Return("home")
|
||||
env.On("Pwd").Return(tc.ActivePath)
|
||||
fcPath := filepath.Join("home", ".config", "configstore", "firebase-tools.json")
|
||||
env.On("FileContent", fcPath).Return(tc.ActiveConfig)
|
||||
env.On("Error", mock2.Anything).Return()
|
||||
f := Firebase{
|
||||
env: env,
|
||||
}
|
||||
f.Enabled()
|
||||
assert.Equal(t, tc.ExpectedEnabled, f.Enabled())
|
||||
if tc.ExpectedEnabled {
|
||||
assert.Equal(t, tc.ExpectedString, renderTemplate(env, f.Template(), f), tc.Case)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetFirebaseActiveConfig(t *testing.T) {
|
||||
data :=
|
||||
`{
|
||||
"activeProjects": {
|
||||
"path": "project-name"
|
||||
}
|
||||
}`
|
||||
cases := []struct {
|
||||
Case string
|
||||
ActiveConfig string
|
||||
ExpectedString string
|
||||
ExpectedError string
|
||||
}{
|
||||
{
|
||||
Case: "happy path",
|
||||
ActiveConfig: data,
|
||||
ExpectedString: data,
|
||||
},
|
||||
{
|
||||
Case: "no active config",
|
||||
ActiveConfig: "",
|
||||
ExpectedError: FIREBASENOACTIVECONFIG,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
env := new(mock.MockedEnvironment)
|
||||
env.On("Home").Return("home")
|
||||
configPath := filepath.Join("home", ".config", "configstore")
|
||||
contentPath := filepath.Join(configPath, "firebase-tools.json")
|
||||
env.On("FileContent", contentPath).Return(tc.ActiveConfig)
|
||||
env.On("Error", mock2.Anything).Return()
|
||||
f := Firebase{
|
||||
env: env,
|
||||
}
|
||||
got, err := f.getActiveConfig(configPath)
|
||||
assert.Equal(t, tc.ExpectedString, got, tc.Case)
|
||||
if len(tc.ExpectedError) > 0 {
|
||||
assert.EqualError(t, err, tc.ExpectedError, tc.Case)
|
||||
} else {
|
||||
assert.NoError(t, err, tc.Case)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -22,7 +22,7 @@ func TestGolang(t *testing.T) {
|
|||
}{
|
||||
{Case: "Go 1.15", ExpectedString: "1.15.8", Version: "go version go1.15.8 darwin/amd64"},
|
||||
{Case: "Go 1.16", ExpectedString: "1.16", Version: "go version go1.16 darwin/amd64"},
|
||||
{Case: "go.mod 1.21", ParseModFile: true, HasModFileInParentDir: true, ExpectedString: "1.21"},
|
||||
{Case: "go.mod 1.22.3", ParseModFile: true, HasModFileInParentDir: true, ExpectedString: "1.22.3"},
|
||||
{Case: "no go.mod file fallback", ParseModFile: true, ExpectedString: "1.16", Version: "go version go1.16 darwin/amd64"},
|
||||
{
|
||||
Case: "invalid go.mod file fallback",
|
||||
|
|
|
@ -19,7 +19,7 @@ func (h *Helm) Enabled() bool {
|
|||
}
|
||||
|
||||
inChart := false
|
||||
files := []string{"Chart.yml", "Chart.yaml"}
|
||||
files := []string{"Chart.yml", "Chart.yaml", "helmfile.yaml", "helmfile.yml"}
|
||||
for _, file := range files {
|
||||
if _, err := h.env.HasParentFilePath(file); err == nil {
|
||||
inChart = true
|
||||
|
|
|
@ -57,6 +57,22 @@ func TestHelmSegment(t *testing.T) {
|
|||
DisplayMode: "files",
|
||||
ChartFile: "Chart.yaml",
|
||||
},
|
||||
{
|
||||
Case: "DisplayMode always inside chart. Chart file helmfile.yaml",
|
||||
HelmExists: true,
|
||||
ExpectedEnabled: true,
|
||||
ExpectedString: "Helm 3.12.3",
|
||||
DisplayMode: "files",
|
||||
ChartFile: "helmfile.yaml",
|
||||
},
|
||||
{
|
||||
Case: "DisplayMode always inside chart. Chart file helmfile.yml",
|
||||
HelmExists: true,
|
||||
ExpectedEnabled: true,
|
||||
ExpectedString: "Helm 3.12.3",
|
||||
DisplayMode: "files",
|
||||
ChartFile: "helmfile.yml",
|
||||
},
|
||||
{
|
||||
Case: "DisplayMode always outside chart",
|
||||
HelmExists: true,
|
||||
|
|
|
@ -1,61 +0,0 @@
|
|||
package segments
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/jandedobbeleer/oh-my-posh/src/platform"
|
||||
"github.com/jandedobbeleer/oh-my-posh/src/properties"
|
||||
"github.com/jandedobbeleer/oh-my-posh/src/shell"
|
||||
)
|
||||
|
||||
type ITerm struct {
|
||||
props properties.Properties
|
||||
env platform.Environment
|
||||
|
||||
PromptMark string
|
||||
}
|
||||
|
||||
func (i *ITerm) Template() string {
|
||||
return "{{ .PromptMark }}"
|
||||
}
|
||||
|
||||
func (i *ITerm) Enabled() bool {
|
||||
promptMark, err := i.getResult()
|
||||
if err != nil {
|
||||
i.env.Error(err)
|
||||
return false
|
||||
}
|
||||
i.PromptMark = promptMark
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func (i *ITerm) getResult() (string, error) {
|
||||
var response string
|
||||
// First, check if we're using iTerm
|
||||
if i.env.Getenv("TERM_PROGRAM") != "iTerm.app" {
|
||||
return "", errors.New("Only works with iTerm")
|
||||
}
|
||||
|
||||
// Check to ensure the user has squelched the default mark for BASH and ZSH
|
||||
if i.env.Getenv("ITERM2_SQUELCH_MARK") != "1" {
|
||||
return "", errors.New("iTerm default mark enabled (export ITERM2_SQUELCH_MARK=1)")
|
||||
}
|
||||
|
||||
// Now, set the mark string based on shell (or error out)
|
||||
switch i.env.Shell() {
|
||||
case shell.ZSH:
|
||||
response = `%{$(iterm2_prompt_mark)%}`
|
||||
case shell.BASH:
|
||||
response = `\[$(iterm2_prompt_mark)\]`
|
||||
default:
|
||||
return "", errors.New("Shell isn't compatible with iTerm Shell Integration")
|
||||
}
|
||||
|
||||
return response, nil
|
||||
}
|
||||
|
||||
func (i *ITerm) Init(props properties.Properties, env platform.Environment) {
|
||||
i.props = props
|
||||
i.env = env
|
||||
}
|
|
@ -1,46 +0,0 @@
|
|||
package segments
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/jandedobbeleer/oh-my-posh/src/mock"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
mock2 "github.com/stretchr/testify/mock"
|
||||
)
|
||||
|
||||
func TestITermSegment(t *testing.T) {
|
||||
cases := []struct {
|
||||
Case string
|
||||
TermProgram string
|
||||
SquelchMark string
|
||||
Shell string
|
||||
Template string
|
||||
ExpectedString string
|
||||
ExpectedDisabled bool
|
||||
}{
|
||||
{Case: "not iterm", TermProgram: "", SquelchMark: "1", Shell: "zsh", ExpectedDisabled: true},
|
||||
{Case: "default mark", TermProgram: "iTerm.app", Shell: "zsh", Template: "{{ .PromptMark }}", ExpectedDisabled: true},
|
||||
{Case: "zsh", TermProgram: "iTerm.app", SquelchMark: "1", Shell: "zsh", Template: "{{ .PromptMark }}", ExpectedString: `%{$(iterm2_prompt_mark)%}`},
|
||||
{Case: "bash", TermProgram: "iTerm.app", SquelchMark: "1", Shell: "bash", Template: "{{ .PromptMark }}", ExpectedString: `\[$(iterm2_prompt_mark)\]`},
|
||||
{Case: "fish", TermProgram: "iTerm.app", SquelchMark: "1", Shell: "fish", Template: "{{ .PromptMark }}", ExpectedDisabled: true},
|
||||
{Case: "pwsh", TermProgram: "iTerm.app", SquelchMark: "1", Shell: "pwsh", Template: "{{ .PromptMark }}", ExpectedDisabled: true},
|
||||
{Case: "gibberishshell", TermProgram: "iTerm.app", SquelchMark: "1", Shell: "jaserhuashf", Template: "{{ .PromptMark }}", ExpectedDisabled: true},
|
||||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
env := new(mock.MockedEnvironment)
|
||||
env.On("PathSeparator").Return("/")
|
||||
env.On("Getenv", "TERM_PROGRAM").Return(tc.TermProgram)
|
||||
env.On("Getenv", "ITERM2_SQUELCH_MARK").Return(tc.SquelchMark)
|
||||
env.On("Shell").Return(tc.Shell)
|
||||
env.On("Error", mock2.Anything).Return()
|
||||
iterm := &ITerm{
|
||||
env: env,
|
||||
}
|
||||
assert.Equal(t, !tc.ExpectedDisabled, iterm.Enabled(), tc.Case)
|
||||
if !tc.ExpectedDisabled {
|
||||
assert.Equal(t, tc.ExpectedString, renderTemplate(env, tc.Template, iterm), tc.Case)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -3,6 +3,7 @@ package segments
|
|||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
http2 "net/http"
|
||||
"time"
|
||||
|
||||
"github.com/jandedobbeleer/oh-my-posh/src/platform"
|
||||
|
@ -20,7 +21,8 @@ type Nightscout struct {
|
|||
|
||||
const (
|
||||
// Your complete Nightscout URL and APIKey like this
|
||||
URL properties.Property = "url"
|
||||
URL properties.Property = "url"
|
||||
Headers properties.Property = "headers"
|
||||
|
||||
DoubleUpIcon properties.Property = "doubleup_icon"
|
||||
SingleUpIcon properties.Property = "singleup_icon"
|
||||
|
@ -116,7 +118,14 @@ func (ns *Nightscout) getResult() (*NightscoutData, error) {
|
|||
}
|
||||
}
|
||||
|
||||
body, err := ns.env.HTTPRequest(url, nil, httpTimeout)
|
||||
headers := ns.props.GetKeyValueMap(Headers, map[string]string{})
|
||||
modifiers := func(request *http2.Request) {
|
||||
for key, value := range headers {
|
||||
request.Header.Add(key, value)
|
||||
}
|
||||
}
|
||||
|
||||
body, err := ns.env.HTTPRequest(url, nil, httpTimeout, modifiers)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -136,6 +136,7 @@ func TestNSSegment(t *testing.T) {
|
|||
props := properties.Map{
|
||||
properties.CacheTimeout: tc.CacheTimeout,
|
||||
URL: "FAKE",
|
||||
Headers: map[string]string{"Fake-Header": "xxxxx"},
|
||||
}
|
||||
|
||||
cache := &mock.MockedCache{}
|
||||
|
|
|
@ -32,7 +32,7 @@ func (n *Node) Init(props properties.Properties, env platform.Environment) {
|
|||
n.language = language{
|
||||
env: env,
|
||||
props: props,
|
||||
extensions: []string{"*.js", "*.ts", "package.json", ".nvmrc", "pnpm-workspace.yaml", ".pnpmfile.cjs", ".npmrc", ".vue"},
|
||||
extensions: []string{"*.js", "*.ts", "package.json", ".nvmrc", "pnpm-workspace.yaml", ".pnpmfile.cjs", ".vue"},
|
||||
commands: []*cmd{
|
||||
{
|
||||
executable: "node",
|
||||
|
|
|
@ -54,13 +54,14 @@ func (oi *Os) getDistroIcon(distro string) string {
|
|||
"almalinux": "\uF31D",
|
||||
"almalinux9": "\uF31D",
|
||||
"alpine": "\uF300",
|
||||
"android": "\uF17b",
|
||||
"aosc": "\uF301",
|
||||
"arch": "\uF303",
|
||||
"centos": "\uF304",
|
||||
"coreos": "\uF305",
|
||||
"debian": "\uF306",
|
||||
"deepin": "\uF321",
|
||||
"devuan": "\uF307",
|
||||
"raspbian": "\uF315",
|
||||
"elementary": "\uF309",
|
||||
"fedora": "\uF30a",
|
||||
"gentoo": "\uF30d",
|
||||
|
@ -70,12 +71,12 @@ func (oi *Os) getDistroIcon(distro string) string {
|
|||
"nixos": "\uF313",
|
||||
"opensuse": "\uF314",
|
||||
"opensuse-tumbleweed": "\uF314",
|
||||
"raspbian": "\uF315",
|
||||
"redhat": "\uF316",
|
||||
"rocky": "\uF32B",
|
||||
"sabayon": "\uF317",
|
||||
"slackware": "\uF319",
|
||||
"ubuntu": "\uF31b",
|
||||
"android": "\uf17b",
|
||||
}
|
||||
|
||||
if icon, ok := iconMap[distro]; ok {
|
||||
|
|
|
@ -86,7 +86,7 @@ func TestOWMSegmentSingle(t *testing.T) {
|
|||
for _, tc := range cases {
|
||||
env := &mock.MockedEnvironment{}
|
||||
var props properties.Map
|
||||
if tc.Latitude != 0 && tc.Longitude != 0 && tc.Location != "" {
|
||||
if tc.Latitude != 0 && tc.Longitude != 0 && tc.Location != "" { //nolint: gocritic
|
||||
props = properties.Map{
|
||||
APIKey: "key",
|
||||
Location: tc.Location,
|
||||
|
|
|
@ -25,6 +25,7 @@ type Path struct {
|
|||
Location string
|
||||
Writable bool
|
||||
RootDir bool
|
||||
Folders Folders
|
||||
}
|
||||
|
||||
const (
|
||||
|
@ -48,8 +49,8 @@ const (
|
|||
Short string = "short"
|
||||
// Full displays the full path
|
||||
Full string = "full"
|
||||
// Folder displays the current folder
|
||||
Folder string = "folder"
|
||||
// FolderType displays the current folder
|
||||
FolderType string = "folder"
|
||||
// Mixed like agnoster, but if a folder name is short enough, it is displayed as-is
|
||||
Mixed string = "mixed"
|
||||
// Letter like agnoster, but with the first letter of each folder name
|
||||
|
@ -81,6 +82,12 @@ const (
|
|||
FolderFormat properties.Property = "folder_format"
|
||||
// format to use on the first and last folder of the path
|
||||
EdgeFormat properties.Property = "edge_format"
|
||||
// format to use on first folder of the path
|
||||
LeftFormat properties.Property = "left_format"
|
||||
// format to use on the last folder of the path
|
||||
RightFormat properties.Property = "right_format"
|
||||
// GitDirFormat format to use on the git directory
|
||||
GitDirFormat properties.Property = "gitdir_format"
|
||||
)
|
||||
|
||||
func (pt *Path) Template() string {
|
||||
|
@ -105,25 +112,34 @@ func (pt *Path) Enabled() bool {
|
|||
}
|
||||
|
||||
func (pt *Path) setPaths() {
|
||||
defer func() {
|
||||
pt.Folders = pt.splitPath()
|
||||
}()
|
||||
|
||||
pt.pwd = pt.env.Pwd()
|
||||
if (pt.env.Shell() == shell.PWSH || pt.env.Shell() == shell.PWSH5) && len(pt.env.Flags().PSWD) != 0 {
|
||||
pt.pwd = pt.env.Flags().PSWD
|
||||
}
|
||||
|
||||
if len(pt.pwd) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
// ensure a clean path
|
||||
pt.root, pt.relative = pt.replaceMappedLocations()
|
||||
|
||||
// this is a full replacement of the parent
|
||||
if len(pt.root) == 0 {
|
||||
pt.pwd = pt.relative
|
||||
return
|
||||
}
|
||||
|
||||
pathSeparator := pt.env.PathSeparator()
|
||||
if !strings.HasSuffix(pt.root, pathSeparator) && len(pt.relative) > 0 {
|
||||
pt.pwd = pt.root + pathSeparator + pt.relative
|
||||
return
|
||||
}
|
||||
|
||||
pt.pwd = pt.root + pt.relative
|
||||
}
|
||||
|
||||
|
@ -173,7 +189,7 @@ func (pt *Path) setStyle() {
|
|||
fallthrough
|
||||
case Full:
|
||||
pt.Path = pt.getFullPath()
|
||||
case Folder:
|
||||
case FolderType:
|
||||
pt.Path = pt.getFolderPath()
|
||||
case Powerlevel:
|
||||
maxWidth := int(pt.props.GetFloat64(MaxWidth, 0))
|
||||
|
@ -213,15 +229,17 @@ func (pt *Path) getMixedPath() string {
|
|||
threshold := int(pt.props.GetFloat64(MixedThreshold, 4))
|
||||
folderIcon := pt.props.GetString(FolderIcon, "..")
|
||||
separator := pt.getFolderSeparator()
|
||||
elements := strings.Split(pt.relative, pt.env.PathSeparator())
|
||||
|
||||
if pt.root != pt.env.PathSeparator() {
|
||||
elements = append([]string{pt.root}, elements...)
|
||||
pt.Folders = append(Folders{{Name: pt.root}}, pt.Folders...)
|
||||
}
|
||||
n := len(elements)
|
||||
buffer.WriteString(elements[0])
|
||||
|
||||
n := len(pt.Folders)
|
||||
buffer.WriteString(pt.Folders[0].Name)
|
||||
|
||||
for i := 1; i < n; i++ {
|
||||
folder := elements[i]
|
||||
if len(folder) > threshold && i != n-1 {
|
||||
folder := pt.Folders[i].Name
|
||||
if len(folder) > threshold && i != n-1 && !pt.Folders[i].Display {
|
||||
folder = folderIcon
|
||||
}
|
||||
buffer.WriteString(fmt.Sprintf("%s%s", separator, folder))
|
||||
|
@ -229,33 +247,28 @@ func (pt *Path) getMixedPath() string {
|
|||
return buffer.String()
|
||||
}
|
||||
|
||||
func (pt *Path) pathDepth(pwd string) int {
|
||||
splitted := strings.Split(pwd, pt.env.PathSeparator())
|
||||
depth := 0
|
||||
for _, part := range splitted {
|
||||
if part != "" {
|
||||
depth++
|
||||
}
|
||||
}
|
||||
return depth
|
||||
}
|
||||
|
||||
func (pt *Path) getAgnosterPath() string {
|
||||
folderIcon := pt.props.GetString(FolderIcon, "..")
|
||||
splitted := strings.Split(pt.relative, pt.env.PathSeparator())
|
||||
|
||||
if pt.root == pt.env.PathSeparator() {
|
||||
pt.root = splitted[0]
|
||||
splitted = splitted[1:]
|
||||
pt.root = pt.Folders[0].Name
|
||||
pt.Folders = pt.Folders[1:]
|
||||
}
|
||||
|
||||
var elements []string
|
||||
n := len(splitted)
|
||||
for i := 1; i < n; i++ {
|
||||
elements = append(elements, folderIcon)
|
||||
n := len(pt.Folders)
|
||||
for i := 0; i < n-1; i++ {
|
||||
name := folderIcon
|
||||
|
||||
if pt.Folders[i].Display {
|
||||
name = pt.Folders[i].Name
|
||||
}
|
||||
|
||||
elements = append(elements, name)
|
||||
}
|
||||
|
||||
if len(splitted) > 0 {
|
||||
elements = append(elements, splitted[n-1])
|
||||
if len(pt.Folders) > 0 {
|
||||
elements = append(elements, pt.Folders[n-1].Name)
|
||||
}
|
||||
|
||||
return pt.colorizePath(pt.root, elements)
|
||||
|
@ -263,52 +276,66 @@ func (pt *Path) getAgnosterPath() string {
|
|||
|
||||
func (pt *Path) getAgnosterLeftPath() string {
|
||||
folderIcon := pt.props.GetString(FolderIcon, "..")
|
||||
splitted := strings.Split(pt.relative, pt.env.PathSeparator())
|
||||
|
||||
if pt.root == pt.env.PathSeparator() {
|
||||
pt.root = splitted[0]
|
||||
splitted = splitted[1:]
|
||||
pt.root = pt.Folders[0].Name
|
||||
pt.Folders = pt.Folders[1:]
|
||||
}
|
||||
|
||||
var elements []string
|
||||
n := len(splitted)
|
||||
elements = append(elements, splitted[0])
|
||||
n := len(pt.Folders)
|
||||
elements = append(elements, pt.Folders[0].Name)
|
||||
for i := 1; i < n; i++ {
|
||||
if pt.Folders[i].Display {
|
||||
elements = append(elements, pt.Folders[i].Name)
|
||||
continue
|
||||
}
|
||||
|
||||
elements = append(elements, folderIcon)
|
||||
}
|
||||
|
||||
return pt.colorizePath(pt.root, elements)
|
||||
}
|
||||
|
||||
func (pt *Path) getRelevantLetter(folder string) string {
|
||||
func (pt *Path) getRelevantLetter(folder *Folder) string {
|
||||
if folder.Display {
|
||||
return folder.Name
|
||||
}
|
||||
|
||||
// check if there is at least a letter we can use
|
||||
matches := regex.FindNamedRegexMatch(`(?P<letter>[\p{L}0-9]).*`, folder)
|
||||
matches := regex.FindNamedRegexMatch(`(?P<letter>[\p{L}0-9]).*`, folder.Name)
|
||||
if matches == nil || len(matches["letter"]) == 0 {
|
||||
// no letter found, keep the folder unchanged
|
||||
return folder
|
||||
return folder.Name
|
||||
}
|
||||
letter := matches["letter"]
|
||||
// handle non-letter characters before the first found letter
|
||||
letter = folder[0:strings.Index(folder, letter)] + letter
|
||||
letter = folder.Name[0:strings.Index(folder.Name, letter)] + letter
|
||||
return letter
|
||||
}
|
||||
|
||||
func (pt *Path) getLetterPath() string {
|
||||
splitted := strings.Split(pt.relative, pt.env.PathSeparator())
|
||||
if pt.root == pt.env.PathSeparator() {
|
||||
pt.root = splitted[0]
|
||||
splitted = splitted[1:]
|
||||
pt.root = pt.Folders[0].Name
|
||||
pt.Folders = pt.Folders[1:]
|
||||
}
|
||||
pt.root = pt.getRelevantLetter(pt.root)
|
||||
|
||||
pt.root = pt.getRelevantLetter(&Folder{Name: pt.root})
|
||||
|
||||
var elements []string
|
||||
n := len(splitted)
|
||||
n := len(pt.Folders)
|
||||
for i := 0; i < n-1; i++ {
|
||||
letter := pt.getRelevantLetter(splitted[i])
|
||||
if pt.Folders[i].Display {
|
||||
elements = append(elements, pt.Folders[i].Name)
|
||||
continue
|
||||
}
|
||||
|
||||
letter := pt.getRelevantLetter(pt.Folders[i])
|
||||
elements = append(elements, letter)
|
||||
}
|
||||
|
||||
if len(splitted) > 0 {
|
||||
elements = append(elements, splitted[n-1])
|
||||
if len(pt.Folders) > 0 {
|
||||
elements = append(elements, pt.Folders[n-1].Name)
|
||||
}
|
||||
|
||||
return pt.colorizePath(pt.root, elements)
|
||||
|
@ -316,98 +343,101 @@ func (pt *Path) getLetterPath() string {
|
|||
|
||||
func (pt *Path) getUniqueLettersPath(maxWidth int) string {
|
||||
separator := pt.getFolderSeparator()
|
||||
splitted := strings.Split(pt.relative, pt.env.PathSeparator())
|
||||
|
||||
if pt.root == pt.env.PathSeparator() {
|
||||
pt.root = splitted[0]
|
||||
splitted = splitted[1:]
|
||||
pt.root = pt.Folders[0].Name
|
||||
pt.Folders = pt.Folders[1:]
|
||||
}
|
||||
|
||||
if maxWidth > 0 {
|
||||
path := strings.Join(splitted, separator)
|
||||
path := strings.Join(pt.Folders.List(), separator)
|
||||
if len(path) <= maxWidth {
|
||||
return pt.colorizePath(pt.root, splitted)
|
||||
return pt.colorizePath(pt.root, pt.Folders.List())
|
||||
}
|
||||
}
|
||||
|
||||
pt.root = pt.getRelevantLetter(pt.root)
|
||||
pt.root = pt.getRelevantLetter(&Folder{Name: pt.root})
|
||||
|
||||
var elements []string
|
||||
n := len(splitted)
|
||||
n := len(pt.Folders)
|
||||
letters := make(map[string]bool)
|
||||
letters[pt.root] = true
|
||||
for i := 0; i < n-1; i++ {
|
||||
folder := splitted[i]
|
||||
letter := pt.getRelevantLetter(folder)
|
||||
folder := pt.Folders[i].Name
|
||||
letter := pt.getRelevantLetter(pt.Folders[i])
|
||||
|
||||
for letters[letter] {
|
||||
if letter == folder {
|
||||
break
|
||||
}
|
||||
letter += folder[len(letter) : len(letter)+1]
|
||||
}
|
||||
|
||||
letters[letter] = true
|
||||
elements = append(elements, letter)
|
||||
|
||||
// only return early on maxWidth > 0
|
||||
// this enables the powerlevel10k behavior
|
||||
if maxWidth > 0 {
|
||||
list := splitted[i+1:]
|
||||
list := pt.Folders[i+1:].List()
|
||||
list = append(list, elements...)
|
||||
current := strings.Join(list, separator)
|
||||
leftover := maxWidth - len(current) - len(pt.root) - len(separator)
|
||||
if leftover >= 0 {
|
||||
elements = append(elements, strings.Join(splitted[i+1:], separator))
|
||||
elements = append(elements, strings.Join(pt.Folders[i+1:].List(), separator))
|
||||
return pt.colorizePath(pt.root, elements)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if len(splitted) > 0 {
|
||||
elements = append(elements, splitted[n-1])
|
||||
if len(pt.Folders) > 0 {
|
||||
elements = append(elements, pt.Folders[n-1].Name)
|
||||
}
|
||||
|
||||
return pt.colorizePath(pt.root, elements)
|
||||
}
|
||||
|
||||
func (pt *Path) getAgnosterFullPath() string {
|
||||
splitted := strings.Split(pt.relative, pt.env.PathSeparator())
|
||||
if pt.root == pt.env.PathSeparator() {
|
||||
pt.root = splitted[0]
|
||||
splitted = splitted[1:]
|
||||
pt.root = pt.Folders[0].Name
|
||||
pt.Folders = pt.Folders[1:]
|
||||
}
|
||||
|
||||
return pt.colorizePath(pt.root, splitted)
|
||||
return pt.colorizePath(pt.root, pt.Folders.List())
|
||||
}
|
||||
|
||||
func (pt *Path) getAgnosterShortPath() string {
|
||||
pathDepth := pt.pathDepth(pt.relative)
|
||||
pathDepth := len(pt.Folders)
|
||||
|
||||
maxDepth := pt.props.GetInt(MaxDepth, 1)
|
||||
if maxDepth < 1 {
|
||||
maxDepth = 1
|
||||
}
|
||||
|
||||
folderIcon := pt.props.GetString(FolderIcon, "..")
|
||||
hideRootLocation := pt.props.GetBool(HideRootLocation, false)
|
||||
|
||||
if pathDepth <= maxDepth {
|
||||
if hideRootLocation {
|
||||
pt.root = folderIcon
|
||||
}
|
||||
return pt.getAgnosterFullPath()
|
||||
}
|
||||
|
||||
pathSeparator := pt.env.PathSeparator()
|
||||
rel := strings.TrimPrefix(pt.relative, pathSeparator)
|
||||
splitted := strings.Split(rel, pathSeparator)
|
||||
splitPos := pathDepth - maxDepth
|
||||
// var buffer strings.Builder
|
||||
var elements []string
|
||||
|
||||
var folders []string
|
||||
// unix root, needs to be replaced with the folder we're in at root level
|
||||
root := pt.root
|
||||
room := pathDepth - maxDepth
|
||||
if root == pathSeparator {
|
||||
root = splitted[0]
|
||||
root = pt.Folders[0].Name
|
||||
room--
|
||||
}
|
||||
|
||||
if hideRootLocation || room > 0 {
|
||||
elements = append(elements, folderIcon)
|
||||
folders = append(folders, folderIcon)
|
||||
}
|
||||
|
||||
if hideRootLocation {
|
||||
|
@ -415,14 +445,14 @@ func (pt *Path) getAgnosterShortPath() string {
|
|||
}
|
||||
|
||||
for i := splitPos; i < pathDepth; i++ {
|
||||
elements = append(elements, splitted[i])
|
||||
folders = append(folders, pt.Folders[i].Name)
|
||||
}
|
||||
return pt.colorizePath(root, elements)
|
||||
|
||||
return pt.colorizePath(root, folders)
|
||||
}
|
||||
|
||||
func (pt *Path) getFullPath() string {
|
||||
elements := strings.Split(pt.relative, pt.env.PathSeparator())
|
||||
return pt.colorizePath(pt.root, elements)
|
||||
return pt.colorizePath(pt.root, pt.Folders.List())
|
||||
}
|
||||
|
||||
func (pt *Path) getFolderPath() string {
|
||||
|
@ -597,7 +627,10 @@ func (pt *Path) colorizePath(root string, elements []string) string {
|
|||
folderSeparator := pt.getFolderSeparator()
|
||||
colorSeparator := pt.props.GetBool(CycleFolderSeparator, false)
|
||||
folderFormat := pt.props.GetString(FolderFormat, "%s")
|
||||
|
||||
edgeFormat := pt.props.GetString(EdgeFormat, folderFormat)
|
||||
leftFormat := pt.props.GetString(LeftFormat, edgeFormat)
|
||||
rightFormat := pt.props.GetString(RightFormat, edgeFormat)
|
||||
|
||||
colorizeElement := func(element string) string {
|
||||
if skipColorize || len(element) == 0 {
|
||||
|
@ -610,7 +643,7 @@ func (pt *Path) colorizePath(root string, elements []string) string {
|
|||
}
|
||||
|
||||
if len(elements) == 0 {
|
||||
root := fmt.Sprintf(edgeFormat, root)
|
||||
root := fmt.Sprintf(leftFormat, root)
|
||||
return colorizeElement(root)
|
||||
}
|
||||
|
||||
|
@ -623,7 +656,7 @@ func (pt *Path) colorizePath(root string, elements []string) string {
|
|||
|
||||
var builder strings.Builder
|
||||
|
||||
root = fmt.Sprintf(edgeFormat, root)
|
||||
root = fmt.Sprintf(leftFormat, root)
|
||||
builder.WriteString(colorizeElement(root))
|
||||
|
||||
if root != pt.env.PathSeparator() && len(root) != 0 {
|
||||
|
@ -637,7 +670,7 @@ func (pt *Path) colorizePath(root string, elements []string) string {
|
|||
|
||||
format := folderFormat
|
||||
if i == len(elements)-1 {
|
||||
format = edgeFormat
|
||||
format = rightFormat
|
||||
}
|
||||
|
||||
element = fmt.Sprintf(format, element)
|
||||
|
@ -649,3 +682,78 @@ func (pt *Path) colorizePath(root string, elements []string) string {
|
|||
|
||||
return builder.String()
|
||||
}
|
||||
|
||||
type Folder struct {
|
||||
Name string
|
||||
Display bool
|
||||
Path string
|
||||
}
|
||||
|
||||
type Folders []*Folder
|
||||
|
||||
func (f Folders) List() []string {
|
||||
var list []string
|
||||
|
||||
for _, folder := range f {
|
||||
list = append(list, folder.Name)
|
||||
}
|
||||
|
||||
return list
|
||||
}
|
||||
|
||||
func (pt *Path) splitPath() Folders {
|
||||
result := Folders{}
|
||||
folders := []string{}
|
||||
|
||||
if len(pt.relative) != 0 {
|
||||
folders = strings.Split(pt.relative, pt.env.PathSeparator())
|
||||
}
|
||||
|
||||
folderFormatMap := pt.makeFolderFormatMap()
|
||||
|
||||
getCurrentPath := func() string {
|
||||
if pt.root == "~" {
|
||||
return pt.env.Home() + pt.env.PathSeparator()
|
||||
}
|
||||
|
||||
if pt.env.GOOS() == platform.WINDOWS {
|
||||
return pt.root + pt.env.PathSeparator()
|
||||
}
|
||||
|
||||
return pt.root
|
||||
}
|
||||
|
||||
currentPath := getCurrentPath()
|
||||
|
||||
var display bool
|
||||
|
||||
for _, folder := range folders {
|
||||
currentPath += folder
|
||||
|
||||
if format := folderFormatMap[currentPath]; len(format) != 0 {
|
||||
folder = fmt.Sprintf(format, folder)
|
||||
display = true
|
||||
}
|
||||
|
||||
result = append(result, &Folder{Name: folder, Path: currentPath, Display: display})
|
||||
|
||||
currentPath += pt.env.PathSeparator()
|
||||
|
||||
display = false
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
func (pt *Path) makeFolderFormatMap() map[string]string {
|
||||
folderFormatMap := make(map[string]string)
|
||||
|
||||
if gitDirFormat := pt.props.GetString(GitDirFormat, ""); len(gitDirFormat) != 0 {
|
||||
dir, err := pt.env.HasParentFilePath(".git")
|
||||
if err == nil && dir.IsDir {
|
||||
folderFormatMap[dir.ParentFolder] = gitDirFormat
|
||||
}
|
||||
}
|
||||
|
||||
return folderFormatMap
|
||||
}
|
||||
|
|
|
@ -787,21 +787,21 @@ func TestFullAndFolderPath(t *testing.T) {
|
|||
{Style: Full, FolderSeparatorIcon: "|", Pwd: homeDir + abc, Expected: "~|abc"},
|
||||
{Style: Full, FolderSeparatorIcon: "|", Pwd: abcd, Expected: "/a|b|c|d"},
|
||||
|
||||
{Style: Folder, Pwd: "/", Expected: "/"},
|
||||
{Style: Folder, Pwd: homeDir, Expected: "~"},
|
||||
{Style: Folder, Pwd: homeDir, Expected: "someone", DisableMappedLocations: true},
|
||||
{Style: Folder, Pwd: homeDir + abc, Expected: "abc"},
|
||||
{Style: Folder, Pwd: abcd, Expected: "d"},
|
||||
{Style: FolderType, Pwd: "/", Expected: "/"},
|
||||
{Style: FolderType, Pwd: homeDir, Expected: "~"},
|
||||
{Style: FolderType, Pwd: homeDir, Expected: "someone", DisableMappedLocations: true},
|
||||
{Style: FolderType, Pwd: homeDir + abc, Expected: "abc"},
|
||||
{Style: FolderType, Pwd: abcd, Expected: "d"},
|
||||
|
||||
{Style: Folder, FolderSeparatorIcon: "|", Pwd: "/", Expected: "/"},
|
||||
{Style: Folder, FolderSeparatorIcon: "|", Pwd: homeDir, Expected: "~"},
|
||||
{Style: Folder, FolderSeparatorIcon: "|", Pwd: homeDir, Expected: "someone", DisableMappedLocations: true},
|
||||
{Style: Folder, FolderSeparatorIcon: "|", Pwd: homeDir + abc, Expected: "abc"},
|
||||
{Style: Folder, FolderSeparatorIcon: "|", Pwd: abcd, Expected: "d"},
|
||||
{Style: FolderType, FolderSeparatorIcon: "|", Pwd: "/", Expected: "/"},
|
||||
{Style: FolderType, FolderSeparatorIcon: "|", Pwd: homeDir, Expected: "~"},
|
||||
{Style: FolderType, FolderSeparatorIcon: "|", Pwd: homeDir, Expected: "someone", DisableMappedLocations: true},
|
||||
{Style: FolderType, FolderSeparatorIcon: "|", Pwd: homeDir + abc, Expected: "abc"},
|
||||
{Style: FolderType, FolderSeparatorIcon: "|", Pwd: abcd, Expected: "d"},
|
||||
|
||||
// for Windows paths
|
||||
{Style: Folder, FolderSeparatorIcon: "\\", Pwd: "C:\\", Expected: "C:\\", PathSeparator: "\\", GOOS: platform.WINDOWS},
|
||||
{Style: Folder, FolderSeparatorIcon: "\\", Pwd: homeDirWindows, Expected: "~", PathSeparator: "\\", GOOS: platform.WINDOWS},
|
||||
{Style: FolderType, FolderSeparatorIcon: "\\", Pwd: "C:\\", Expected: "C:\\", PathSeparator: "\\", GOOS: platform.WINDOWS},
|
||||
{Style: FolderType, FolderSeparatorIcon: "\\", Pwd: homeDirWindows, Expected: "~", PathSeparator: "\\", GOOS: platform.WINDOWS},
|
||||
{Style: Full, FolderSeparatorIcon: "\\", Pwd: homeDirWindows, Expected: "~", PathSeparator: "\\", GOOS: platform.WINDOWS},
|
||||
{Style: Full, FolderSeparatorIcon: "\\", Pwd: homeDirWindows + "\\abc", Expected: "~\\abc", PathSeparator: "\\", GOOS: platform.WINDOWS},
|
||||
{Style: Full, FolderSeparatorIcon: "\\", Pwd: "C:\\Users\\posh", Expected: "C:\\Users\\posh", PathSeparator: "\\", GOOS: platform.WINDOWS},
|
||||
|
@ -994,7 +994,7 @@ func TestFolderPathCustomMappedLocations(t *testing.T) {
|
|||
path := &Path{
|
||||
env: env,
|
||||
props: properties.Map{
|
||||
properties.Style: Folder,
|
||||
properties.Style: FolderType,
|
||||
MappedLocations: map[string]string{
|
||||
abcd: "#",
|
||||
},
|
||||
|
@ -1502,3 +1502,71 @@ func TestReplaceMappedLocations(t *testing.T) {
|
|||
assert.Equal(t, tc.Expected, path.pwd)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSplitPath(t *testing.T) {
|
||||
cases := []struct {
|
||||
Case string
|
||||
GOOS string
|
||||
Relative string
|
||||
Root string
|
||||
GitDir *platform.FileInfo
|
||||
GitDirFormat string
|
||||
Expected Folders
|
||||
}{
|
||||
{Case: "Root directory", Root: "/", Expected: Folders{}},
|
||||
{
|
||||
Case: "Regular directory",
|
||||
Root: "/",
|
||||
Relative: "c/d",
|
||||
GOOS: platform.DARWIN,
|
||||
Expected: Folders{
|
||||
{Name: "c", Path: "/c"},
|
||||
{Name: "d", Path: "/c/d"},
|
||||
},
|
||||
},
|
||||
{
|
||||
Case: "Home directory - git folder",
|
||||
Root: "~",
|
||||
Relative: "c/d",
|
||||
GOOS: platform.DARWIN,
|
||||
GitDir: &platform.FileInfo{IsDir: true, ParentFolder: "/a/b/c"},
|
||||
GitDirFormat: "<b>%s</b>",
|
||||
Expected: Folders{
|
||||
{Name: "<b>c</b>", Path: "/a/b/c", Display: true},
|
||||
{Name: "d", Path: "/a/b/c/d"},
|
||||
},
|
||||
},
|
||||
{
|
||||
Case: "Home directory - git folder on Windows",
|
||||
Root: "C:",
|
||||
Relative: "a/b/c/d",
|
||||
GOOS: platform.WINDOWS,
|
||||
GitDir: &platform.FileInfo{IsDir: true, ParentFolder: "C:/a/b/c"},
|
||||
GitDirFormat: "<b>%s</b>",
|
||||
Expected: Folders{
|
||||
{Name: "a", Path: "C:/a"},
|
||||
{Name: "b", Path: "C:/a/b"},
|
||||
{Name: "<b>c</b>", Path: "C:/a/b/c", Display: true},
|
||||
{Name: "d", Path: "C:/a/b/c/d"},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
env := new(mock.MockedEnvironment)
|
||||
env.On("PathSeparator").Return("/")
|
||||
env.On("Home").Return("/a/b")
|
||||
env.On("HasParentFilePath", ".git").Return(tc.GitDir, nil)
|
||||
env.On("GOOS").Return(tc.GOOS)
|
||||
path := &Path{
|
||||
env: env,
|
||||
props: properties.Map{
|
||||
GitDirFormat: tc.GitDirFormat,
|
||||
},
|
||||
root: tc.Root,
|
||||
relative: tc.Relative,
|
||||
}
|
||||
got := path.splitPath()
|
||||
assert.Equal(t, tc.Expected, got, tc.Case)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@ import (
|
|||
"github.com/jandedobbeleer/oh-my-posh/src/regex"
|
||||
"golang.org/x/exp/slices"
|
||||
|
||||
"github.com/BurntSushi/toml"
|
||||
toml "github.com/pelletier/go-toml/v2"
|
||||
)
|
||||
|
||||
type ProjectItem struct {
|
||||
|
@ -154,7 +154,7 @@ func (n *Project) getCargoPackage(item ProjectItem) *ProjectData {
|
|||
content := n.env.FileContent(item.Files[0])
|
||||
|
||||
var data CargoTOML
|
||||
_, err := toml.Decode(content, &data)
|
||||
err := toml.Unmarshal([]byte(content), &data)
|
||||
if err != nil {
|
||||
n.Error = err.Error()
|
||||
return nil
|
||||
|
@ -170,7 +170,7 @@ func (n *Project) getPythonPackage(item ProjectItem) *ProjectData {
|
|||
content := n.env.FileContent(item.Files[0])
|
||||
|
||||
var data PyProjectTOML
|
||||
_, err := toml.Decode(content, &data)
|
||||
err := toml.Unmarshal([]byte(content), &data)
|
||||
if err != nil {
|
||||
n.Error = err.Error()
|
||||
return nil
|
||||
|
@ -293,7 +293,7 @@ func (n *Project) getProjectData(item ProjectItem) *ProjectData {
|
|||
content := n.env.FileContent(item.Files[0])
|
||||
|
||||
var data ProjectData
|
||||
_, err := toml.Decode(content, &data)
|
||||
err := toml.Unmarshal([]byte(content), &data)
|
||||
if err != nil {
|
||||
n.Error = err.Error()
|
||||
return nil
|
||||
|
|
220
src/segments/pulumi.go
Normal file
220
src/segments/pulumi.go
Normal file
|
@ -0,0 +1,220 @@
|
|||
package segments
|
||||
|
||||
import (
|
||||
"crypto/sha1"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/jandedobbeleer/oh-my-posh/src/platform"
|
||||
"github.com/jandedobbeleer/oh-my-posh/src/properties"
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
const (
|
||||
FetchStack properties.Property = "fetch_stack"
|
||||
FetchAbout properties.Property = "fetch_about"
|
||||
|
||||
JSON string = "json"
|
||||
YAML string = "yaml"
|
||||
|
||||
pulumiJSON string = "Pulumi.json"
|
||||
pulumiYAML string = "Pulumi.yaml"
|
||||
)
|
||||
|
||||
type Pulumi struct {
|
||||
props properties.Properties
|
||||
env platform.Environment
|
||||
|
||||
Stack string
|
||||
Name string
|
||||
|
||||
workspaceSHA1 string
|
||||
|
||||
backend
|
||||
}
|
||||
|
||||
type backend struct {
|
||||
URL string `json:"url"`
|
||||
User string `json:"user"`
|
||||
}
|
||||
|
||||
type pulumiFileSpec struct {
|
||||
Name string `yaml:"name" json:"name"`
|
||||
}
|
||||
|
||||
type pulumiWorkSpaceFileSpec struct {
|
||||
Stack string `json:"stack"`
|
||||
}
|
||||
|
||||
func (p *Pulumi) Template() string {
|
||||
return "\U000f0d46 {{ .Stack }}{{if .User }} :: {{ .User }}@{{ end }}{{ if .URL }}{{ .URL }}{{ end }}"
|
||||
}
|
||||
|
||||
func (p *Pulumi) Init(props properties.Properties, env platform.Environment) {
|
||||
p.props = props
|
||||
p.env = env
|
||||
}
|
||||
|
||||
func (p *Pulumi) Enabled() bool {
|
||||
if !p.env.HasCommand("pulumi") {
|
||||
return false
|
||||
}
|
||||
|
||||
err := p.getProjectName()
|
||||
if err != nil {
|
||||
p.env.Error(err)
|
||||
return false
|
||||
}
|
||||
|
||||
if p.props.GetBool(FetchStack, false) {
|
||||
p.getPulumiStackName()
|
||||
}
|
||||
|
||||
if p.props.GetBool(FetchAbout, false) {
|
||||
p.getPulumiAbout()
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func (p *Pulumi) getPulumiStackName() {
|
||||
if len(p.Name) == 0 || len(p.workspaceSHA1) == 0 {
|
||||
p.env.Debug("pulumi project name or workspace sha1 is empty")
|
||||
return
|
||||
}
|
||||
|
||||
stackNameFile := p.Name + "-" + p.workspaceSHA1 + "-" + "workspace.json"
|
||||
|
||||
homedir := p.env.Home()
|
||||
|
||||
workspaceCacheDir := filepath.Join(homedir, ".pulumi", "workspaces")
|
||||
if !p.env.HasFolder(workspaceCacheDir) || !p.env.HasFilesInDir(workspaceCacheDir, stackNameFile) {
|
||||
return
|
||||
}
|
||||
|
||||
workspaceCacheFile := filepath.Join(workspaceCacheDir, stackNameFile)
|
||||
workspaceCacheFileContent := p.env.FileContent(workspaceCacheFile)
|
||||
|
||||
var pulumiWorkspaceSpec pulumiWorkSpaceFileSpec
|
||||
err := json.Unmarshal([]byte(workspaceCacheFileContent), &pulumiWorkspaceSpec)
|
||||
if err != nil {
|
||||
p.env.Error(fmt.Errorf("pulumi workspace file decode error"))
|
||||
return
|
||||
}
|
||||
|
||||
p.env.DebugF("pulumi stack name: %s", pulumiWorkspaceSpec.Stack)
|
||||
p.Stack = pulumiWorkspaceSpec.Stack
|
||||
}
|
||||
|
||||
func (p *Pulumi) getProjectName() error {
|
||||
var kind, fileName string
|
||||
for _, file := range []string{pulumiYAML, pulumiJSON} {
|
||||
if p.env.HasFiles(file) {
|
||||
fileName = file
|
||||
kind = filepath.Ext(file)[1:]
|
||||
}
|
||||
}
|
||||
|
||||
if len(kind) == 0 {
|
||||
return fmt.Errorf("no pulumi spec file found")
|
||||
}
|
||||
|
||||
var pulumiFileSpec pulumiFileSpec
|
||||
var err error
|
||||
|
||||
pulumiFile := p.env.FileContent(fileName)
|
||||
|
||||
switch kind {
|
||||
case YAML:
|
||||
err = yaml.Unmarshal([]byte(pulumiFile), &pulumiFileSpec)
|
||||
case JSON:
|
||||
err = json.Unmarshal([]byte(pulumiFile), &pulumiFileSpec)
|
||||
default:
|
||||
err = fmt.Errorf("unknown pulumi spec file format")
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
p.env.Error(err)
|
||||
return nil
|
||||
}
|
||||
|
||||
p.Name = pulumiFileSpec.Name
|
||||
|
||||
sha1HexString := func(value string) string {
|
||||
h := sha1.New()
|
||||
|
||||
_, err := h.Write([]byte(value))
|
||||
if err != nil {
|
||||
p.env.Error(err)
|
||||
return ""
|
||||
}
|
||||
|
||||
return hex.EncodeToString(h.Sum(nil))
|
||||
}
|
||||
|
||||
p.workspaceSHA1 = sha1HexString(p.env.Pwd() + p.env.PathSeparator() + fileName)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *Pulumi) getPulumiAbout() {
|
||||
if len(p.Stack) == 0 {
|
||||
p.env.Error(fmt.Errorf("pulumi stack name is empty, use `fetch_stack` property to enable stack fetching"))
|
||||
return
|
||||
}
|
||||
|
||||
cacheKey := "pulumi-" + p.Name + "-" + p.Stack + "-" + p.workspaceSHA1 + "-about"
|
||||
|
||||
getAboutCache := func(key string) (*backend, error) {
|
||||
aboutBackend, OK := p.env.Cache().Get(key)
|
||||
if (!OK || len(aboutBackend) == 0) || (OK && len(aboutBackend) == 0) {
|
||||
return nil, fmt.Errorf("no data in cache")
|
||||
}
|
||||
|
||||
var backend *backend
|
||||
err := json.Unmarshal([]byte(aboutBackend), &backend)
|
||||
if err != nil {
|
||||
p.env.DebugF("unable to decode about cache: %s", aboutBackend)
|
||||
p.env.Error(fmt.Errorf("pulling about cache decode error"))
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return backend, nil
|
||||
}
|
||||
|
||||
aboutBackend, err := getAboutCache(cacheKey)
|
||||
if err == nil {
|
||||
p.backend = *aboutBackend
|
||||
return
|
||||
}
|
||||
|
||||
aboutOutput, err := p.env.RunCommand("pulumi", "about", "--json")
|
||||
|
||||
if err != nil {
|
||||
p.env.Error(fmt.Errorf("unable to get pulumi about output"))
|
||||
return
|
||||
}
|
||||
|
||||
var about struct {
|
||||
Backend *backend `json:"backend"`
|
||||
}
|
||||
|
||||
err = json.Unmarshal([]byte(aboutOutput), &about)
|
||||
if err != nil {
|
||||
p.env.Error(fmt.Errorf("pulumi about output decode error"))
|
||||
return
|
||||
}
|
||||
|
||||
if about.Backend == nil {
|
||||
p.env.Debug("pulumi about backend is not set")
|
||||
return
|
||||
}
|
||||
|
||||
p.backend = *about.Backend
|
||||
|
||||
cacheTimeout := p.props.GetInt(properties.CacheTimeout, 43800)
|
||||
jso, _ := json.Marshal(about.Backend)
|
||||
p.env.Cache().Set(cacheKey, string(jso), cacheTimeout)
|
||||
}
|
236
src/segments/pulumi_test.go
Normal file
236
src/segments/pulumi_test.go
Normal file
|
@ -0,0 +1,236 @@
|
|||
package segments
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"github.com/jandedobbeleer/oh-my-posh/src/mock"
|
||||
"github.com/jandedobbeleer/oh-my-posh/src/properties"
|
||||
"github.com/stretchr/testify/assert"
|
||||
mock2 "github.com/stretchr/testify/mock"
|
||||
)
|
||||
|
||||
func TestPulumi(t *testing.T) {
|
||||
cases := []struct {
|
||||
Case string
|
||||
YAMLConfig string
|
||||
JSONConfig string
|
||||
|
||||
HasCommand bool
|
||||
|
||||
FetchStack bool
|
||||
Stack string
|
||||
StackError error
|
||||
|
||||
HasWorkspaceFolder bool
|
||||
WorkSpaceFile string
|
||||
|
||||
FetchAbout bool
|
||||
About string
|
||||
AboutError error
|
||||
AboutCache string
|
||||
|
||||
ExpectedString string
|
||||
ExpectedEnabled bool
|
||||
}{
|
||||
{
|
||||
Case: "no pulumi command",
|
||||
ExpectedEnabled: false,
|
||||
HasCommand: false,
|
||||
},
|
||||
{
|
||||
Case: "pulumi command is present, but no pulumi file",
|
||||
ExpectedEnabled: false,
|
||||
HasCommand: true,
|
||||
},
|
||||
{
|
||||
Case: "pulumi file YAML is present",
|
||||
ExpectedString: "\U000f0d46",
|
||||
ExpectedEnabled: true,
|
||||
HasCommand: true,
|
||||
YAMLConfig: `
|
||||
name: oh-my-posh
|
||||
runtime: golang
|
||||
description: A Console App
|
||||
`,
|
||||
},
|
||||
{
|
||||
Case: "pulumi file JSON is present",
|
||||
ExpectedString: "\U000f0d46",
|
||||
ExpectedEnabled: true,
|
||||
HasCommand: true,
|
||||
JSONConfig: `{ "name": "oh-my-posh" }`,
|
||||
},
|
||||
{
|
||||
Case: "no stack present",
|
||||
ExpectedString: "\U000f0d46 1337",
|
||||
ExpectedEnabled: true,
|
||||
HasCommand: true,
|
||||
HasWorkspaceFolder: true,
|
||||
FetchStack: true,
|
||||
JSONConfig: `{ "name": "oh-my-posh" }`,
|
||||
WorkSpaceFile: `{ "stack": "1337" }`,
|
||||
},
|
||||
{
|
||||
Case: "pulumi stack",
|
||||
ExpectedString: "\U000f0d46 1337",
|
||||
ExpectedEnabled: true,
|
||||
HasCommand: true,
|
||||
HasWorkspaceFolder: true,
|
||||
FetchStack: true,
|
||||
JSONConfig: `{ "name": "oh-my-posh" }`,
|
||||
WorkSpaceFile: `{ "stack": "1337" }`,
|
||||
},
|
||||
{
|
||||
Case: "pulumi URL",
|
||||
ExpectedString: "\U000f0d46 1337 :: posh-user@s3://test-pulumi-state-test",
|
||||
ExpectedEnabled: true,
|
||||
HasCommand: true,
|
||||
HasWorkspaceFolder: true,
|
||||
FetchStack: true,
|
||||
FetchAbout: true,
|
||||
JSONConfig: `{ "name": "oh-my-posh" }`,
|
||||
WorkSpaceFile: `{ "stack": "1337" }`,
|
||||
About: `{ "backend": { "url": "s3://test-pulumi-state-test", "user":"posh-user" } }`,
|
||||
},
|
||||
{
|
||||
Case: "pulumi URL - cache",
|
||||
ExpectedString: "\U000f0d46 1337 :: posh-user@s3://test-pulumi-state-test",
|
||||
ExpectedEnabled: true,
|
||||
HasCommand: true,
|
||||
HasWorkspaceFolder: true,
|
||||
FetchStack: true,
|
||||
FetchAbout: true,
|
||||
JSONConfig: `{ "name": "oh-my-posh" }`,
|
||||
WorkSpaceFile: `{ "stack": "1337" }`,
|
||||
AboutCache: `{ "url": "s3://test-pulumi-state-test", "user":"posh-user" }`,
|
||||
},
|
||||
// Error flows
|
||||
{
|
||||
Case: "pulumi file JSON error",
|
||||
ExpectedString: "\U000f0d46",
|
||||
ExpectedEnabled: true,
|
||||
FetchStack: true,
|
||||
HasCommand: true,
|
||||
JSONConfig: `{`,
|
||||
},
|
||||
{
|
||||
Case: "pulumi workspace file JSON error",
|
||||
ExpectedString: "\U000f0d46",
|
||||
ExpectedEnabled: true,
|
||||
FetchStack: true,
|
||||
HasCommand: true,
|
||||
JSONConfig: `{ "name": "oh-my-posh" }`,
|
||||
WorkSpaceFile: `{`,
|
||||
HasWorkspaceFolder: true,
|
||||
},
|
||||
{
|
||||
Case: "pulumi URL, no fetch_stack set",
|
||||
ExpectedString: "\U000f0d46",
|
||||
ExpectedEnabled: true,
|
||||
HasCommand: true,
|
||||
FetchAbout: true,
|
||||
JSONConfig: `{ "name": "oh-my-posh" }`,
|
||||
},
|
||||
{
|
||||
Case: "pulumi URL - cache error",
|
||||
ExpectedString: "\U000f0d46 1337 :: posh-user@s3://test-pulumi-state-test-output",
|
||||
ExpectedEnabled: true,
|
||||
HasCommand: true,
|
||||
HasWorkspaceFolder: true,
|
||||
FetchStack: true,
|
||||
FetchAbout: true,
|
||||
JSONConfig: `{ "name": "oh-my-posh" }`,
|
||||
WorkSpaceFile: `{ "stack": "1337" }`,
|
||||
AboutCache: `{`,
|
||||
About: `{ "backend": { "url": "s3://test-pulumi-state-test-output", "user":"posh-user" } }`,
|
||||
},
|
||||
{
|
||||
Case: "pulumi URL - about error",
|
||||
ExpectedString: "\U000f0d46 1337",
|
||||
ExpectedEnabled: true,
|
||||
HasCommand: true,
|
||||
HasWorkspaceFolder: true,
|
||||
FetchStack: true,
|
||||
FetchAbout: true,
|
||||
JSONConfig: `{ "name": "oh-my-posh" }`,
|
||||
WorkSpaceFile: `{ "stack": "1337" }`,
|
||||
AboutError: errors.New("error"),
|
||||
},
|
||||
{
|
||||
Case: "pulumi URL - about decode error",
|
||||
ExpectedString: "\U000f0d46 1337",
|
||||
ExpectedEnabled: true,
|
||||
HasCommand: true,
|
||||
HasWorkspaceFolder: true,
|
||||
FetchStack: true,
|
||||
FetchAbout: true,
|
||||
JSONConfig: `{ "name": "oh-my-posh" }`,
|
||||
WorkSpaceFile: `{ "stack": "1337" }`,
|
||||
About: `{`,
|
||||
},
|
||||
{
|
||||
Case: "pulumi URL - about backend is nil",
|
||||
ExpectedString: "\U000f0d46 1337",
|
||||
ExpectedEnabled: true,
|
||||
HasCommand: true,
|
||||
HasWorkspaceFolder: true,
|
||||
FetchStack: true,
|
||||
FetchAbout: true,
|
||||
JSONConfig: `{ "name": "oh-my-posh" }`,
|
||||
WorkSpaceFile: `{ "stack": "1337" }`,
|
||||
About: `{}`,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
env := new(mock.MockedEnvironment)
|
||||
|
||||
env.On("HasCommand", "pulumi").Return(tc.HasCommand)
|
||||
env.On("RunCommand", "pulumi", []string{"stack", "ls", "--json"}).Return(tc.Stack, tc.StackError)
|
||||
env.On("RunCommand", "pulumi", []string{"about", "--json"}).Return(tc.About, tc.AboutError)
|
||||
|
||||
env.On("Pwd").Return("/home/foobar/Work/oh-my-posh/pulumi/projects/awesome-project")
|
||||
env.On("Home").Return(filepath.Clean("/home/foobar"))
|
||||
env.On("Error", mock2.Anything)
|
||||
env.On("Debug", mock2.Anything)
|
||||
env.On("DebugF", mock2.Anything, mock2.Anything)
|
||||
|
||||
env.On("HasFiles", pulumiYAML).Return(len(tc.YAMLConfig) > 0)
|
||||
env.On("FileContent", pulumiYAML).Return(tc.YAMLConfig, nil)
|
||||
|
||||
env.On("HasFiles", pulumiJSON).Return(len(tc.JSONConfig) > 0)
|
||||
env.On("FileContent", pulumiJSON).Return(tc.JSONConfig, nil)
|
||||
|
||||
env.On("PathSeparator").Return("/")
|
||||
|
||||
env.On("HasFolder", filepath.Clean("/home/foobar/.pulumi/workspaces")).Return(tc.HasWorkspaceFolder)
|
||||
workspaceFile := "oh-my-posh-c62b7b6786c5c5a85896576e46a25d7c9f888e92-workspace.json"
|
||||
env.On("HasFilesInDir", filepath.Clean("/home/foobar/.pulumi/workspaces"), workspaceFile).Return(len(tc.WorkSpaceFile) > 0)
|
||||
env.On("FileContent", filepath.Clean("/home/foobar/.pulumi/workspaces/"+workspaceFile)).Return(tc.WorkSpaceFile, nil)
|
||||
|
||||
cache := &mock.MockedCache{}
|
||||
cache.On("Get", "pulumi-oh-my-posh-1337-c62b7b6786c5c5a85896576e46a25d7c9f888e92-about").Return(tc.AboutCache, len(tc.AboutCache) > 0)
|
||||
cache.On("Set", mock2.Anything, mock2.Anything, mock2.Anything)
|
||||
|
||||
env.On("Cache").Return(cache)
|
||||
|
||||
pulumi := &Pulumi{
|
||||
env: env,
|
||||
props: properties.Map{
|
||||
FetchStack: tc.FetchStack,
|
||||
FetchAbout: tc.FetchAbout,
|
||||
},
|
||||
}
|
||||
|
||||
assert.Equal(t, tc.ExpectedEnabled, pulumi.Enabled(), tc.Case)
|
||||
|
||||
if !tc.ExpectedEnabled {
|
||||
continue
|
||||
}
|
||||
|
||||
var got = renderTemplate(env, pulumi.Template(), pulumi)
|
||||
assert.Equal(t, tc.ExpectedString, got, tc.Case)
|
||||
}
|
||||
}
|
|
@ -21,6 +21,7 @@ const (
|
|||
// FetchVirtualEnv fetches the virtual env
|
||||
FetchVirtualEnv properties.Property = "fetch_virtual_env"
|
||||
UsePythonVersionFile properties.Property = "use_python_version_file"
|
||||
FolderNameFallback properties.Property = "folder_name_fallback"
|
||||
)
|
||||
|
||||
func (p *Python) Template() string {
|
||||
|
@ -50,6 +51,11 @@ func (p *Python) Init(props properties.Properties, env platform.Environment) {
|
|||
args: []string{"--version"},
|
||||
regex: `(?:Python (?P<version>((?P<major>[0-9]+).(?P<minor>[0-9]+).(?P<patch>[0-9]+))))`,
|
||||
},
|
||||
{
|
||||
executable: "py",
|
||||
args: []string{"--version"},
|
||||
regex: `(?:Python (?P<version>((?P<major>[0-9]+).(?P<minor>[0-9]+).(?P<patch>[0-9]+))))`,
|
||||
},
|
||||
},
|
||||
versionURLTemplate: "https://docs.python.org/release/{{ .Major }}.{{ .Minor }}.{{ .Patch }}/whatsnew/changelog.html#python-{{ .Major }}-{{ .Minor }}-{{ .Patch }}",
|
||||
displayMode: props.GetString(DisplayMode, DisplayModeEnvironment),
|
||||
|
@ -74,6 +80,7 @@ func (p *Python) loadContext() {
|
|||
"CONDA_DEFAULT_ENV",
|
||||
}
|
||||
|
||||
folderNameFallback := p.language.props.GetBool(FolderNameFallback, true)
|
||||
defaultVenvNames := []string{
|
||||
".venv",
|
||||
"venv",
|
||||
|
@ -87,8 +94,7 @@ func (p *Python) loadContext() {
|
|||
}
|
||||
|
||||
name := platform.Base(p.language.env, venv)
|
||||
|
||||
if slices.Contains(defaultVenvNames, name) {
|
||||
if folderNameFallback && slices.Contains(defaultVenvNames, name) {
|
||||
venv = strings.TrimSuffix(venv, name)
|
||||
name = platform.Base(p.language.env, venv)
|
||||
}
|
||||
|
|
|
@ -150,14 +150,36 @@ func TestPythonPythonInContext(t *testing.T) {
|
|||
|
||||
func TestPythonVirtualEnvIgnoreDefaultVenvNames(t *testing.T) {
|
||||
cases := []struct {
|
||||
VirtualEnvName string
|
||||
Expected string
|
||||
FolderNameFallback bool
|
||||
VirtualEnvName string
|
||||
}{
|
||||
{VirtualEnvName: "/path/to/folder/.venv"},
|
||||
{VirtualEnvName: "/path/to/folder/venv"},
|
||||
{
|
||||
Expected: "folder",
|
||||
FolderNameFallback: true,
|
||||
VirtualEnvName: "/path/to/folder/.venv",
|
||||
},
|
||||
{
|
||||
Expected: "folder",
|
||||
FolderNameFallback: true,
|
||||
VirtualEnvName: "/path/to/folder/venv",
|
||||
},
|
||||
{
|
||||
Expected: ".venv",
|
||||
FolderNameFallback: false,
|
||||
VirtualEnvName: "/path/to/folder/.venv",
|
||||
},
|
||||
{
|
||||
Expected: "venv",
|
||||
FolderNameFallback: false,
|
||||
VirtualEnvName: "/path/to/folder/venv",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
env := new(mock.MockedEnvironment)
|
||||
params := &mockedLanguageParams{}
|
||||
env, props := getMockedLanguageEnv(params)
|
||||
|
||||
env.On("GOOS").Return("")
|
||||
env.On("PathSeparator").Return("/")
|
||||
env.On("CommandPath", mock2.Anything).Return("")
|
||||
|
@ -167,9 +189,12 @@ func TestPythonVirtualEnvIgnoreDefaultVenvNames(t *testing.T) {
|
|||
env.On("Getenv", "CONDA_DEFAULT_ENV").Return("")
|
||||
env.On("Getenv", "PYENV_VERSION").Return("")
|
||||
env.On("HasParentFilePath", ".python-version").Return(&platform.FileInfo{}, errors.New("no match at root level"))
|
||||
|
||||
props[FolderNameFallback] = tc.FolderNameFallback
|
||||
|
||||
python := &Python{}
|
||||
python.Init(properties.Map{}, env)
|
||||
python.Init(props, env)
|
||||
python.loadContext()
|
||||
assert.Equal(t, "folder", python.Venv)
|
||||
assert.Equal(t, tc.Expected, python.Venv)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,24 +3,28 @@
|
|||
package segments
|
||||
|
||||
func (s *Spotify) Enabled() bool {
|
||||
var err error
|
||||
// Check if running
|
||||
running := s.runAppleScriptCommand("application \"Spotify\" is running")
|
||||
if running == "false" || running == "" {
|
||||
s.Status = stopped
|
||||
return false
|
||||
}
|
||||
|
||||
s.Status = s.runAppleScriptCommand("tell application \"Spotify\" to player state as string")
|
||||
if err != nil {
|
||||
|
||||
if len(s.Status) == 0 {
|
||||
s.Status = stopped
|
||||
return false
|
||||
}
|
||||
|
||||
if s.Status == stopped {
|
||||
return false
|
||||
}
|
||||
|
||||
s.Artist = s.runAppleScriptCommand("tell application \"Spotify\" to artist of current track as string")
|
||||
s.Track = s.runAppleScriptCommand("tell application \"Spotify\" to name of current track as string")
|
||||
s.resolveIcon()
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
package segments
|
||||
|
||||
import (
|
||||
"encoding/csv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
|
@ -11,24 +10,40 @@ func (s *Spotify) Enabled() bool {
|
|||
if !s.env.IsWsl() {
|
||||
return false
|
||||
}
|
||||
|
||||
tlist, err := s.env.RunCommand("tasklist.exe", "/V", "/FI", "Imagename eq Spotify.exe", "/FO", "CSV", "/NH")
|
||||
if err != nil || strings.HasPrefix(tlist, "INFO") {
|
||||
return false
|
||||
}
|
||||
records, err := csv.NewReader(strings.NewReader(tlist)).ReadAll()
|
||||
if err != nil || len(records) == 0 {
|
||||
|
||||
records := strings.Split(tlist, "\n")
|
||||
if len(records) == 0 {
|
||||
return false
|
||||
}
|
||||
|
||||
for _, record := range records {
|
||||
title := record[len(record)-1]
|
||||
if strings.Contains(title, " - ") {
|
||||
infos := strings.Split(title, " - ")
|
||||
s.Artist = infos[0]
|
||||
s.Track = strings.Join(infos[1:], " - ")
|
||||
s.Status = playing
|
||||
s.resolveIcon()
|
||||
return true
|
||||
record = strings.TrimSpace(record)
|
||||
fields := strings.Split(record, ",")
|
||||
if len(fields) == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
// last elemant is the title
|
||||
title := fields[len(fields)-1]
|
||||
// trim leading and trailing quotes from the field
|
||||
title = strings.TrimPrefix(title, `"`)
|
||||
title = strings.TrimSuffix(title, `"`)
|
||||
if !strings.Contains(title, " - ") {
|
||||
continue
|
||||
}
|
||||
|
||||
infos := strings.Split(title, " - ")
|
||||
s.Artist = infos[0]
|
||||
s.Track = strings.Join(infos[1:], " - ")
|
||||
s.Status = playing
|
||||
s.resolveIcon()
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
|
|
@ -46,6 +46,17 @@ func TestSpotifyWsl(t *testing.T) {
|
|||
"Spotify.exe","22052","Console","1","29,040 K","Unknown","PC\user","0:00:00","N/A"
|
||||
"Spotify.exe","22072","Console","1","43,960 K","Unknown","PC\user","0:01:50","N/A"
|
||||
"Spotify.exe","10404","Console","1","256,924 K","Unknown","PC\user","0:10:49","N/A"`,
|
||||
},
|
||||
{
|
||||
Case: "Spotify playing",
|
||||
ExpectedString: "\ue602 Grabbitz - Another Form Of \"Goodbye\"",
|
||||
ExpectedEnabled: true,
|
||||
ExecOutput: `"Spotify.exe","13748","Console","1","303.744 K","Running","GARMIN\elderbroekowe","0:03:58","Grabbitz - Another Form Of "Goodbye""
|
||||
"Spotify.exe","4208","Console","1","31.544 K","Running","GARMIN\elderbroekowe","0:00:00","N/A"
|
||||
"Spotify.exe","14528","Console","1","184.020 K","Running","GARMIN\elderbroekowe","0:02:54","N/A"
|
||||
"Spotify.exe","14488","Console","1","53.828 K","Unknown","GARMIN\elderbroekowe","0:00:08","N/A"
|
||||
"Spotify.exe","14800","Console","1","29.576 K","Unknown","GARMIN\elderbroekowe","0:00:00","N/A"
|
||||
"Spotify.exe","19836","Console","1","237.360 K","Unknown","GARMIN\elderbroekowe","0:07:46","N/A"`,
|
||||
},
|
||||
{
|
||||
Case: "tasklist.exe not in path",
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package segments
|
||||
|
||||
import (
|
||||
"path"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
|
@ -123,6 +124,18 @@ func (s *Svn) setSvnStatus() {
|
|||
}
|
||||
}
|
||||
|
||||
func (s *Svn) Repo() string {
|
||||
// Get the repository name as the last path element of the repository root URL
|
||||
repo := s.getSvnCommandOutput("info", "--show-item", "repos-root-url")
|
||||
base := path.Base(repo)
|
||||
|
||||
if base == "." {
|
||||
return ""
|
||||
}
|
||||
|
||||
return base
|
||||
}
|
||||
|
||||
func (s *Svn) getSvnCommandOutput(command string, args ...string) string {
|
||||
args = append([]string{command, s.realDir}, args...)
|
||||
val, err := s.env.RunCommand(s.command, args...)
|
||||
|
|
|
@ -262,3 +262,44 @@ R Moved.File`,
|
|||
assert.Equal(t, tc.ExpectedConflicts, s.Working.HasConflicts(), tc.Case)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRepo(t *testing.T) {
|
||||
cases := []struct {
|
||||
Case string
|
||||
Repo string
|
||||
Expected string
|
||||
}{
|
||||
{
|
||||
Case: "No repo",
|
||||
Repo: "",
|
||||
Expected: "",
|
||||
},
|
||||
{
|
||||
Case: "Repo with trailing slash",
|
||||
Repo: "http://example.com/",
|
||||
Expected: "example.com",
|
||||
},
|
||||
{
|
||||
Case: "Repo without trailing slash",
|
||||
Repo: "http://example.com",
|
||||
Expected: "example.com",
|
||||
},
|
||||
{
|
||||
Case: "Repo with a path",
|
||||
Repo: "http://example.com/test/repo",
|
||||
Expected: "repo",
|
||||
},
|
||||
}
|
||||
for _, tc := range cases {
|
||||
env := new(mock.MockedEnvironment)
|
||||
env.On("RunCommand", "svn", []string{"info", "", "--show-item", "repos-root-url"}).Return(tc.Repo, nil)
|
||||
s := &Svn{
|
||||
scm: scm{
|
||||
env: env,
|
||||
command: SVNCOMMAND,
|
||||
},
|
||||
}
|
||||
|
||||
assert.Equal(t, tc.Expected, s.Repo(), tc.Case)
|
||||
}
|
||||
}
|
||||
|
|
56
src/segments/talosctl.go
Normal file
56
src/segments/talosctl.go
Normal file
|
@ -0,0 +1,56 @@
|
|||
package segments
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/jandedobbeleer/oh-my-posh/src/platform"
|
||||
"github.com/jandedobbeleer/oh-my-posh/src/properties"
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
type TalosCTL struct {
|
||||
props properties.Properties
|
||||
env platform.Environment
|
||||
|
||||
Context string `yaml:"context"`
|
||||
}
|
||||
|
||||
func (t *TalosCTL) Template() string {
|
||||
return " {{ .Context}} "
|
||||
}
|
||||
|
||||
func (t *TalosCTL) Init(props properties.Properties, env platform.Environment) {
|
||||
t.props = props
|
||||
t.env = env
|
||||
}
|
||||
|
||||
func (t *TalosCTL) Enabled() bool {
|
||||
cfgDir := filepath.Join(t.env.Home(), ".talos")
|
||||
configFile, err := t.getActiveConfig(cfgDir)
|
||||
if err != nil {
|
||||
t.env.Error(err)
|
||||
return false
|
||||
}
|
||||
|
||||
err = yaml.Unmarshal([]byte(configFile), t)
|
||||
if err != nil {
|
||||
t.env.Error(err)
|
||||
return false
|
||||
}
|
||||
|
||||
if len(t.Context) == 0 {
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func (t *TalosCTL) getActiveConfig(cfgDir string) (string, error) {
|
||||
activeConfigFile := filepath.Join(cfgDir, "config")
|
||||
activeConfigData := t.env.FileContent(activeConfigFile)
|
||||
if len(activeConfigData) == 0 {
|
||||
return "", errors.New("NO ACTIVE CONFIG FOUND")
|
||||
}
|
||||
return activeConfigData, nil
|
||||
}
|
95
src/segments/talosctl_test.go
Normal file
95
src/segments/talosctl_test.go
Normal file
|
@ -0,0 +1,95 @@
|
|||
package segments
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"github.com/jandedobbeleer/oh-my-posh/src/mock"
|
||||
"github.com/stretchr/testify/assert"
|
||||
mock2 "github.com/stretchr/testify/mock"
|
||||
)
|
||||
|
||||
func TestTalosctlSegment(t *testing.T) {
|
||||
cases := []struct {
|
||||
Case string
|
||||
ActiveConfig string
|
||||
ExpectedEnabled bool
|
||||
ExpectedString string
|
||||
}{
|
||||
{
|
||||
Case: "happy path",
|
||||
ExpectedEnabled: true,
|
||||
ActiveConfig: "context: context-name",
|
||||
ExpectedString: "context-name",
|
||||
},
|
||||
{
|
||||
Case: "no active config",
|
||||
ExpectedEnabled: false,
|
||||
},
|
||||
{
|
||||
Case: "empty config",
|
||||
ActiveConfig: "",
|
||||
ExpectedEnabled: false,
|
||||
},
|
||||
{
|
||||
Case: "bad config",
|
||||
ActiveConfig: "other-yaml: not-expected",
|
||||
ExpectedEnabled: false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
env := new(mock.MockedEnvironment)
|
||||
env.On("Home").Return("home")
|
||||
fcPath := filepath.Join("home", ".talos", "config")
|
||||
env.On("FileContent", fcPath).Return(tc.ActiveConfig)
|
||||
env.On("Error", mock2.Anything).Return()
|
||||
talos := TalosCTL{
|
||||
env: env,
|
||||
}
|
||||
talos.Enabled()
|
||||
assert.Equal(t, tc.ExpectedEnabled, talos.Enabled())
|
||||
if tc.ExpectedEnabled {
|
||||
assert.Equal(t, tc.ExpectedString, renderTemplate(env, talos.Template(), talos), tc.Case)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetTalosctlActiveConfig(t *testing.T) {
|
||||
cases := []struct {
|
||||
Case string
|
||||
ActiveConfig string
|
||||
ExpectedString string
|
||||
ExpectedError string
|
||||
}{
|
||||
{
|
||||
Case: "happy path",
|
||||
ActiveConfig: "context: context-name",
|
||||
ExpectedString: "context: context-name",
|
||||
},
|
||||
{
|
||||
Case: "no active config",
|
||||
ActiveConfig: "",
|
||||
ExpectedError: "NO ACTIVE CONFIG FOUND",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
env := new(mock.MockedEnvironment)
|
||||
env.On("Home").Return("home")
|
||||
configPath := filepath.Join("home", ".talos")
|
||||
contentPath := filepath.Join(configPath, "config")
|
||||
env.On("FileContent", contentPath).Return(tc.ActiveConfig)
|
||||
env.On("Error", mock2.Anything).Return()
|
||||
talos := TalosCTL{
|
||||
env: env,
|
||||
}
|
||||
got, err := talos.getActiveConfig(configPath)
|
||||
assert.Equal(t, tc.ExpectedString, got, tc.Case)
|
||||
if len(tc.ExpectedError) > 0 {
|
||||
assert.EqualError(t, err, tc.ExpectedError, tc.Case)
|
||||
} else {
|
||||
assert.NoError(t, err, tc.Case)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -105,7 +105,7 @@ func mockFilePresence(tc *testCase, ui5tooling *UI5Tooling, env *mock.MockedEnvi
|
|||
}
|
||||
|
||||
if match {
|
||||
if tc.DisplayMode == DisplayModeFiles && tc.WorkingDir == WorkingDirRoot {
|
||||
if tc.DisplayMode == DisplayModeFiles && tc.WorkingDir == WorkingDirRoot { //nolint: gocritic
|
||||
env.On("HasFiles", f).Return(true)
|
||||
env.On("HasFileInParentDirs", f, uint(4)).Return(false)
|
||||
// mode context, working dir != working dir root
|
||||
|
|
|
@ -110,7 +110,7 @@ func TestUnitySegment(t *testing.T) {
|
|||
}
|
||||
|
||||
// 2021.9.20f1 is used in the test cases below as a fake Unity version.
|
||||
// As such, it doesn't exist in the predfined map in unity.go. This
|
||||
// As such, it doesn't exist in the predefined map in unity.go. This
|
||||
// allows us to test the web request portion of the code, which is the
|
||||
// fallback for obtaining a C# version.
|
||||
func TestUnitySegmentCSharpWebRequest(t *testing.T) {
|
||||
|
|
|
@ -52,6 +52,7 @@ var (
|
|||
ShellIntegration bool
|
||||
RPrompt bool
|
||||
CursorPositioning bool
|
||||
PromptMark bool
|
||||
)
|
||||
|
||||
func getExecutablePath(env platform.Environment) (string, error) {
|
||||
|
@ -207,9 +208,18 @@ func PrintInit(env platform.Environment) string {
|
|||
if env.Flags().Manual {
|
||||
return "false"
|
||||
}
|
||||
|
||||
return strconv.FormatBool(setting)
|
||||
}
|
||||
|
||||
promptMark := func() string {
|
||||
if PromptMark {
|
||||
return "iterm2_prompt_mark"
|
||||
}
|
||||
|
||||
return ""
|
||||
}
|
||||
|
||||
shell := env.Flags().Shell
|
||||
configFile := env.Flags().Config
|
||||
|
||||
|
@ -273,6 +283,7 @@ func PrintInit(env platform.Environment) string {
|
|||
"::CURSOR::", strconv.FormatBool(CursorPositioning),
|
||||
"::UPGRADE::", strconv.FormatBool(hasNotice),
|
||||
"::UPGRADENOTICE::", notice,
|
||||
"::PROMPT_MARK::", promptMark(),
|
||||
).Replace(script)
|
||||
}
|
||||
|
||||
|
|
|
@ -23,16 +23,19 @@ function fish_prompt
|
|||
::OMP:: print transient --config $POSH_THEME --shell fish --status $omp_status_cache --pipestatus="$omp_pipestatus_cache" --execution-time $omp_duration --stack-count $omp_stack_count --shell-version $FISH_VERSION --no-status=$omp_no_exit_code
|
||||
return
|
||||
end
|
||||
|
||||
set --global omp_status_cache $omp_status_cache_temp
|
||||
set --global omp_pipestatus_cache $omp_pipestatus_cache_temp
|
||||
set --global omp_stack_count (count $dirstack)
|
||||
set --global omp_duration "$CMD_DURATION$cmd_duration"
|
||||
set --global omp_no_exit_code false
|
||||
|
||||
# check if variable set, < 3.2 case
|
||||
if set --query omp_lastcommand; and test "$omp_lastcommand" = ""
|
||||
set omp_duration 0
|
||||
set omp_no_exit_code true
|
||||
end
|
||||
|
||||
# works with fish >=3.2
|
||||
if set --query omp_last_status_generation; and test "$omp_last_status_generation" = "$status_generation"
|
||||
set omp_duration 0
|
||||
|
@ -41,16 +44,23 @@ function fish_prompt
|
|||
# first execution - $status_generation is 0, $omp_last_status_generation is empty
|
||||
set omp_no_exit_code true
|
||||
end
|
||||
|
||||
if set --query status_generation
|
||||
set --global --export omp_last_status_generation $status_generation
|
||||
end
|
||||
|
||||
set_poshcontext
|
||||
|
||||
# validate if the user cleared the screen
|
||||
set --local omp_cleared false
|
||||
set --local last_command (history search --max 1)
|
||||
|
||||
if test "$last_command" = "clear"
|
||||
set omp_cleared true
|
||||
end
|
||||
|
||||
::PROMPT_MARK::
|
||||
|
||||
::OMP:: print primary --config $POSH_THEME --shell fish --status $omp_status_cache --pipestatus="$omp_pipestatus_cache" --execution-time $omp_duration --stack-count $omp_stack_count --shell-version $FISH_VERSION --cleared=$omp_cleared --no-status=$omp_no_exit_code
|
||||
end
|
||||
|
||||
|
|
|
@ -23,12 +23,15 @@ $env.PROMPT_MULTILINE_INDICATOR = (^::OMP:: print secondary $"--config=($env.POS
|
|||
$env.PROMPT_COMMAND = { ||
|
||||
# hack to set the cursor line to 1 when the user clears the screen
|
||||
# this obviously isn't bulletproof, but it's a start
|
||||
let clear = (history | last 1 | get 0.command) == "clear"
|
||||
mut clear = false
|
||||
if $nu.history-enabled {
|
||||
$clear = (history | is-empty) or ((history | last 1 | get 0.command) == "clear")
|
||||
}
|
||||
|
||||
^::OMP:: print primary $"--config=($env.POSH_THEME)" --shell=nu $"--shell-version=($env.POSH_SHELL_VERSION)" $"--execution-time=(posh_cmd_duration)" $"--status=($env.LAST_EXIT_CODE)" $"--terminal-width=(posh_width)" $"--cleared=($clear)"
|
||||
}
|
||||
|
||||
$env.PROMPT_COMMAND_RIGHT = { ||
|
||||
$env.PROMPT_COMMAND_RIGHT = { ||
|
||||
^::OMP:: print right $"--config=($env.POSH_THEME)" --shell=nu $"--shell-version=($env.POSH_SHELL_VERSION)" $"--execution-time=(posh_cmd_duration)" $"--status=($env.LAST_EXIT_CODE)" $"--terminal-width=(posh_width)"
|
||||
}
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@ export POSH_PID=$$
|
|||
export POWERLINE_COMMAND="oh-my-posh"
|
||||
export CONDA_PROMPT_MODIFIER=false
|
||||
export POSH_PROMPT_COUNT=0
|
||||
export ZLE_RPROMPT_INDENT=0
|
||||
|
||||
# set secondary prompt
|
||||
PS2="$(::OMP:: print secondary --config="$POSH_THEME" --shell=zsh)"
|
||||
|
|
|
@ -28,15 +28,16 @@ var (
|
|||
"ShellVersion",
|
||||
"UserName",
|
||||
"HostName",
|
||||
"Env",
|
||||
"Data",
|
||||
"Code",
|
||||
"Env",
|
||||
"OS",
|
||||
"WSL",
|
||||
"Segments",
|
||||
"Templates",
|
||||
"PromptCount",
|
||||
"Segments",
|
||||
"SHLVL",
|
||||
"Templates",
|
||||
"Var",
|
||||
"Data",
|
||||
}
|
||||
)
|
||||
|
||||
|
@ -158,7 +159,7 @@ func (t *Text) cleanTemplate() {
|
|||
continue
|
||||
}
|
||||
// end of a variable, needs to be appended
|
||||
if !isKnownVariable(property) {
|
||||
if !isKnownVariable(property) { //nolint: gocritic
|
||||
result += ".Data" + property
|
||||
} else if strings.HasPrefix(property, ".Segments") && !strings.HasSuffix(property, ".Contains") {
|
||||
// as we can't provide a clean way to access the list
|
||||
|
|
|
@ -59,15 +59,16 @@ func Latest(env platform.Environment) (string, error) {
|
|||
//
|
||||
// The upgrade check is only performed every other week.
|
||||
func Notice(env platform.Environment) (string, bool) {
|
||||
// never validate when we install using the Windows Store
|
||||
if env.Getenv("POSH_INSTALLER") == "ws" {
|
||||
return "", false
|
||||
}
|
||||
// do not check when last validation was < 1 week ago
|
||||
if _, OK := env.Cache().Get(CACHEKEY); OK {
|
||||
return "", false
|
||||
}
|
||||
|
||||
// never validate when we install using the Windows Store
|
||||
if env.Getenv("POSH_INSTALLER") == "ws" {
|
||||
return "", false
|
||||
}
|
||||
|
||||
latest, err := Latest(env)
|
||||
if err != nil {
|
||||
return "", false
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
"style": "folder"
|
||||
},
|
||||
"style": "powerline",
|
||||
"template": " \uf07b\uea9c{{ .Path }} ",
|
||||
"template": " \uf07b\uea9c {{ .Path }} ",
|
||||
"type": "path"
|
||||
},
|
||||
{
|
||||
|
@ -59,7 +59,7 @@
|
|||
"threshold": 0
|
||||
},
|
||||
"style": "diamond",
|
||||
"template": " \ueba2{{ .FormattedMs }}\u2800",
|
||||
"template": " \ueba2 {{ .FormattedMs }}\u2800",
|
||||
"trailing_diamond": "\ue0b4",
|
||||
"type": "executiontime"
|
||||
}
|
||||
|
@ -204,13 +204,14 @@
|
|||
"background": "#b2bec3",
|
||||
"foreground": "#222222",
|
||||
"leading_diamond": "\ue0b6",
|
||||
"trailing_diamond": "<transparent,background>\ue0b2</>",
|
||||
"properties": {
|
||||
"linux": "\ue712",
|
||||
"macos": "\ue711",
|
||||
"windows": "\ue70f"
|
||||
},
|
||||
"style": "diamond",
|
||||
"template": " {{ if .WSL }}WSL at {{ end }}{{.Icon}}<#222222> \ue0b2</>",
|
||||
"template": " {{ if .WSL }}WSL at {{ end }}{{.Icon}} ",
|
||||
"type": "os"
|
||||
},
|
||||
{
|
||||
|
@ -222,14 +223,14 @@
|
|||
],
|
||||
"foreground": "#262626",
|
||||
"invert_powerline": true,
|
||||
"leading_diamond": "\ue0b2",
|
||||
"powerline_symbol": "\ue0b2",
|
||||
"properties": {
|
||||
"charged_icon": "\uf240 ",
|
||||
"charging_icon": "\uf1e6 ",
|
||||
"discharging_icon": "\ue234 "
|
||||
},
|
||||
"style": "diamond",
|
||||
"template": " {{ if not .Error }}{{ .Icon }}{{ .Percentage }}{{ end }}{{ .Error }}\uf295 <#262626>\ue0b2</>",
|
||||
"style": "powerline",
|
||||
"template": " {{ if not .Error }}{{ .Icon }}{{ .Percentage }}{{ end }}{{ .Error }}\uf295 ",
|
||||
"type": "battery"
|
||||
},
|
||||
{
|
||||
|
|
|
@ -7,10 +7,12 @@
|
|||
"cloud-text-amazon": "#4285F4",
|
||||
"cloud-text-azure": "#4285F4",
|
||||
"cloud-text-gcp": "#4285F4",
|
||||
"cloud-text-firebase": "#FFA000",
|
||||
"error-background": "#dd0033",
|
||||
"error-text": "#242424",
|
||||
"git-text": "#238636",
|
||||
"kubernetes-text": "#FFBB00",
|
||||
"talosctl-text": "#FF6C00",
|
||||
"symbol-color": "#ffffff",
|
||||
"timer-text": "#dd0033"
|
||||
},
|
||||
|
@ -38,6 +40,14 @@
|
|||
"template": "<p:symbol-color>\uf308</> {{.Context}}{{if .Namespace}} \uf061 {{.Namespace}}{{end}}",
|
||||
"type": "kubectl"
|
||||
},
|
||||
{
|
||||
"background": "p:background-color",
|
||||
"foreground": "p:talosctl-text",
|
||||
"style": "powerline",
|
||||
"powerline_symbol": "\ue0b4",
|
||||
"template": "<p:symbol-color>\udb84\udcfe</> {{.Context}}",
|
||||
"type": "talosctl"
|
||||
},
|
||||
{
|
||||
"background": "p:background-color",
|
||||
"foreground": "p:cloud-text-amazon",
|
||||
|
@ -76,6 +86,14 @@
|
|||
"template": " <p:symbol-color>\ue7b2</> {{ .Project }}",
|
||||
"type": "gcp"
|
||||
},
|
||||
{
|
||||
"background": "p:background-color",
|
||||
"foreground": "p:cloud-text-firebase",
|
||||
"style": "powerline",
|
||||
"powerline_symbol": "\ue0b4",
|
||||
"template": " <p:symbol-color>\udb82\udd67</> {{ .Project }}",
|
||||
"type": "firebase"
|
||||
},
|
||||
{
|
||||
"background": "p:background-color",
|
||||
"foreground": "p:git-text",
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# yaml-language-server: $schema=https://raw.githubusercontent.com/JanDeDobbeleer/oh-my-posh/main/themes/schema.json
|
||||
final_space: true
|
||||
blocks:
|
||||
- type: prompt
|
||||
alignment: left
|
||||
|
@ -27,7 +27,7 @@ blocks:
|
|||
opensuse:
|
||||
raspbian:
|
||||
ubuntu:
|
||||
windows:
|
||||
windows:
|
||||
wsl:
|
||||
wsl_separator:
|
||||
template: " {{ if .WSL }}{{ end }}{{.Icon}}═"
|
||||
|
@ -42,7 +42,7 @@ blocks:
|
|||
powerline_symbol:
|
||||
background: magenta
|
||||
foreground: black
|
||||
template: " {{ if .SSHSession }} {{ end }}{{ .UserName }}@{{ .HostName }} "
|
||||
template: " {{ if .SSHSession }} {{ end }}{{ .UserName }}@{{ .HostName }} "
|
||||
- type: angular
|
||||
style: powerline
|
||||
powerline_symbol:
|
||||
|
@ -50,7 +50,7 @@ blocks:
|
|||
foreground: black
|
||||
properties:
|
||||
fetch_version: true
|
||||
template: " ﮰ {{ if .Error }}{{ .Error }}{{ else }}{{ .Full }}{{ end }} "
|
||||
template: " {{ if .Error }}{{ .Error }}{{ else }}{{ .Full }}{{ end }} "
|
||||
- type: aws
|
||||
style: powerline
|
||||
powerline_symbol:
|
||||
|
@ -83,7 +83,7 @@ blocks:
|
|||
foreground: black
|
||||
properties:
|
||||
fetch_version: true
|
||||
template: " ﳑ {{ if .Error }}{{ .Error }}{{ else }}{{ .Full }}{{ end }} "
|
||||
template: " {{ if .Error }}{{ .Error }}{{ else }}{{ .Full }}{{ end }} "
|
||||
- type: java
|
||||
style: powerline
|
||||
powerline_symbol:
|
||||
|
@ -103,7 +103,7 @@ blocks:
|
|||
powerline_symbol:
|
||||
background: lightYellow
|
||||
foreground: black
|
||||
template: " ﴱ {{.Context}}{{if .Namespace}} :: {{.Namespace}}{{end}} "
|
||||
template: " {{.Context}}{{if .Namespace}} :: {{.Namespace}}{{end}} "
|
||||
- type: node
|
||||
style: powerline
|
||||
powerline_symbol:
|
||||
|
@ -111,7 +111,7 @@ blocks:
|
|||
foreground: black
|
||||
properties:
|
||||
fetch_version: true
|
||||
template: " {{ if .PackageManagerIcon }}{{ .PackageManagerIcon }} {{ end }}{{ .Full }} "
|
||||
template: " {{ if .PackageManagerIcon }}{{ .PackageManagerIcon }} {{ end }}{{ .Full }} "
|
||||
- type: php
|
||||
style: powerline
|
||||
powerline_symbol:
|
||||
|
@ -192,7 +192,7 @@ blocks:
|
|||
fetch_status: true
|
||||
fetch_upstream_icon: true
|
||||
fetch_worktree_count: true
|
||||
template: "{{ .UpstreamIcon }}{{ .HEAD }}{{if .BranchStatus }} {{ .BranchStatus }}{{ end }}{{ if .Working.Changed }} {{ .Working.String }}{{ end }}{{ if and (.Working.Changed) (.Staging.Changed) }} |{{ end }}{{ if .Staging.Changed }} {{ .Staging.String }}{{ end }}{{ if gt .StashCount 0 }} {{ .StashCount }}{{ end }}"
|
||||
template: "{{ .UpstreamIcon }}{{ .HEAD }}{{if .BranchStatus }} {{ .BranchStatus }}{{ end }}{{ if .Working.Changed }} {{ .Working.String }}{{ end }}{{ if and (.Working.Changed) (.Staging.Changed) }} |{{ end }}{{ if .Staging.Changed }} {{ .Staging.String }}{{ end }}{{ if gt .StashCount 0 }} {{ .StashCount }}{{ end }}"
|
||||
- type: prompt
|
||||
alignment: left
|
||||
newline: true
|
||||
|
@ -210,7 +210,7 @@ blocks:
|
|||
foreground: black
|
||||
properties:
|
||||
always_enabled: true
|
||||
template: " {{ if gt .Code 0 }}{{ else }}{{ end }}{{ if eq ( gt .Code 0 ) .Segments.Path.Writable}} {{ end }}"
|
||||
template: " {{ if gt .Code 0 }} {{ else }} {{ end }}{{ if eq ( gt .Code 0 ) .Segments.Path.Writable}} {{ end }}"
|
||||
- type: path
|
||||
style: powerline
|
||||
powerline_symbol:
|
||||
|
@ -221,10 +221,10 @@ blocks:
|
|||
properties:
|
||||
style: agnoster_short
|
||||
folder_icon:
|
||||
folder_separator_icon: " "
|
||||
home_icon:
|
||||
folder_separator_icon: " "
|
||||
home_icon:
|
||||
max_depth: 3
|
||||
template: "{{ if eq ( gt .Code 0 ) .Writable }} {{ end }} {{ .Path }}{{ if not .Writable }} {{ end }}{{ if and .Writable .Root }} {{end}}"
|
||||
template: "{{ if eq ( gt .Code 0 ) .Writable }} {{ end }} {{ .Path }}{{ if not .Writable }} {{ end }}{{ if and .Writable .Root }} {{end}} "
|
||||
- type: text
|
||||
style: diamond
|
||||
trailing_diamond:
|
||||
|
@ -234,7 +234,7 @@ blocks:
|
|||
foreground: white
|
||||
properties:
|
||||
root_icon:
|
||||
template: "{{ if and .Root ( not .Segments.Path.Writable ) }} {{ end }}{{ if and .Root .Segments.Path.Writable }} {{ end }} \b"
|
||||
template: "{{ if not .Root }}\u2800{{ end }}{{ if and .Root ( not .Segments.Path.Writable ) }} {{ end }}{{ if and .Root .Segments.Path.Writable }} {{ end }}"
|
||||
console_title_template: "{{ .Folder }}"
|
||||
palette:
|
||||
black: "#1B1A23"
|
||||
|
|
|
@ -52,7 +52,7 @@ blocks:
|
|||
always_enabled: true
|
||||
style: round
|
||||
style: powerline
|
||||
template: " 羽{{ .FormattedMs }} "
|
||||
template: " {{ .FormattedMs }} "
|
||||
type: executiontime
|
||||
|
||||
# Exit code
|
||||
|
@ -84,14 +84,14 @@ blocks:
|
|||
foreground: p:white
|
||||
leading_diamond:
|
||||
properties:
|
||||
charged_icon:
|
||||
charging_icon:
|
||||
discharging_icon: " "
|
||||
charged_icon:
|
||||
charging_icon:
|
||||
discharging_icon: " "
|
||||
style: diamond
|
||||
template: " {{.Templates }}{{ .Percentage}} <transparent></>"
|
||||
template: " {{.Templates }}{{ .Percentage}} <transparent></>"
|
||||
templates:
|
||||
- '{{if eq "Discharging" .State.String}}{{if lt .Percentage 11}}{{else if lt .Percentage 21}}{{else if lt .Percentage 31}}{{else if lt .Percentage 41}}{{else if lt .Percentage 51}}{{else if lt .Percentage 61}}{{else if lt .Percentage 71}}{{else if lt .Percentage 81}}{{else if lt .Percentage 91}}{{else}}{{end}}{{end}}'
|
||||
- '{{if eq "Charging" .State.String}}{{ if lt .Percentage 21}}{{else if lt .Percentage 31}}{{else if lt .Percentage 41}}{{else if lt .Percentage 61}}{{else if lt .Percentage 81}}{{else if lt .Percentage 91}}{{else}}{{end}}{{end}}'
|
||||
- '{{if eq "Discharging" .State.String}}{{if lt .Percentage 11}}{{else if lt .Percentage 21}}{{else if lt .Percentage 31}}{{else if lt .Percentage 41}}{{else if lt .Percentage 51}}{{else if lt .Percentage 61}}{{else if lt .Percentage 71}}{{else if lt .Percentage 81}}{{else if lt .Percentage 91}}{{else}}{{end}}{{end}}'
|
||||
- '{{if eq "Charging" .State.String}}{{ if lt .Percentage 21}}{{else if lt .Percentage 31}}{{else if lt .Percentage 41}}{{else if lt .Percentage 61}}{{else if lt .Percentage 81}}{{else if lt .Percentage 91}}{{else}}{{end}}{{end}}'
|
||||
templates_logic: first_match
|
||||
type: battery
|
||||
|
||||
|
@ -117,7 +117,7 @@ blocks:
|
|||
if ! res=$(curl -s wttr.in -Gsm2 --data-urlencode "format=j1"); then
|
||||
echo "$now"
|
||||
date +'%s' >/tmp/last_update.w
|
||||
echo 睊 >/tmp/weather.w
|
||||
echo >/tmp/weather.w
|
||||
rm /tmp/w_lock.w
|
||||
exit 0
|
||||
fi
|
||||
|
@ -125,7 +125,7 @@ blocks:
|
|||
temp=$(jq -r .temp_C <<<"$res")
|
||||
feels_like=$(jq -r .FeelsLikeC <<<"$res")
|
||||
[[ $(bc -l <<<"$feels_like!=$temp") -eq 1 ]] && feels_string=" feels $feels_like°C"
|
||||
WWC_MAP='{"113":"Sunny","116":"PartlyCloudy","119":"Cloudy","122":"VeryCloudy","143":"Fog","176":"LightShowers","179":"LightSleetShowers","182":"LightSleet","185":"LightSleet","200":"ThunderyShowers","227":"LightSnow","230":"HeavySnow","248":"Fog","260":"Fog","263":"LightShowers","266":"LightRain","281":"LightSleet","284":"LightSleet","293":"LightRain","296":"LightRain","299":"HeavyShowers","302":"HeavyRain","305":"HeavyShowers","308":"HeavyRain","311":"LightSleet","314":"LightSleet","317":"LightSleet","320":"LightSnow","323":"LightSnowShowers","326":"LightSnowShowers","329":"HeavySnow","332":"HeavySnow","335":"HeavySnowShowers","338":"HeavySnow","350":"LightSleet","353":"LightShowers","356":"HeavyShowers","359":"HeavyRain","362":"LightSleetShowers","365":"LightSleetShowers","368":"LightSnowShowers","371":"HeavySnowShowers","374":"LightSleetShowers","377":"LightSleet","386":"ThunderyShowers","389":"ThunderyHeavyRain","392":"ThunderySnowShowers","395":"HeavySnowShowers"}';NF_DAY_MAP='{"Unknown":"ﮊ","Cloudy":"","Fog":"","HeavyRain":"","HeavyShowers":"","HeavySnow":"","HeavySnowShowers":"","LightRain":"","LightShowers":"","LightSleet":"","LightSleetShowers":"","LightSnow":"","LightSnowShowers":"","PartlyCloudy":"","Sunny":"","ThunderyHeavyRain":"","ThunderyShowers":"","ThunderySnowShowers":"","VeryCloudy":""}';NF_NIGHT_MAP='{"Unknown":"ﮊ","Cloudy":"","Fog":"","HeavyRain":"","HeavyShowers":"","HeavySnow":"","HeavySnowShowers":"","LightRain":"","LightShowers":"","LightSleet":"","LightSleetShowers":"","LightSnow":"","LightSnowShowers":"","PartlyCloudy":"","Sunny":"","ThunderyHeavyRain":"","ThunderyShowers":"","ThunderySnowShowers":"","VeryCloudy":""}'
|
||||
WWC_MAP='{"113":"Sunny","116":"PartlyCloudy","119":"Cloudy","122":"VeryCloudy","143":"Fog","176":"LightShowers","179":"LightSleetShowers","182":"LightSleet","185":"LightSleet","200":"ThunderyShowers","227":"LightSnow","230":"HeavySnow","248":"Fog","260":"Fog","263":"LightShowers","266":"LightRain","281":"LightSleet","284":"LightSleet","293":"LightRain","296":"LightRain","299":"HeavyShowers","302":"HeavyRain","305":"HeavyShowers","308":"HeavyRain","311":"LightSleet","314":"LightSleet","317":"LightSleet","320":"LightSnow","323":"LightSnowShowers","326":"LightSnowShowers","329":"HeavySnow","332":"HeavySnow","335":"HeavySnowShowers","338":"HeavySnow","350":"LightSleet","353":"LightShowers","356":"HeavyShowers","359":"HeavyRain","362":"LightSleetShowers","365":"LightSleetShowers","368":"LightSnowShowers","371":"HeavySnowShowers","374":"LightSleetShowers","377":"LightSleet","386":"ThunderyShowers","389":"ThunderyHeavyRain","392":"ThunderySnowShowers","395":"HeavySnowShowers"}';NF_DAY_MAP='{"Unknown":"","Cloudy":"","Fog":"","HeavyRain":"","HeavyShowers":"","HeavySnow":"","HeavySnowShowers":"","LightRain":"","LightShowers":"","LightSleet":"","LightSleetShowers":"","LightSnow":"","LightSnowShowers":"","PartlyCloudy":"","Sunny":"","ThunderyHeavyRain":"","ThunderyShowers":"","ThunderySnowShowers":"","VeryCloudy":""}';NF_NIGHT_MAP='{"Unknown":"","Cloudy":"","Fog":"","HeavyRain":"","HeavyShowers":"","HeavySnow":"","HeavySnowShowers":"","LightRain":"","LightShowers":"","LightSleet":"","LightSleetShowers":"","LightSnow":"","LightSnowShowers":"","PartlyCloudy":"","Sunny":"","ThunderyHeavyRain":"","ThunderyShowers":"","ThunderySnowShowers":"","VeryCloudy":""}'
|
||||
cur_h="$(date +'%H')" ;wwc="$(jq '.weatherCode' <<<"$res")"
|
||||
if [[ $cur_h -gt 18 || $cur_h -lt 6 ]]; then icon=$(jq -r ".$(echo "$WWC_MAP" | jq -r ".$wwc")" <<<"$NF_DAY_MAP")
|
||||
else icon=$(jq -r ".$(echo "$WWC_MAP" | jq -r ".$wwc")" <<<"$NF_NIGHT_MAP"); fi
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue