mirror of
https://github.com/JanDeDobbeleer/oh-my-posh.git
synced 2025-02-02 05:41:10 -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"
|
||||
// Hides the root location if it doesn't fit in max_depth. Used in Agnoster Short
|
||||
HideRootLocation properties.Property = "hide_root_location"
|
||||
// A foreground color cycle
|
||||
Cycle properties.Property = "cycle"
|
||||
)
|
||||
|
||||
func (pt *Path) Template() string {
|
||||
|
@ -233,41 +235,39 @@ func (pt *Path) pathDepth(pwd string) int {
|
|||
}
|
||||
|
||||
func (pt *Path) getAgnosterPath() string {
|
||||
var buffer strings.Builder
|
||||
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...)
|
||||
splitted := strings.Split(pt.relative, pt.env.PathSeparator())
|
||||
if pt.root == pt.env.PathSeparator() {
|
||||
pt.root = splitted[0]
|
||||
splitted = splitted[1:]
|
||||
}
|
||||
n := len(elements)
|
||||
buffer.WriteString(elements[0])
|
||||
for i := 2; i < n; i++ {
|
||||
buffer.WriteString(fmt.Sprintf("%s%s", separator, folderIcon))
|
||||
|
||||
var elements []string
|
||||
n := len(splitted)
|
||||
for i := 1; i < n; i++ {
|
||||
elements = append(elements, folderIcon)
|
||||
}
|
||||
if n > 1 {
|
||||
buffer.WriteString(fmt.Sprintf("%s%s", separator, elements[n-1]))
|
||||
}
|
||||
return buffer.String()
|
||||
elements = append(elements, splitted[n-1])
|
||||
|
||||
return pt.colorizePath(pt.root, elements)
|
||||
}
|
||||
|
||||
func (pt *Path) getAgnosterLeftPath() string {
|
||||
var buffer strings.Builder
|
||||
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...)
|
||||
splitted := strings.Split(pt.relative, pt.env.PathSeparator())
|
||||
if pt.root == pt.env.PathSeparator() {
|
||||
pt.root = splitted[0]
|
||||
splitted = splitted[1:]
|
||||
}
|
||||
n := len(elements)
|
||||
buffer.WriteString(elements[0])
|
||||
if n > 1 {
|
||||
buffer.WriteString(fmt.Sprintf("%s%s", separator, elements[1]))
|
||||
|
||||
var elements []string
|
||||
n := len(splitted)
|
||||
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 buffer.String()
|
||||
|
||||
return pt.colorizePath(pt.root, elements)
|
||||
}
|
||||
|
||||
func (pt *Path) getRelevantLetter(folder string) string {
|
||||
|
@ -284,43 +284,47 @@ func (pt *Path) getRelevantLetter(folder string) string {
|
|||
}
|
||||
|
||||
func (pt *Path) getLetterPath() string {
|
||||
var buffer strings.Builder
|
||||
separator := pt.getFolderSeparator()
|
||||
elements := strings.Split(pt.relative, pt.env.PathSeparator())
|
||||
if pt.root != pt.env.PathSeparator() {
|
||||
elements = append([]string{pt.root}, elements...)
|
||||
splitted := strings.Split(pt.relative, pt.env.PathSeparator())
|
||||
if pt.root == pt.env.PathSeparator() {
|
||||
pt.root = splitted[0]
|
||||
splitted = splitted[1:]
|
||||
}
|
||||
n := len(elements)
|
||||
pt.root = pt.getRelevantLetter(pt.root)
|
||||
|
||||
var elements []string
|
||||
n := len(splitted)
|
||||
for i := 0; i < n-1; i++ {
|
||||
letter := pt.getRelevantLetter(elements[i])
|
||||
if i != 0 {
|
||||
buffer.WriteString(separator)
|
||||
}
|
||||
buffer.WriteString(letter)
|
||||
letter := pt.getRelevantLetter(splitted[i])
|
||||
elements = append(elements, letter)
|
||||
}
|
||||
buffer.WriteString(fmt.Sprintf("%s%s", separator, elements[n-1]))
|
||||
return buffer.String()
|
||||
elements = append(elements, splitted[n-1])
|
||||
|
||||
return pt.colorizePath(pt.root, elements)
|
||||
}
|
||||
|
||||
func (pt *Path) getUniqueLettersPath(maxWidth int) string {
|
||||
var buffer strings.Builder
|
||||
separator := pt.getFolderSeparator()
|
||||
elements := strings.Split(pt.relative, pt.env.PathSeparator())
|
||||
if pt.root != pt.env.PathSeparator() {
|
||||
elements = append([]string{pt.root}, elements...)
|
||||
splitted := strings.Split(pt.relative, pt.env.PathSeparator())
|
||||
if pt.root == pt.env.PathSeparator() {
|
||||
pt.root = splitted[0]
|
||||
splitted = splitted[1:]
|
||||
}
|
||||
|
||||
if maxWidth > 0 {
|
||||
path := strings.Join(elements, separator)
|
||||
path := strings.Join(splitted, separator)
|
||||
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[pt.root] = true
|
||||
for i := 0; i < n-1; i++ {
|
||||
folder := elements[i]
|
||||
folder := splitted[i]
|
||||
letter := pt.getRelevantLetter(folder)
|
||||
for letters[letter] {
|
||||
if letter == folder {
|
||||
|
@ -329,32 +333,33 @@ func (pt *Path) getUniqueLettersPath(maxWidth int) string {
|
|||
letter += folder[len(letter) : len(letter)+1]
|
||||
}
|
||||
letters[letter] = true
|
||||
if i != 0 {
|
||||
buffer.WriteString(separator)
|
||||
}
|
||||
buffer.WriteString(letter)
|
||||
elements = append(elements, letter)
|
||||
// only return early on maxWidth > 0
|
||||
// this enables the powerlevel10k behavior
|
||||
if maxWidth > 0 {
|
||||
trailing := strings.Join(elements[i+1:], separator)
|
||||
leftover := maxWidth - buffer.Len() - len(trailing) - len(separator)
|
||||
list := splitted[i+1:]
|
||||
list = append(list, elements...)
|
||||
current := strings.Join(list, separator)
|
||||
leftover := maxWidth - len(current) - len(pt.root) - len(separator)
|
||||
if leftover >= 0 {
|
||||
buffer.WriteString(fmt.Sprintf("%s%s", separator, trailing))
|
||||
return buffer.String()
|
||||
elements = append(elements, strings.Join(splitted[i+1:], separator))
|
||||
return pt.colorizePath(pt.root, elements)
|
||||
}
|
||||
}
|
||||
}
|
||||
buffer.WriteString(fmt.Sprintf("%s%s", separator, elements[n-1]))
|
||||
return buffer.String()
|
||||
elements = append(elements, splitted[n-1])
|
||||
|
||||
return pt.colorizePath(pt.root, elements)
|
||||
}
|
||||
|
||||
func (pt *Path) getAgnosterFullPath() string {
|
||||
path := strings.Trim(pt.relative, pt.env.PathSeparator())
|
||||
path = pt.replaceFolderSeparators(path)
|
||||
splitted := strings.Split(pt.relative, 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 {
|
||||
|
@ -372,11 +377,11 @@ func (pt *Path) getAgnosterShortPath() string {
|
|||
return pt.getAgnosterFullPath()
|
||||
}
|
||||
pathSeparator := pt.env.PathSeparator()
|
||||
folderSeparator := pt.getFolderSeparator()
|
||||
rel := strings.TrimPrefix(pt.relative, pathSeparator)
|
||||
splitted := strings.Split(rel, pathSeparator)
|
||||
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
|
||||
root := pt.root
|
||||
room := pathDepth - maxDepth
|
||||
|
@ -384,29 +389,24 @@ func (pt *Path) getAgnosterShortPath() string {
|
|||
root = splitted[0]
|
||||
room--
|
||||
}
|
||||
|
||||
if hideRootLocation || room > 0 {
|
||||
elements = append(elements, folderIcon)
|
||||
}
|
||||
|
||||
if hideRootLocation {
|
||||
buffer.WriteString(folderIcon)
|
||||
} else {
|
||||
buffer.WriteString(root)
|
||||
if room > 0 {
|
||||
buffer.WriteString(folderSeparator)
|
||||
buffer.WriteString(folderIcon)
|
||||
}
|
||||
root = ""
|
||||
}
|
||||
|
||||
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 {
|
||||
rel := pt.relative
|
||||
pathSeparator := pt.env.PathSeparator()
|
||||
if len(pt.root) != 0 && pt.root != pathSeparator && !strings.HasSuffix(pt.root, pathSeparator) {
|
||||
rel = pathSeparator + rel
|
||||
}
|
||||
path := pt.replaceFolderSeparators(rel)
|
||||
return pt.root + path
|
||||
elements := strings.Split(pt.relative, pt.env.PathSeparator())
|
||||
return pt.colorizePath(pt.root, elements)
|
||||
}
|
||||
|
||||
func (pt *Path) getFolderPath() string {
|
||||
|
@ -573,3 +573,31 @@ func (pt *Path) replaceFolderSeparators(pwd string) string {
|
|||
pwd = strings.ReplaceAll(pwd, defaultSeparator, folderSeparator)
|
||||
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
|
||||
GOOS string
|
||||
PathSeparator string
|
||||
Cycle []string
|
||||
}{
|
||||
{
|
||||
Case: "Windows registry drive case sensitive",
|
||||
|
@ -1073,9 +1074,17 @@ func TestAgnosterPath(t *testing.T) {
|
|||
PWD: "/mnt/folder/location",
|
||||
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.On("Home").Return(tc.Home)
|
||||
env.On("PathSeparator").Return(tc.PathSeparator)
|
||||
|
@ -1093,6 +1102,7 @@ func TestAgnosterPath(t *testing.T) {
|
|||
FolderSeparatorIcon: " > ",
|
||||
FolderIcon: "f",
|
||||
HomeIcon: "~",
|
||||
Cycle: tc.Cycle,
|
||||
},
|
||||
}
|
||||
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.On("Home").Return(tc.Home)
|
||||
env.On("PathSeparator").Return(tc.PathSeparator)
|
||||
|
|
|
@ -10,36 +10,39 @@ Display the current path.
|
|||
|
||||
## Sample Configuration
|
||||
|
||||
import Config from '@site/src/components/Config.js';
|
||||
import Config from "@site/src/components/Config.js";
|
||||
|
||||
<Config data={{
|
||||
"type": "path",
|
||||
"style": "powerline",
|
||||
"powerline_symbol": "\uE0B0",
|
||||
"foreground": "#ffffff",
|
||||
"background": "#61AFEF",
|
||||
"properties": {
|
||||
"style": "folder",
|
||||
"mapped_locations": {
|
||||
"C:\\temp": "\ue799"
|
||||
}
|
||||
}
|
||||
}}/>
|
||||
<Config
|
||||
data={{
|
||||
type: "path",
|
||||
style: "powerline",
|
||||
powerline_symbol: "\uE0B0",
|
||||
foreground: "#ffffff",
|
||||
background: "#61AFEF",
|
||||
properties: {
|
||||
style: "folder",
|
||||
mapped_locations: {
|
||||
"C:\\temp": "\ue799",
|
||||
},
|
||||
},
|
||||
}}
|
||||
/>
|
||||
|
||||
## Properties
|
||||
|
||||
| Name | Type | Description |
|
||||
| --------------------------- | --------- | ---------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `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 `` |
|
||||
| `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 `..` |
|
||||
| `windows_registry_icon` | `string` | the icon to display when in the Windows registry - defaults to `\uE0B1` |
|
||||
| `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` |
|
||||
| `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` |
|
||||
| `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` |
|
||||
| Name | Type | Description |
|
||||
| --------------------------- | ---------- | ---------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `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 `` |
|
||||
| `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 `..` |
|
||||
| `windows_registry_icon` | `string` | the icon to display when in the Windows registry - defaults to `\uE0B1` |
|
||||
| `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` |
|
||||
| `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` |
|
||||
| `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
|
||||
|
||||
|
|
Loading…
Reference in a new issue