mirror of
https://github.com/JanDeDobbeleer/oh-my-posh.git
synced 2025-03-05 20:49:04 -08:00
feat(path): add colored full path
This commit is contained in:
parent
4e9e753e13
commit
facc24d290
|
@ -73,6 +73,8 @@ const (
|
||||||
MaxWidth properties.Property = "max_width"
|
MaxWidth properties.Property = "max_width"
|
||||||
// Hides the root location if it doesn't fit in max_depth. Used in Agnoster Short
|
// Hides the root location if it doesn't fit in max_depth. Used in Agnoster Short
|
||||||
HideRootLocation properties.Property = "hide_root_location"
|
HideRootLocation properties.Property = "hide_root_location"
|
||||||
|
// A foreground color cycle
|
||||||
|
Cycle properties.Property = "cycle"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (pt *Path) Template() string {
|
func (pt *Path) Template() string {
|
||||||
|
@ -233,41 +235,39 @@ func (pt *Path) pathDepth(pwd string) int {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (pt *Path) getAgnosterPath() string {
|
func (pt *Path) getAgnosterPath() string {
|
||||||
var buffer strings.Builder
|
|
||||||
folderIcon := pt.props.GetString(FolderIcon, "..")
|
folderIcon := pt.props.GetString(FolderIcon, "..")
|
||||||
separator := pt.getFolderSeparator()
|
splitted := strings.Split(pt.relative, pt.env.PathSeparator())
|
||||||
elements := strings.Split(pt.relative, pt.env.PathSeparator())
|
if pt.root == pt.env.PathSeparator() {
|
||||||
if pt.root != pt.env.PathSeparator() {
|
pt.root = splitted[0]
|
||||||
elements = append([]string{pt.root}, elements...)
|
splitted = splitted[1:]
|
||||||
}
|
}
|
||||||
n := len(elements)
|
|
||||||
buffer.WriteString(elements[0])
|
var elements []string
|
||||||
for i := 2; i < n; i++ {
|
n := len(splitted)
|
||||||
buffer.WriteString(fmt.Sprintf("%s%s", separator, folderIcon))
|
for i := 1; i < n; i++ {
|
||||||
|
elements = append(elements, folderIcon)
|
||||||
}
|
}
|
||||||
if n > 1 {
|
elements = append(elements, splitted[n-1])
|
||||||
buffer.WriteString(fmt.Sprintf("%s%s", separator, elements[n-1]))
|
|
||||||
}
|
return pt.colorizePath(pt.root, elements)
|
||||||
return buffer.String()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (pt *Path) getAgnosterLeftPath() string {
|
func (pt *Path) getAgnosterLeftPath() string {
|
||||||
var buffer strings.Builder
|
|
||||||
folderIcon := pt.props.GetString(FolderIcon, "..")
|
folderIcon := pt.props.GetString(FolderIcon, "..")
|
||||||
separator := pt.getFolderSeparator()
|
splitted := strings.Split(pt.relative, pt.env.PathSeparator())
|
||||||
elements := strings.Split(pt.relative, pt.env.PathSeparator())
|
if pt.root == pt.env.PathSeparator() {
|
||||||
if pt.root != pt.env.PathSeparator() {
|
pt.root = splitted[0]
|
||||||
elements = append([]string{pt.root}, elements...)
|
splitted = splitted[1:]
|
||||||
}
|
}
|
||||||
n := len(elements)
|
|
||||||
buffer.WriteString(elements[0])
|
var elements []string
|
||||||
if n > 1 {
|
n := len(splitted)
|
||||||
buffer.WriteString(fmt.Sprintf("%s%s", separator, elements[1]))
|
elements = append(elements, splitted[0])
|
||||||
|
for i := 1; i < n; i++ {
|
||||||
|
elements = append(elements, folderIcon)
|
||||||
}
|
}
|
||||||
for i := 2; i < n; i++ {
|
|
||||||
buffer.WriteString(fmt.Sprintf("%s%s", separator, folderIcon))
|
return pt.colorizePath(pt.root, elements)
|
||||||
}
|
|
||||||
return buffer.String()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (pt *Path) getRelevantLetter(folder string) string {
|
func (pt *Path) getRelevantLetter(folder string) string {
|
||||||
|
@ -284,43 +284,47 @@ func (pt *Path) getRelevantLetter(folder string) string {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (pt *Path) getLetterPath() string {
|
func (pt *Path) getLetterPath() string {
|
||||||
var buffer strings.Builder
|
splitted := strings.Split(pt.relative, pt.env.PathSeparator())
|
||||||
separator := pt.getFolderSeparator()
|
if pt.root == pt.env.PathSeparator() {
|
||||||
elements := strings.Split(pt.relative, pt.env.PathSeparator())
|
pt.root = splitted[0]
|
||||||
if pt.root != pt.env.PathSeparator() {
|
splitted = splitted[1:]
|
||||||
elements = append([]string{pt.root}, elements...)
|
|
||||||
}
|
}
|
||||||
n := len(elements)
|
pt.root = pt.getRelevantLetter(pt.root)
|
||||||
|
|
||||||
|
var elements []string
|
||||||
|
n := len(splitted)
|
||||||
for i := 0; i < n-1; i++ {
|
for i := 0; i < n-1; i++ {
|
||||||
letter := pt.getRelevantLetter(elements[i])
|
letter := pt.getRelevantLetter(splitted[i])
|
||||||
if i != 0 {
|
elements = append(elements, letter)
|
||||||
buffer.WriteString(separator)
|
|
||||||
}
|
|
||||||
buffer.WriteString(letter)
|
|
||||||
}
|
}
|
||||||
buffer.WriteString(fmt.Sprintf("%s%s", separator, elements[n-1]))
|
elements = append(elements, splitted[n-1])
|
||||||
return buffer.String()
|
|
||||||
|
return pt.colorizePath(pt.root, elements)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (pt *Path) getUniqueLettersPath(maxWidth int) string {
|
func (pt *Path) getUniqueLettersPath(maxWidth int) string {
|
||||||
var buffer strings.Builder
|
|
||||||
separator := pt.getFolderSeparator()
|
separator := pt.getFolderSeparator()
|
||||||
elements := strings.Split(pt.relative, pt.env.PathSeparator())
|
splitted := strings.Split(pt.relative, pt.env.PathSeparator())
|
||||||
if pt.root != pt.env.PathSeparator() {
|
if pt.root == pt.env.PathSeparator() {
|
||||||
elements = append([]string{pt.root}, elements...)
|
pt.root = splitted[0]
|
||||||
|
splitted = splitted[1:]
|
||||||
}
|
}
|
||||||
|
|
||||||
if maxWidth > 0 {
|
if maxWidth > 0 {
|
||||||
path := strings.Join(elements, separator)
|
path := strings.Join(splitted, separator)
|
||||||
if len(path) <= maxWidth {
|
if len(path) <= maxWidth {
|
||||||
return path
|
return pt.colorizePath(pt.root, splitted)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
n := len(elements)
|
pt.root = pt.getRelevantLetter(pt.root)
|
||||||
|
|
||||||
|
var elements []string
|
||||||
|
n := len(splitted)
|
||||||
letters := make(map[string]bool)
|
letters := make(map[string]bool)
|
||||||
|
letters[pt.root] = true
|
||||||
for i := 0; i < n-1; i++ {
|
for i := 0; i < n-1; i++ {
|
||||||
folder := elements[i]
|
folder := splitted[i]
|
||||||
letter := pt.getRelevantLetter(folder)
|
letter := pt.getRelevantLetter(folder)
|
||||||
for letters[letter] {
|
for letters[letter] {
|
||||||
if letter == folder {
|
if letter == folder {
|
||||||
|
@ -329,32 +333,33 @@ func (pt *Path) getUniqueLettersPath(maxWidth int) string {
|
||||||
letter += folder[len(letter) : len(letter)+1]
|
letter += folder[len(letter) : len(letter)+1]
|
||||||
}
|
}
|
||||||
letters[letter] = true
|
letters[letter] = true
|
||||||
if i != 0 {
|
elements = append(elements, letter)
|
||||||
buffer.WriteString(separator)
|
|
||||||
}
|
|
||||||
buffer.WriteString(letter)
|
|
||||||
// only return early on maxWidth > 0
|
// only return early on maxWidth > 0
|
||||||
// this enables the powerlevel10k behavior
|
// this enables the powerlevel10k behavior
|
||||||
if maxWidth > 0 {
|
if maxWidth > 0 {
|
||||||
trailing := strings.Join(elements[i+1:], separator)
|
list := splitted[i+1:]
|
||||||
leftover := maxWidth - buffer.Len() - len(trailing) - len(separator)
|
list = append(list, elements...)
|
||||||
|
current := strings.Join(list, separator)
|
||||||
|
leftover := maxWidth - len(current) - len(pt.root) - len(separator)
|
||||||
if leftover >= 0 {
|
if leftover >= 0 {
|
||||||
buffer.WriteString(fmt.Sprintf("%s%s", separator, trailing))
|
elements = append(elements, strings.Join(splitted[i+1:], separator))
|
||||||
return buffer.String()
|
return pt.colorizePath(pt.root, elements)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
buffer.WriteString(fmt.Sprintf("%s%s", separator, elements[n-1]))
|
elements = append(elements, splitted[n-1])
|
||||||
return buffer.String()
|
|
||||||
|
return pt.colorizePath(pt.root, elements)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (pt *Path) getAgnosterFullPath() string {
|
func (pt *Path) getAgnosterFullPath() string {
|
||||||
path := strings.Trim(pt.relative, pt.env.PathSeparator())
|
splitted := strings.Split(pt.relative, pt.env.PathSeparator())
|
||||||
path = pt.replaceFolderSeparators(path)
|
|
||||||
if pt.root == pt.env.PathSeparator() {
|
if pt.root == pt.env.PathSeparator() {
|
||||||
return path
|
pt.root = splitted[0]
|
||||||
|
splitted = splitted[1:]
|
||||||
}
|
}
|
||||||
return pt.root + pt.getFolderSeparator() + path
|
|
||||||
|
return pt.colorizePath(pt.root, splitted)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (pt *Path) getAgnosterShortPath() string {
|
func (pt *Path) getAgnosterShortPath() string {
|
||||||
|
@ -372,11 +377,11 @@ func (pt *Path) getAgnosterShortPath() string {
|
||||||
return pt.getAgnosterFullPath()
|
return pt.getAgnosterFullPath()
|
||||||
}
|
}
|
||||||
pathSeparator := pt.env.PathSeparator()
|
pathSeparator := pt.env.PathSeparator()
|
||||||
folderSeparator := pt.getFolderSeparator()
|
|
||||||
rel := strings.TrimPrefix(pt.relative, pathSeparator)
|
rel := strings.TrimPrefix(pt.relative, pathSeparator)
|
||||||
splitted := strings.Split(rel, pathSeparator)
|
splitted := strings.Split(rel, pathSeparator)
|
||||||
splitPos := pathDepth - maxDepth
|
splitPos := pathDepth - maxDepth
|
||||||
var buffer strings.Builder
|
// var buffer strings.Builder
|
||||||
|
var elements []string
|
||||||
// unix root, needs to be replaced with the folder we're in at root level
|
// unix root, needs to be replaced with the folder we're in at root level
|
||||||
root := pt.root
|
root := pt.root
|
||||||
room := pathDepth - maxDepth
|
room := pathDepth - maxDepth
|
||||||
|
@ -384,29 +389,24 @@ func (pt *Path) getAgnosterShortPath() string {
|
||||||
root = splitted[0]
|
root = splitted[0]
|
||||||
room--
|
room--
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if hideRootLocation || room > 0 {
|
||||||
|
elements = append(elements, folderIcon)
|
||||||
|
}
|
||||||
|
|
||||||
if hideRootLocation {
|
if hideRootLocation {
|
||||||
buffer.WriteString(folderIcon)
|
root = ""
|
||||||
} else {
|
|
||||||
buffer.WriteString(root)
|
|
||||||
if room > 0 {
|
|
||||||
buffer.WriteString(folderSeparator)
|
|
||||||
buffer.WriteString(folderIcon)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for i := splitPos; i < pathDepth; i++ {
|
for i := splitPos; i < pathDepth; i++ {
|
||||||
buffer.WriteString(fmt.Sprintf("%s%s", folderSeparator, splitted[i]))
|
elements = append(elements, splitted[i])
|
||||||
}
|
}
|
||||||
return buffer.String()
|
return pt.colorizePath(root, elements)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (pt *Path) getFullPath() string {
|
func (pt *Path) getFullPath() string {
|
||||||
rel := pt.relative
|
elements := strings.Split(pt.relative, pt.env.PathSeparator())
|
||||||
pathSeparator := pt.env.PathSeparator()
|
return pt.colorizePath(pt.root, elements)
|
||||||
if len(pt.root) != 0 && pt.root != pathSeparator && !strings.HasSuffix(pt.root, pathSeparator) {
|
|
||||||
rel = pathSeparator + rel
|
|
||||||
}
|
|
||||||
path := pt.replaceFolderSeparators(rel)
|
|
||||||
return pt.root + path
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (pt *Path) getFolderPath() string {
|
func (pt *Path) getFolderPath() string {
|
||||||
|
@ -573,3 +573,31 @@ func (pt *Path) replaceFolderSeparators(pwd string) string {
|
||||||
pwd = strings.ReplaceAll(pwd, defaultSeparator, folderSeparator)
|
pwd = strings.ReplaceAll(pwd, defaultSeparator, folderSeparator)
|
||||||
return pwd
|
return pwd
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (pt *Path) colorizePath(root string, elements []string) string {
|
||||||
|
cycle := pt.props.GetStringArray(Cycle, []string{})
|
||||||
|
folderSeparator := pt.getFolderSeparator()
|
||||||
|
|
||||||
|
if len(cycle) != 0 {
|
||||||
|
colorize := "<%s>%s</>"
|
||||||
|
|
||||||
|
if len(root) != 0 {
|
||||||
|
root = fmt.Sprintf(colorize, cycle[0], root)
|
||||||
|
cycle = append(cycle[1:], cycle[0])
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, element := range elements {
|
||||||
|
if len(element) == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
colored := fmt.Sprintf(colorize, cycle[0], element)
|
||||||
|
elements[i] = colored
|
||||||
|
cycle = append(cycle[1:], cycle[0])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if root == pt.env.PathSeparator() || len(root) == 0 {
|
||||||
|
return root + strings.Join(elements, folderSeparator)
|
||||||
|
}
|
||||||
|
return root + folderSeparator + strings.Join(elements, folderSeparator)
|
||||||
|
}
|
||||||
|
|
|
@ -956,6 +956,7 @@ func TestAgnosterPath(t *testing.T) {
|
||||||
PWD string
|
PWD string
|
||||||
GOOS string
|
GOOS string
|
||||||
PathSeparator string
|
PathSeparator string
|
||||||
|
Cycle []string
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
Case: "Windows registry drive case sensitive",
|
Case: "Windows registry drive case sensitive",
|
||||||
|
@ -1073,9 +1074,17 @@ func TestAgnosterPath(t *testing.T) {
|
||||||
PWD: "/mnt/folder/location",
|
PWD: "/mnt/folder/location",
|
||||||
PathSeparator: "/",
|
PathSeparator: "/",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
Case: "Unix, colorize",
|
||||||
|
Expected: "<blue>mnt</> > <yellow>f</> > <blue>location</>",
|
||||||
|
Home: homeDir,
|
||||||
|
PWD: "/mnt/folder/location",
|
||||||
|
PathSeparator: "/",
|
||||||
|
Cycle: []string{"blue", "yellow"},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tc := range cases { //nolint:dupl
|
for _, tc := range cases {
|
||||||
env := new(mock.MockedEnvironment)
|
env := new(mock.MockedEnvironment)
|
||||||
env.On("Home").Return(tc.Home)
|
env.On("Home").Return(tc.Home)
|
||||||
env.On("PathSeparator").Return(tc.PathSeparator)
|
env.On("PathSeparator").Return(tc.PathSeparator)
|
||||||
|
@ -1093,6 +1102,7 @@ func TestAgnosterPath(t *testing.T) {
|
||||||
FolderSeparatorIcon: " > ",
|
FolderSeparatorIcon: " > ",
|
||||||
FolderIcon: "f",
|
FolderIcon: "f",
|
||||||
HomeIcon: "~",
|
HomeIcon: "~",
|
||||||
|
Cycle: tc.Cycle,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
path.setPaths()
|
path.setPaths()
|
||||||
|
@ -1229,7 +1239,7 @@ func TestAgnosterLeftPath(t *testing.T) {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tc := range cases { //nolint:dupl
|
for _, tc := range cases {
|
||||||
env := new(mock.MockedEnvironment)
|
env := new(mock.MockedEnvironment)
|
||||||
env.On("Home").Return(tc.Home)
|
env.On("Home").Return(tc.Home)
|
||||||
env.On("PathSeparator").Return(tc.PathSeparator)
|
env.On("PathSeparator").Return(tc.PathSeparator)
|
||||||
|
|
|
@ -10,36 +10,39 @@ Display the current path.
|
||||||
|
|
||||||
## Sample Configuration
|
## Sample Configuration
|
||||||
|
|
||||||
import Config from '@site/src/components/Config.js';
|
import Config from "@site/src/components/Config.js";
|
||||||
|
|
||||||
<Config data={{
|
<Config
|
||||||
"type": "path",
|
data={{
|
||||||
"style": "powerline",
|
type: "path",
|
||||||
"powerline_symbol": "\uE0B0",
|
style: "powerline",
|
||||||
"foreground": "#ffffff",
|
powerline_symbol: "\uE0B0",
|
||||||
"background": "#61AFEF",
|
foreground: "#ffffff",
|
||||||
"properties": {
|
background: "#61AFEF",
|
||||||
"style": "folder",
|
properties: {
|
||||||
"mapped_locations": {
|
style: "folder",
|
||||||
"C:\\temp": "\ue799"
|
mapped_locations: {
|
||||||
}
|
"C:\\temp": "\ue799",
|
||||||
}
|
},
|
||||||
}}/>
|
},
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
## Properties
|
## Properties
|
||||||
|
|
||||||
| Name | Type | Description |
|
| Name | Type | Description |
|
||||||
| --------------------------- | --------- | ---------------------------------------------------------------------------------------------------------------------------- |
|
| --------------------------- | ---------- | ---------------------------------------------------------------------------------------------------------------------------- |
|
||||||
| `folder_separator_icon` | `string` | the symbol to use as a separator between folders - defaults to platform path separator |
|
| `folder_separator_icon` | `string` | the symbol to use as a separator between folders - defaults to platform path separator |
|
||||||
| `folder_separator_template` | `string` | the [template][templates] to use as a separator between folders - defaults to `` |
|
| `folder_separator_template` | `string` | the [template][templates] to use as a separator between folders - defaults to `` |
|
||||||
| `home_icon` | `string` | the icon to display when at `$HOME`, defaults to `~` |
|
| `home_icon` | `string` | the icon to display when at `$HOME`, defaults to `~` |
|
||||||
| `folder_icon` | `string` | the icon to use as a folder indication - defaults to `..` |
|
| `folder_icon` | `string` | the icon to use as a folder indication - defaults to `..` |
|
||||||
| `windows_registry_icon` | `string` | the icon to display when in the Windows registry - defaults to `\uE0B1` |
|
| `windows_registry_icon` | `string` | the icon to display when in the Windows registry - defaults to `\uE0B1` |
|
||||||
| `style` | `enum` | how to display the current path |
|
| `style` | `enum` | how to display the current path |
|
||||||
| `mixed_threshold` | `number` | the maximum length of a path segment that will be displayed when using `Mixed` - defaults to `4` |
|
| `mixed_threshold` | `number` | the maximum length of a path segment that will be displayed when using `Mixed` - defaults to `4` |
|
||||||
| `max_depth` | `number` | maximum path depth to display before shortening when using `agnoster_short`, defaults to `1` |
|
| `max_depth` | `number` | maximum path depth to display before shortening when using `agnoster_short`, defaults to `1` |
|
||||||
| `max_width` | `number` | maximum path length to display when using `powerlevel`, defaults to `0` |
|
| `max_width` | `number` | maximum path length to display when using `powerlevel`, defaults to `0` |
|
||||||
| `hide_root_location` | `boolean` | hides the root location if it doesn't fit in the last `max_depth` folders, when using `agnoster_short` - defaults to `false` |
|
| `hide_root_location` | `boolean` | hides the root location if it doesn't fit in the last `max_depth` folders, when using `agnoster_short` - defaults to `false` |
|
||||||
|
| `cycle` | `[]string` | a list of foreground colors to cycle through to colorize the individual path folders |
|
||||||
|
|
||||||
## Mapped Locations
|
## Mapped Locations
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue