mirror of
https://github.com/JanDeDobbeleer/oh-my-posh.git
synced 2024-11-12 14:04:05 -08:00
parent
e422e87384
commit
bb246377ce
|
@ -61,10 +61,12 @@ An alternative is to use the [Posh-Git segment][poshgit]
|
||||||
- display_status: `boolean` - display the local changes or not - defaults to `false`
|
- display_status: `boolean` - display the local changes or not - defaults to `false`
|
||||||
- display_status_detail: `boolean` - display the local changes in detail or not - defaults to `true`
|
- display_status_detail: `boolean` - display the local changes in detail or not - defaults to `true`
|
||||||
- display_stash_count: `boolean` show stash count or not - defaults to `false`
|
- display_stash_count: `boolean` show stash count or not - defaults to `false`
|
||||||
|
- display_worktree_count: `boolean` show worktree count or not - defaults to `false`
|
||||||
- status_separator_icon: `string` icon/text to display between staging and working area changes - defaults to ` |`
|
- status_separator_icon: `string` icon/text to display between staging and working area changes - defaults to ` |`
|
||||||
- local_working_icon: `string` - the icon to display in front of the working area changes - defaults to `\uF044`
|
- local_working_icon: `string` - the icon to display in front of the working area changes - defaults to `\uF044`
|
||||||
- local_staged_icon: `string` - the icon to display in front of the staged area changes - defaults to `\uF046`
|
- local_staged_icon: `string` - the icon to display in front of the staged area changes - defaults to `\uF046`
|
||||||
- stash_count_icon: `string` icon/text to display before the stash context - defaults to `\uF692`
|
- stash_count_icon: `string` icon/text to display before the stash context - defaults to `\uF692`
|
||||||
|
- worktree_count_icon: `string` icon/text to display before the worktree context - defaults to `\uF1BB`
|
||||||
|
|
||||||
### HEAD context
|
### HEAD context
|
||||||
|
|
||||||
|
|
|
@ -57,6 +57,7 @@ type environmentInfo interface {
|
||||||
hasFilesInDir(dir, pattern string) bool
|
hasFilesInDir(dir, pattern string) bool
|
||||||
hasFolder(folder string) bool
|
hasFolder(folder string) bool
|
||||||
getFileContent(file string) string
|
getFileContent(file string) string
|
||||||
|
getFoldersList(path string) []string
|
||||||
getPathSeperator() string
|
getPathSeperator() string
|
||||||
getCurrentUser() string
|
getCurrentUser() string
|
||||||
isRunningAsRoot() bool
|
isRunningAsRoot() bool
|
||||||
|
@ -219,6 +220,21 @@ func (env *environment) getFileContent(file string) string {
|
||||||
return string(content)
|
return string(content)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (env *environment) getFoldersList(path string) []string {
|
||||||
|
defer env.tracer.trace(time.Now(), "getFoldersList", path)
|
||||||
|
content, err := os.ReadDir(path)
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
var folderNames []string
|
||||||
|
for _, s := range content {
|
||||||
|
if s.IsDir() {
|
||||||
|
folderNames = append(folderNames, s.Name())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return folderNames
|
||||||
|
}
|
||||||
|
|
||||||
func (env *environment) getPathSeperator() string {
|
func (env *environment) getPathSeperator() string {
|
||||||
defer env.tracer.trace(time.Now(), "getPathSeperator")
|
defer env.tracer.trace(time.Now(), "getPathSeperator")
|
||||||
return string(os.PathSeparator)
|
return string(os.PathSeparator)
|
||||||
|
|
|
@ -20,6 +20,7 @@ type gitRepo struct {
|
||||||
gitWorkingFolder string // .git working folder, can be different of root if using worktree
|
gitWorkingFolder string // .git working folder, can be different of root if using worktree
|
||||||
isWorkTree bool
|
isWorkTree bool
|
||||||
gitRootFolder string // .git root folder
|
gitRootFolder string // .git root folder
|
||||||
|
worktreeCount int
|
||||||
}
|
}
|
||||||
|
|
||||||
type gitStatus struct {
|
type gitStatus struct {
|
||||||
|
@ -120,6 +121,10 @@ const (
|
||||||
AheadColor Property = "ahead_color"
|
AheadColor Property = "ahead_color"
|
||||||
// BranchMaxLength truncates the length of the branch name
|
// BranchMaxLength truncates the length of the branch name
|
||||||
BranchMaxLength Property = "branch_max_length"
|
BranchMaxLength Property = "branch_max_length"
|
||||||
|
// DisplayWorktreeCount show worktree count or not
|
||||||
|
DisplayWorktreeCount Property = "display_worktree_count"
|
||||||
|
// WorktreeCountIcon shows before the worktree context
|
||||||
|
WorktreeCountIcon Property = "worktree_count_icon"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (g *git) enabled() bool {
|
func (g *git) enabled() bool {
|
||||||
|
@ -189,6 +194,9 @@ func (g *git) string() string {
|
||||||
if g.repo.stashCount != 0 {
|
if g.repo.stashCount != 0 {
|
||||||
fmt.Fprintf(buffer, " %s%d", g.props.getString(StashCountIcon, "\uF692 "), g.repo.stashCount)
|
fmt.Fprintf(buffer, " %s%d", g.props.getString(StashCountIcon, "\uF692 "), g.repo.stashCount)
|
||||||
}
|
}
|
||||||
|
if g.repo.worktreeCount != 0 {
|
||||||
|
fmt.Fprintf(buffer, " %s%d", g.props.getString(WorktreeCountIcon, "\uf1bb "), g.repo.worktreeCount)
|
||||||
|
}
|
||||||
return buffer.String()
|
return buffer.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -270,6 +278,9 @@ func (g *git) setGitStatus() {
|
||||||
if g.props.getBool(DisplayStashCount, false) {
|
if g.props.getBool(DisplayStashCount, false) {
|
||||||
g.repo.stashCount = g.getStashContext()
|
g.repo.stashCount = g.getStashContext()
|
||||||
}
|
}
|
||||||
|
if g.props.getBool(DisplayWorktreeCount, false) {
|
||||||
|
g.repo.worktreeCount = g.getWorktreeContext()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *git) SetStatusColor() {
|
func (g *git) SetStatusColor() {
|
||||||
|
@ -315,30 +326,30 @@ func (g *git) getGitHEADContext(ref string) string {
|
||||||
ref = fmt.Sprintf("%s%s", branchIcon, ref)
|
ref = fmt.Sprintf("%s%s", branchIcon, ref)
|
||||||
}
|
}
|
||||||
// rebase
|
// rebase
|
||||||
if g.hasGitFolder("rebase-merge") {
|
if g.env.hasFolder(g.repo.gitWorkingFolder + "/rebase-merge") {
|
||||||
head := g.getGitFileContents("rebase-merge/head-name")
|
head := g.getGitFileContents(g.repo.gitWorkingFolder, "rebase-merge/head-name")
|
||||||
origin := strings.Replace(head, "refs/heads/", "", 1)
|
origin := strings.Replace(head, "refs/heads/", "", 1)
|
||||||
origin = g.truncateBranch(origin)
|
origin = g.truncateBranch(origin)
|
||||||
onto := g.getGitRefFileSymbolicName("rebase-merge/onto")
|
onto := g.getGitRefFileSymbolicName("rebase-merge/onto")
|
||||||
onto = g.truncateBranch(onto)
|
onto = g.truncateBranch(onto)
|
||||||
step := g.getGitFileContents("rebase-merge/msgnum")
|
step := g.getGitFileContents(g.repo.gitWorkingFolder, "rebase-merge/msgnum")
|
||||||
total := g.getGitFileContents("rebase-merge/end")
|
total := g.getGitFileContents(g.repo.gitWorkingFolder, "rebase-merge/end")
|
||||||
icon := g.props.getString(RebaseIcon, "\uE728 ")
|
icon := g.props.getString(RebaseIcon, "\uE728 ")
|
||||||
return fmt.Sprintf("%s%s%s onto %s%s (%s/%s) at %s", icon, branchIcon, origin, branchIcon, onto, step, total, ref)
|
return fmt.Sprintf("%s%s%s onto %s%s (%s/%s) at %s", icon, branchIcon, origin, branchIcon, onto, step, total, ref)
|
||||||
}
|
}
|
||||||
if g.hasGitFolder("rebase-apply") {
|
if g.env.hasFolder(g.repo.gitWorkingFolder + "/rebase-apply") {
|
||||||
head := g.getGitFileContents("rebase-apply/head-name")
|
head := g.getGitFileContents(g.repo.gitWorkingFolder, "rebase-apply/head-name")
|
||||||
origin := strings.Replace(head, "refs/heads/", "", 1)
|
origin := strings.Replace(head, "refs/heads/", "", 1)
|
||||||
origin = g.truncateBranch(origin)
|
origin = g.truncateBranch(origin)
|
||||||
step := g.getGitFileContents("rebase-apply/next")
|
step := g.getGitFileContents(g.repo.gitWorkingFolder, "rebase-apply/next")
|
||||||
total := g.getGitFileContents("rebase-apply/last")
|
total := g.getGitFileContents(g.repo.gitWorkingFolder, "rebase-apply/last")
|
||||||
icon := g.props.getString(RebaseIcon, "\uE728 ")
|
icon := g.props.getString(RebaseIcon, "\uE728 ")
|
||||||
return fmt.Sprintf("%s%s%s (%s/%s) at %s", icon, branchIcon, origin, step, total, ref)
|
return fmt.Sprintf("%s%s%s (%s/%s) at %s", icon, branchIcon, origin, step, total, ref)
|
||||||
}
|
}
|
||||||
// merge
|
// merge
|
||||||
if g.hasGitFile("MERGE_MSG") && g.hasGitFile("MERGE_HEAD") {
|
if g.hasGitFile("MERGE_MSG") && g.hasGitFile("MERGE_HEAD") {
|
||||||
icon := g.props.getString(MergeIcon, "\uE727 ")
|
icon := g.props.getString(MergeIcon, "\uE727 ")
|
||||||
mergeContext := g.getGitFileContents("MERGE_MSG")
|
mergeContext := g.getGitFileContents(g.repo.gitWorkingFolder, "MERGE_MSG")
|
||||||
matches := findNamedRegexMatch(`Merge branch '(?P<head>.*)' into`, mergeContext)
|
matches := findNamedRegexMatch(`Merge branch '(?P<head>.*)' into`, mergeContext)
|
||||||
if matches != nil && matches["head"] != "" {
|
if matches != nil && matches["head"] != "" {
|
||||||
branch := g.truncateBranch(matches["head"])
|
branch := g.truncateBranch(matches["head"])
|
||||||
|
@ -351,15 +362,15 @@ func (g *git) getGitHEADContext(ref string) string {
|
||||||
// reverts then CHERRY_PICK_HEAD/REVERT_HEAD will not exist so we have to read
|
// reverts then CHERRY_PICK_HEAD/REVERT_HEAD will not exist so we have to read
|
||||||
// the todo file.
|
// the todo file.
|
||||||
if g.hasGitFile("CHERRY_PICK_HEAD") {
|
if g.hasGitFile("CHERRY_PICK_HEAD") {
|
||||||
sha := g.getGitFileContents("CHERRY_PICK_HEAD")
|
sha := g.getGitFileContents(g.repo.gitWorkingFolder, "CHERRY_PICK_HEAD")
|
||||||
icon := g.props.getString(CherryPickIcon, "\uE29B ")
|
icon := g.props.getString(CherryPickIcon, "\uE29B ")
|
||||||
return fmt.Sprintf("%s%s onto %s", icon, sha[0:6], ref)
|
return fmt.Sprintf("%s%s onto %s", icon, sha[0:6], ref)
|
||||||
} else if g.hasGitFile("REVERT_HEAD") {
|
} else if g.hasGitFile("REVERT_HEAD") {
|
||||||
sha := g.getGitFileContents("REVERT_HEAD")
|
sha := g.getGitFileContents(g.repo.gitWorkingFolder, "REVERT_HEAD")
|
||||||
icon := g.props.getString(RevertIcon, "\uF0E2 ")
|
icon := g.props.getString(RevertIcon, "\uF0E2 ")
|
||||||
return fmt.Sprintf("%s%s onto %s", icon, sha[0:6], ref)
|
return fmt.Sprintf("%s%s onto %s", icon, sha[0:6], ref)
|
||||||
} else if g.hasGitFile("sequencer/todo") {
|
} else if g.hasGitFile("sequencer/todo") {
|
||||||
todo := g.getGitFileContents("sequencer/todo")
|
todo := g.getGitFileContents(g.repo.gitWorkingFolder, "sequencer/todo")
|
||||||
matches := findNamedRegexMatch(`^(?P<action>p|pick|revert)\s+(?P<sha>\S+)`, todo)
|
matches := findNamedRegexMatch(`^(?P<action>p|pick|revert)\s+(?P<sha>\S+)`, todo)
|
||||||
if matches != nil && matches["sha"] != "" {
|
if matches != nil && matches["sha"] != "" {
|
||||||
action := matches["action"]
|
action := matches["action"]
|
||||||
|
@ -389,25 +400,18 @@ func (g *git) hasGitFile(file string) bool {
|
||||||
return g.env.hasFilesInDir(g.repo.gitWorkingFolder, file)
|
return g.env.hasFilesInDir(g.repo.gitWorkingFolder, file)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *git) hasGitFolder(folder string) bool {
|
func (g *git) getGitFileContents(folder, file string) string {
|
||||||
path := g.repo.gitWorkingFolder + "/" + folder
|
return strings.Trim(g.env.getFileContent(folder+"/"+file), " \r\n")
|
||||||
return g.env.hasFolder(path)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (g *git) getGitFileContents(file string) string {
|
|
||||||
path := g.repo.gitWorkingFolder + "/" + file
|
|
||||||
content := g.env.getFileContent(path)
|
|
||||||
return strings.Trim(content, " \r\n")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *git) getGitRefFileSymbolicName(refFile string) string {
|
func (g *git) getGitRefFileSymbolicName(refFile string) string {
|
||||||
ref := g.getGitFileContents(refFile)
|
ref := g.getGitFileContents(g.repo.gitWorkingFolder, refFile)
|
||||||
return g.getGitCommandOutput("name-rev", "--name-only", "--exclude=tags/*", ref)
|
return g.getGitCommandOutput("name-rev", "--name-only", "--exclude=tags/*", ref)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *git) getPrettyHEADName() string {
|
func (g *git) getPrettyHEADName() string {
|
||||||
var ref string
|
var ref string
|
||||||
HEAD := g.getGitFileContents("HEAD")
|
HEAD := g.getGitFileContents(g.repo.gitWorkingFolder, "HEAD")
|
||||||
branchPrefix := "ref: refs/heads/"
|
branchPrefix := "ref: refs/heads/"
|
||||||
if strings.HasPrefix(HEAD, branchPrefix) {
|
if strings.HasPrefix(HEAD, branchPrefix) {
|
||||||
ref = strings.TrimPrefix(HEAD, branchPrefix)
|
ref = strings.TrimPrefix(HEAD, branchPrefix)
|
||||||
|
@ -462,7 +466,7 @@ func (g *git) parseGitStats(output []string, working bool) *gitStatus {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *git) getStashContext() int {
|
func (g *git) getStashContext() int {
|
||||||
stashContent := g.getGitFileContents("logs/refs/stash")
|
stashContent := g.getGitFileContents(g.repo.gitRootFolder, "logs/refs/stash")
|
||||||
if stashContent == "" {
|
if stashContent == "" {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
@ -470,6 +474,14 @@ func (g *git) getStashContext() int {
|
||||||
return len(lines)
|
return len(lines)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (g *git) getWorktreeContext() int {
|
||||||
|
if !g.env.hasFolder(g.repo.gitRootFolder + "/worktrees") {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
worktreeFolders := g.env.getFoldersList(g.repo.gitRootFolder + "/worktrees")
|
||||||
|
return len(worktreeFolders)
|
||||||
|
}
|
||||||
|
|
||||||
func (g *git) parseGitStatusInfo(branchInfo string) map[string]string {
|
func (g *git) parseGitStatusInfo(branchInfo string) map[string]string {
|
||||||
var branchRegex = `^## (?P<local>\S+?)(\.{3}(?P<upstream>\S+?)( \[(?P<upstream_status>(ahead (?P<ahead>\d+)(, )?)?(behind (?P<behind>\d+))?(gone)?)])?)?$`
|
var branchRegex = `^## (?P<local>\S+?)(\.{3}(?P<upstream>\S+?)( \[(?P<upstream_status>(ahead (?P<ahead>\d+)(, )?)?(behind (?P<behind>\d+))?(gone)?)])?)?$`
|
||||||
return findNamedRegexMatch(branchRegex, branchInfo)
|
return findNamedRegexMatch(branchRegex, branchInfo)
|
||||||
|
|
|
@ -45,7 +45,7 @@ const (
|
||||||
MappedLocationsEnabled Property = "mapped_locations_enabled"
|
MappedLocationsEnabled Property = "mapped_locations_enabled"
|
||||||
// StackCountEnabled enables the stack count display
|
// StackCountEnabled enables the stack count display
|
||||||
StackCountEnabled Property = "stack_count_enabled"
|
StackCountEnabled Property = "stack_count_enabled"
|
||||||
// Maximum path depth to display whithout shortening
|
// MaxDepth Maximum path depth to display whithout shortening
|
||||||
MaxDepth Property = "max_depth"
|
MaxDepth Property = "max_depth"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -49,6 +49,11 @@ func (env *MockedEnvironment) getFileContent(file string) string {
|
||||||
return args.String(0)
|
return args.String(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (env *MockedEnvironment) getFoldersList(path string) []string {
|
||||||
|
args := env.Called(path)
|
||||||
|
return args.Get(0).([]string)
|
||||||
|
}
|
||||||
|
|
||||||
func (env *MockedEnvironment) getPathSeperator() string {
|
func (env *MockedEnvironment) getPathSeperator() string {
|
||||||
args := env.Called(nil)
|
args := env.Called(nil)
|
||||||
return args.String(0)
|
return args.String(0)
|
||||||
|
|
|
@ -570,6 +570,12 @@
|
||||||
"description": "Display the stash count or not",
|
"description": "Display the stash count or not",
|
||||||
"default": false
|
"default": false
|
||||||
},
|
},
|
||||||
|
"display_worktree_count": {
|
||||||
|
"type": "boolean",
|
||||||
|
"title": "Display Worktree Count",
|
||||||
|
"description": "Display the worktree count or not",
|
||||||
|
"default": false
|
||||||
|
},
|
||||||
"status_separator_icon": {
|
"status_separator_icon": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"title": "Status Separator Icon",
|
"title": "Status Separator Icon",
|
||||||
|
@ -592,7 +598,13 @@
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"title": "Stash Count Icon",
|
"title": "Stash Count Icon",
|
||||||
"description": "The icon to display before the stash context",
|
"description": "The icon to display before the stash context",
|
||||||
"default": "\uF692"
|
"default": "\uF692 "
|
||||||
|
},
|
||||||
|
"worktree_count_icon": {
|
||||||
|
"type": "string",
|
||||||
|
"title": "Worktree Count Icon",
|
||||||
|
"description": "The icon to display before the worktree context",
|
||||||
|
"default": "\uF1bb "
|
||||||
},
|
},
|
||||||
"commit_icon": {
|
"commit_icon": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
|
|
Loading…
Reference in a new issue