Description
Code of Conduct
- I agree to follow this project's Code of Conduct
What would you like to see changed?
I know this feature was implemented only very recently, but I still found something that could be improved. (Sorry!)
Existing Behavior
At the present moment, the path segment regex replaces the first capture group found with the corresponding value in the config, leaving the rest of the string completely untouched.
https://github.com/JanDeDobbeleer/oh-my-posh/blob/main/src/segments/path.go#L639
This (while consistent with mapped_locations
' preservation of subsequent portions of the path) presents an issue: what if you need something more than a mere 1 location substitution?
The Situation
My situation is similar to the one in my prior issues, with an enclosing github folder I want replaced with an icon:
"mapped_locations": {
"/mnt/c": "C:/",
"re:(.*/Users/taylo/Documents/GitHub).*": "github-icon"
}
This works fine in and of itself.
However, I place all my git worktrees for the current repo in a separate folder to keep track (repoName.worktrees/branch-name
), and would like to have oh-my-posh
additionally display "repoName" for these folders1.
In other words, I want something like this:
C:/Users/taylo/Documents/GitHub/repoName.worktrees/branch-name/XXX
to turn into this:
github-icon/repoName/XXX
Unfortunately, there appears to be no way to do these 2 things simultaneously while preserving the original path and successive sub-elements. Given the lack of variable expansion in regexp.FindStringSubmatch, neither of these work:
"re:(.*/Users/taylo/Documents/GitHub/(?P<repoName>.*).worktrees/.*)": "github-icon/$repoName"
"re:(.*/Users/taylo/Documents/GitHub/(.*).worktrees/.*)": "github-icon/$2"
While doing regexp.Expand
could solve this, the existing code for finding submatches would have to be changed to use indices (not to mention 3 or more replacements gets you into some some really ugly nested capture groups).
Proposals
After all that context, I have 3 main ideas for potential solutions to this (in no particular order):
- Allow regex mapped location to replace successive capture groups with the corresponding values.
- Pros:
- Simple for users and fairly consistent with existing implementation.
- Cons:
- Questionable how to represent it inside config and/or JSON schema without breaking existing configs or changing implementations. Having a special delimiter sequence (comma, colon, etc.) risks breaking mappings containing those sequences, and allowing an array of values for this specific purpose would raise issues with how to interpret it for normal mapped locations.
- Nested capture groups would seem to pose an interesting dilemmna - what do we replace if we have mappings for both.
- IDK how you'd implement it in an idiomatic way that doesn't involve calling
strings.Replace
repeatedly or changing existing function behavior.
- Add a config boolean toggle (proposed name
mapped_locations_regex_replaceAll
) to make values for regex patterns be treated as literal replacement expressions passed directly to regex.ReplaceAllString2.
- Pros:
- Codebase already contains a function to facilitate "regex replace all" in the
regexp
package (yay code reuse) - Should be easier to implement and has more extensibility for nerds like me.
- Codebase already contains a function to facilitate "regex replace all" in the
- Cons:
- Inconsistent with normal replacement syntax for restrictions outside the capture group. A basic expression like
"re:(.*/Users/taylo/Documents/GitHub)/apple": "github-icon"
would end up becoming"re:.*/Users/taylo/Documents/GitHub(/apple)": "github-icon$1"
(since we want to preserve the succeeding "/apple")
- Inconsistent with normal replacement syntax for restrictions outside the capture group. A basic expression like
- Go with what I proposed in Path Segment: Add support for recursive location mapping #6166 - adding a toggle to check all mapping lines and perform each replacement in turn. Execution order could probably be the exact reverse of normal (shortest first to ensure prefixes get mapped first)3.
- Pros:
- Keeps existing syntax while also allowing for more complex use cases (albeit with a few hoops)
- Cons:
- Probably not terribly performant to perform
regex.FindStringSubmatch
andstrings.Replace
once per mapping (even if it would make said mappings somewhat less complex). Whether it would be any less performant than using several capture groups and replacement patterns (or whether any change would actually make a noticeable difference) is up for debate.
- Probably not terribly performant to perform
Notes
I'm fairly impartial on what solution is finally implemented, though I tried to keep my suggestions backwards compatible with existing configs (seen as this is a feature already in the wild).
Thanks for reading.
Footnotes
-
I already have the git segment in my config, so showing the extra folders is just wasting my already fairly limited terminal space. ↩
-
I doubt adding an additional prefix (
rer:
or whatnot) solely for these regexes is a good idea. ↩ -
I know the issue was closed as completed earlier, but it's merely an idea. ↩