Last active
July 28, 2026 11:33
-
-
Save Gravifer/7b27c219fed8f79cbdf1a2d123fac312 to your computer and use it in GitHub Desktop.
Git & Jujutsu aware oh-my-posh theme, based on the built-in "tokyo"
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| if ($global:GraviferMainWorktreeCache -isnot [hashtable]) { | |
| $global:GraviferMainWorktreeCache = @{} | |
| } | |
| function global:Set-GraviferPoshContext { | |
| param([bool]$originalStatus) | |
| Remove-Item -LiteralPath 'Env:GRAVIFER_MAIN_WORKTREE' -ErrorAction SilentlyContinue | |
| $location = Get-Location | |
| if ($location.Provider.Name -ne 'FileSystem') { | |
| return | |
| } | |
| $directory = [System.IO.DirectoryInfo]::new($location.ProviderPath) | |
| while ($null -ne $directory) { | |
| $dotGit = [System.IO.Path]::Combine($directory.FullName, '.git') | |
| if ([System.IO.Directory]::Exists($dotGit)) { | |
| return | |
| } | |
| if ([System.IO.File]::Exists($dotGit)) { | |
| try { | |
| $gitDirLine = [System.IO.File]::ReadAllText($dotGit).Trim() | |
| if (-not $gitDirLine.StartsWith('gitdir:', [System.StringComparison]::OrdinalIgnoreCase)) { | |
| return | |
| } | |
| $gitDirValue = $gitDirLine.Substring(7).Trim() | |
| if ([System.IO.Path]::IsPathRooted($gitDirValue)) { | |
| $gitDir = [System.IO.Path]::GetFullPath($gitDirValue) | |
| } | |
| else { | |
| $gitDir = [System.IO.Path]::GetFullPath( | |
| [System.IO.Path]::Combine($directory.FullName, $gitDirValue) | |
| ) | |
| } | |
| $commonDirFile = [System.IO.Path]::Combine($gitDir, 'commondir') | |
| if (-not [System.IO.File]::Exists($commonDirFile)) { | |
| return | |
| } | |
| if (-not $global:GraviferMainWorktreeCache.ContainsKey($gitDir)) { | |
| $mainWorktree = '' | |
| $worktreeOutput = & git -C $directory.FullName worktree list --porcelain -z 2>$null | |
| if ($LASTEXITCODE -eq 0) { | |
| $outputText = $worktreeOutput -join '' | |
| $firstWorktree = $outputText -split "`0" | | |
| Where-Object { $_.StartsWith('worktree ', [System.StringComparison]::Ordinal) } | | |
| Select-Object -First 1 | |
| if ($null -ne $firstWorktree) { | |
| $mainWorktree = $firstWorktree.Substring(9) | |
| } | |
| } | |
| $global:GraviferMainWorktreeCache[$gitDir] = $mainWorktree | |
| } | |
| $cachedMainWorktree = $global:GraviferMainWorktreeCache[$gitDir] | |
| if (-not [string]::IsNullOrEmpty($cachedMainWorktree)) { | |
| $env:GRAVIFER_MAIN_WORKTREE = $cachedMainWorktree | |
| } | |
| } | |
| catch { | |
| return | |
| } | |
| return | |
| } | |
| $directory = $directory.Parent | |
| } | |
| } | |
| Set-Alias -Name Set-PoshContext -Value Set-GraviferPoshContext -Scope Global -Force |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| { | |
| "$schema": "https://raw.githubusercontent.com/JanDeDobbeleer/oh-my-posh/main/themes/schema.json", | |
| "palette": { | |
| "jujutsu-change-id": "#e3e50a", | |
| "jujutsu-change-id-rest": "darken(p:jujutsu-change-id, 35)" | |
| }, | |
| "blocks": [ | |
| { | |
| "alignment": "left", | |
| "leading_diamond": "<#7eb8da>\u250f</>", | |
| "segments": [ | |
| { | |
| "foreground": "#7eb8da", | |
| "properties": { | |
| "time_format": "2006/01/02 15:04:05" | |
| }, | |
| "style": "diamond", | |
| "template": "[<#ffffff>\uf073</> {{ .CurrentDate | date .Format }}]", | |
| "type": "time" | |
| }, | |
| { | |
| "foreground": "#7eb8da", | |
| "style": "plain", | |
| "template": "[<#ffffff>\ueb99</> {{ .UserName }} :: <#ffffff>\uf108</> {{ .HostName }}]", | |
| "type": "session" | |
| }, | |
| { | |
| "foreground": "#be9ddf", | |
| "style": "diamond", | |
| "template": "[<#ffffff>\ue266</> RAM: {{ (div ((sub .PhysicalTotalMemory .PhysicalAvailableMemory)|float64) 1073741824.0) }}/{{ (div .PhysicalTotalMemory 1073741824.0) }}GB]", | |
| "type": "sysinfo" | |
| }, | |
| { | |
| "foreground": "#f36943", | |
| "foreground_templates": [ | |
| "{{if eq \"Charging\" .State.String}}#40c4ff{{end}}", | |
| "{{if eq \"Discharging\" .State.String}}#ff5722{{end}}", | |
| "{{if eq \"Full\" .State.String}}#4caf50{{end}}" | |
| ], | |
| "properties": { | |
| "charged_icon": "<#ffffff>\ue22f</> ", | |
| "charging_icon": "\ueb2d ", | |
| "discharging_icon": "<#ffff00>\uf244</> " | |
| }, | |
| "style": "plain", | |
| "template": "[{{ if not .Error }}{{ .Icon }}{{ .Percentage }}{{ end }}{{ .Error }}\uf295]", | |
| "type": "battery" | |
| }, | |
| { | |
| "foreground": "#be9ddf", | |
| "properties": { | |
| "style": "dallas", | |
| "threshold": 0 | |
| }, | |
| "style": "diamond", | |
| "template": "[<#ffffff>\uf252</> {{ .FormattedMs }}s]", | |
| "type": "executiontime" | |
| } | |
| ], | |
| "type": "prompt" | |
| }, | |
| { | |
| "alignment": "left", | |
| "newline": true, | |
| "leading_diamond": "<#7eb8da>\u2523</>", | |
| "segments": [ | |
| { | |
| "foreground": "#7eb8da", | |
| "style": "diamond", | |
| "template": "[<#ffffff>\uebd8</> Subscription: <#ffff00>{{ .Name }}</>]", | |
| "type": "az" | |
| }, | |
| { | |
| "foreground": "#7eb8da", | |
| "style": "diamond", | |
| "template": "[<#ffffff>\uebd8</> Azure Developer CLI Environment: <#ffff00>{{ .DefaultEnvironment }}</> :: <#ffff00>{{ .Version }}</>]", | |
| "type": "azd" | |
| }, | |
| { | |
| "foreground": "#7eb8da", | |
| "style": "diamond", | |
| "template": "[<#ffffff>\uf270</> <#ffff00>{{ .Profile }}</>{{if .Region}}@<#ffff00>{{ .Region }}</>{{ end }}]", | |
| "type": "aws" | |
| }, | |
| { | |
| "foreground": "#7eb8da", | |
| "style": "diamond", | |
| "template": "[{{ if .Error }}{{ .Error }}{{ else }}<#ffffff>\uf1a0</> <#ffff00>{{ .Project }}</> :: <#ffff00>{{.Account}}</>{{ end }}]", | |
| "type": "gcp" | |
| }, | |
| { | |
| "foreground": "#ffa5d8", | |
| "style": "diamond", | |
| "template": "[<#ffffff>\uf10fe</> <#ffff00>{{.Context}}</>{{if .Namespace}} :: <#ffff00>{{.Namespace}}</>{{end}}]", | |
| "type": "kubectl" | |
| }, | |
| { | |
| "foreground": "#ffa5d8", | |
| "style": "diamond", | |
| "template": "[{{ if .Error }}{{ .Error }}{{ else }}{{ if .Name }}<#ffffff>\uf487</> {{ .Name }}{{ end }}{{ if .Target }} {{ .Target }}{{ end }}{{ end }}]", | |
| "type": "project" | |
| } | |
| ], | |
| "type": "prompt" | |
| }, | |
| { | |
| "alignment": "left", | |
| "newline": true, | |
| "leading_diamond": "<#7eb8da>\u2523</>", | |
| "segments": [ | |
| { | |
| "foreground": "#7eb8da", | |
| "properties": { | |
| "folder_separator_icon": "/", | |
| "style": "full" | |
| }, | |
| "style": "diamond", | |
| "template": "[<#ffffff>\uf115</> <#98bfad>{{ $raw := .$.AbsolutePWD }}{{ $full := .Path }}{{ if hasPrefix \"\\\\\\\\\" $raw }}{{ $raw }}{{ else if not (.Segments.Contains \"Git\") }}{{ $full }}{{ else }}{{ $git := .Segments.Git }}{{ $rel := replace \"\\\\\" \"/\" $git.RelativeDir }}{{ if or (eq $rel \"\") (le (len (splitList \"\" $full)) 52) }}{{ $full }}{{ else }}{{ $parts := splitList \"/\" $full }}{{ $relParts := splitList \"/\" $rel }}{{ $repoIndex := sub (len $parts) (add (len $relParts) 1) }}{{ if lt $repoIndex 1 }}{{ $full }}{{ else }}{{ $root := index $parts 0 }}{{ $repo := index $parts $repoIndex }}{{ $base := printf \"%s/%s\" $root $repo }}{{ if eq $repoIndex 2 }}{{ $base = printf \"%s/%s/%s\" $root (index $parts 1) $repo }}{{ else if gt $repoIndex 2 }}{{ $base = printf \"%s/%s/\u2026/%s\" $root (index $parts 1) $repo }}{{ end }}{{ if eq (len $relParts) 1 }}{{ $base }}/{{ index $relParts 0 }}{{ else }}{{ $firstRel := index $relParts 0 }}{{ $remainingCount := int (sub (len $relParts) 1) }}{{ $tail := list }}{{ $locked := false }}{{ range $i := untilStep (int (sub (len $relParts) 1)) 0 -1 }}{{ if not $locked }}{{ $candidate := prepend $tail (index $relParts $i) }}{{ $candidatePath := printf \"%s/%s/\u2026/%s\" $base $firstRel (join \"/\" $candidate) }}{{ if eq (len $candidate) $remainingCount }}{{ $candidatePath = printf \"%s/%s/%s\" $base $firstRel (join \"/\" $candidate) }}{{ end }}{{ if or (eq (len $tail) 0) (le (len (splitList \"\" $candidatePath)) 52) }}{{ $tail = $candidate }}{{ else }}{{ $locked = true }}{{ end }}{{ end }}{{ end }}{{ if eq (len $tail) $remainingCount }}{{ $base }}/{{ $firstRel }}/{{ join \"/\" $tail }}{{ else }}{{ $base }}/{{ $firstRel }}/\u2026/{{ join \"/\" $tail }}{{ end }}{{ end }}{{ end }}{{ end }}{{ end }}</>]", | |
| "type": "path" | |
| }, | |
| { | |
| "foreground": "#ffa5d8", | |
| "properties": { | |
| "change_id_min_len": 8, | |
| "fetch_status": true, | |
| "ignore_working_copy": true | |
| }, | |
| "style": "plain", | |
| "template": "{{ $hasGit := .Segments.Contains \"Git\" }}[<#ffffff>{{ if $hasGit }}{{ trim .Segments.Git.UpstreamIcon }}{{ else }}\ue5fb{{ end }} </><p:jujutsu-change-id>({{ .ChangeIDPrefix }}</><p:jujutsu-change-id-rest>{{ .ChangeIDRest }}</><p:jujutsu-change-id>{{ if .Working.Changed }}{{ if not $hasGit }} {{ .Working.String }}{{ else }}{{ $git := .Segments.Git }}{{ if and (not $git.Working.Changed) (not $git.Staging.Changed) }} {{ .Working.String }}{{ end }}{{ end }}{{ end }})</>{{ if $hasGit }} {{ else }}]{{ end }}", | |
| "type": "jujutsu" | |
| }, | |
| { | |
| "foreground": "#ffa5d8", | |
| "properties": { | |
| "fetch_stash_count": true, | |
| "fetch_status": true, | |
| "fetch_upstream_icon": true | |
| }, | |
| "style": "plain", | |
| "template": "{{ if not (.Segments.Contains \"Jujutsu\") }}[<#ffffff>{{ .UpstreamIcon }} </>{{ end }}{{ .HEAD }}{{if .BranchStatus }} {{ .BranchStatus }}{{ end }}{{ if and .IsWorkTree .Env.GRAVIFER_MAIN_WORKTREE }} <#ffffff>\udb81\udcc1</> <#98bfad>{{ .Env.GRAVIFER_MAIN_WORKTREE }}</>{{ end }}{{ if .Working.Changed }} <#ffffff>\uf044</> {{ .Working.String }}{{ end }}{{ if and (.Working.Changed) (.Staging.Changed) }} |{{ end }}{{ if .Staging.Changed }} <#ffffff>\uf046</> {{ .Staging.String }}{{ end }}{{ if gt .StashCount 0 }} <#ffffff>\ueb4b</> {{ .StashCount }}{{ end }}]", | |
| "type": "git" | |
| } | |
| ], | |
| "type": "prompt" | |
| }, | |
| { | |
| "alignment": "left", | |
| "newline": true, | |
| "leading_diamond": "<#7eb8da>\u2514\u2500</>", | |
| "segments": [ | |
| { | |
| "style": "diamond", | |
| "template": "<#ffff00>[#]</>", | |
| "type": "root" | |
| }, | |
| { | |
| "foreground": "#ffa5d8", | |
| "style": "diamond", | |
| "template": "[<#ffffff>\uea6c</> Error]", | |
| "type": "status" | |
| }, | |
| { | |
| "style": "diamond", | |
| "template": ">", | |
| "type": "text" | |
| } | |
| ], | |
| "type": "prompt" | |
| } | |
| ], | |
| "final_space": true, | |
| "secondary_prompt": { | |
| "background": "transparent", | |
| "template": " " | |
| }, | |
| "valid_line": { | |
| "background": "transparent", | |
| "template": "> " | |
| }, | |
| "error_line": { | |
| "background": "transparent", | |
| "template": "<#ff0000>\uea87</> " | |
| }, | |
| "version": 3 | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # Import-Module 'C:\tools\vcpkg\scripts\posh-vcpkg' | |
| # Import-Module 'C:\ProgramData\chocolatey\lib\bottom\tools\completion\_btm.ps1' | |
| Import-Module "$env:USERPROFILE\anaconda3\shell\condabin\conda-hook.ps1" # conda activate # Import-Module 'C:\ProgramData\Anaconda3\shell\condabin\conda-hook.ps1' | |
| function y { # https://yazi-rs.github.io/docs/quick-start#shell-wrapper | |
| $tmp = (New-TemporaryFile).FullName | |
| yazi $args --cwd-file="$tmp" | |
| $cwd = Get-Content -Path $tmp -Encoding UTF8 | |
| if (-not [String]::IsNullOrEmpty($cwd) -and $cwd -ne $PWD.Path) { | |
| Set-Location -LiteralPath (Resolve-Path -LiteralPath $cwd).Path | |
| } | |
| Remove-Item -Path $tmp | |
| } | |
| Import-Module "$env:USERPROFILE\Documents\PowerShell\Moonbit.PwshShellCompletion.ps1" | |
| Import-Module "$env:USERPROFILE\Documents\PowerShell\Rustup.PwshCompletions.ps1" | |
| # oh-my-posh init pwsh --config "$env:POSH_THEMES_PATH/gravifer-tokyo.omp.json" | Invoke-Expression | |
| oh-my-posh init pwsh --config "$env:USERPROFILE/.config/oh-my-posh/gravifer-tokyo.omp.json" | Invoke-Expression | |
| . "$env:USERPROFILE/.config/oh-my-posh/gravifer-tokyo.context.ps1" | |
| Invoke-Expression (& { (zoxide init powershell | Out-String) }) | |
| Invoke-Expression (&scoop-search --hook) | |
| function git-bash { | |
| & "C:\\Program Files\\Git\\bin\\bash.exe" | |
| } | |
| (& opam env) -split '\r?\n' | ForEach-Object { Invoke-Expression $_ } | |
| Invoke-Expression (& { (jj util completion power-shell | Out-String) }) | |
| $OutputEncoding = [Console]::OutputEncoding = [Text.Encoding]::UTF8 | |
| . '~\AppData\Roaming\dystroy\broot\config\launcher\powershell\br.ps1' |
Author
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Just a provisional working theme. Screenshots, behavior notes, installation context, and the upstream improvements it motivated are documented in the Oh My Posh Themes Discussion.