-
Notifications
You must be signed in to change notification settings - Fork 947
[Enhancement] Adds P9K_DIR_SHORTEN_LENGTH to P9K_DIR_SHORTEN_STRATEGY truncate_to_unique #979
base: next
Are you sure you want to change the base?
Conversation
powerlevel9k.zsh-theme
Outdated
if (( ${#current_path} > 1 )); then # root and home are exceptions and won't have paths | ||
# cheating here to retain ~ as home folder | ||
local home_path="$(getUniqueFolder $HOME)" | ||
trunc_path="$(getUniqueFolder $(dirname $PWD))" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use ${PWD:h}
instead of $(dirname $PWD)
- it's internal and thus a lot faster 😉
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, good to know, thanks.
Using :h
I found a way to use substitution to get the left path so I can split it up more easily. (:t
would not work in this case as I understand it)
This also does not break if there are more :h
s than directory levels.
% unique_part="${PWD:h:h}"; echo $unique_part ${PWD#${unique_part}}
/home/user/git/private/confrc /submodules/powerlevel9k
% unique_part="${PWD:h:h:h:h:h:h:h:h:h:h:h:h:h:h:h:h:h:h}"; echo $unique_part ${PWD#${unique_part}}
/ home/user/git/private/confrc/submodules/powerlevel9k
I am having trouble getting a variable to control how many directories are cut off though
% echo $PWD
/home/user/git/private/confrc/submodules/powerlevel9k
% LEN=3
% # 3 for PWD, 2 characters in ":h", $LEN for setable variable
% local_pwd=${(r#$((3+2*${LEN}))##:h#)p}
% echo $local_pwd
PWD:h:h:h
% echo ${PWD:h:h:h}
/home/user/git/private
% echo ${(P)local_pwd}
/home/user/git/private/confrc/submodules/powerlevel9k
I suspect (P)
somehow ignores my :h
s. Any idea on that?
On a side note: the version in this pull request breaks stuff if you are in a level 1(?) folder, e.g. /etc
, /home
, /tmp
. I'll try to fix this and add it to the tests if I can.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
From ZSH Expansion
21. Re-evaluation Any ‘(e)’ flag is applied to the value, forcing it to be re-examined for new parameter substitutions, but also for command and arithmetic substitutions.
So try echo ${(e)local_pwd}
instead
powerlevel9k.zsh-theme
Outdated
# cheating here to retain ~ as home folder | ||
local home_path="$(getUniqueFolder $HOME)" | ||
trunc_path="$(getUniqueFolder $(dirname $PWD))" | ||
local cwd="$(basename $PWD)" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use ${PWD:t}
instead of $(basename $PWD)
fc90895
to
0e5e387
Compare
Hi @onaforeignshore, looks like you've done some restructuring. I guess merging to next isn't that easy anymore. Should I just merge next my branch and migrate my changes to the right place? |
Hey @Syphdias - We are in the middle of a big change! Check out this wiki page I just wrote to explain it: @Syphdias - Anyway, yes, you'll want to base your changes on the new |
@bhilburn There are more changes coming through |
@onaforeignshore Sounds like the code I edited will mostly stay the same besides from the location and some variable name changes. I hope I will get around to changing the structure some time today. Maybe I just copy the changes and reset my branch to |
segments/dir.p9k
Outdated
# 12 for "current_path", 2 characters in ":h", $LEN for setable variable | ||
local cwd="${(r#$((12+2*${POWERLEVEL9K_SHORTEN_DIR_LENGTH}))##:h#)cwd}" | ||
# split paths and shorten left one (beware the /) | ||
local left_path="${${(P)cwd}}" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think changes to (P)
since zsh 5.2 make this possible. I could implement a workaround with if [[ "$(zsh --version)" == *"5.1.1"* ]] ...
, a for-loop and dirame
...
This is what I started with. It would replace these lines in function:
local cwd="current_path"
local cwd="${(r#$((12+2*${POWERLEVEL9K_SHORTEN_DIR_LENGTH}))##:h#)cwd}"
local left_path="${${(P)cwd}}"
Hi, I currently have 3 topics I'd like to have some feedback/advice on:
|
|
|
Turns out I was wrong. Same behavior on
I think you misunderstood. I'll try to illustrate why I think it should be changed back.
But on
My point is, why would only one Strategy have special behavior like this? And it has nothing to do with OS X, since all strategies would suffer the same problems with the On the other hand it could be an idea to implement this behavior on purpose on a optional bases for all strategies but I'd put it further up here probably and have it default to |
Hi @onaforeignshore, could you give it another try? Also for testing locally on OS X. |
@Syphdias - Great job highlighting the difference in behavior between So, the fundamental change between @dritter @onaforeignshore - Thoughts? |
test_dir='' | ||
for (( i=0; i < ${#directory}; i++ )); do | ||
test_dir+="${directory:$i:1}" | ||
matching=("$cur_path"/"$test_dir"*/) | ||
matching=("$cur_path/$test_dir"*/) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That code iterates over the current directory character by character and tries to find a directory that is distinct from the original one, right? Wouldn't it be more performant to get all directories with the same first character once and then try to find a unique name?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure if I understand it correctly. Instead of using the expansion you'd use a "grep
" like ${(M)#sub_directories_array:#start_char*}
to find if this expression equals exactly 1?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes. Currently, you try to find a unique name by building up a glob that is every time a character longer, as long you did not find exactly one match. This is a hit to the disk every time.
My hypothesis is now that you have all information necessary after the first glob to build up a unique directory.
Example:
In a folder structure like this:
.
├── asdf
├── asdf100
├── asdf101
├── asdf102
├── asdf2
├── asdf3
├── asdf4
├── asdf5
├── asdf6
├── asdf7
│ └── a
│ └── b
│ └── c
├── asdf8
├── asdf89
└── asdf99
we search the folder asdf7
(Current code)
declare -a matching
directory="asdf7"
test_dir=""
for (( i=0; i < ${#directory}; i++ )); do
test_dir+="${directory:$i:1}"
echo $test_dir;
matching=("${PWD}/${test_dir}"*/);
echo $matching
done
If we modify that loop a bit:
declare -a matching
directory="asdf7"
test_dir=""
matching=("${PWD}/${directory[1]}"*/);
for (( i=0; i < ${#directory}; i++ )); do
test_dir+="${directory:$i:1}"
echo "Testing: $test_dir";
pattern="${PWD}/${test_dir}*"
matching=("${(M)matching:#${pattern}}")
echo $matching
done
(not functional, but you get the idea).
This will need some measurings, but I think the second variant will be faster.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
~/test/asdf101 ❱ source ~/bla\ foo/cancer/test.zsh; ITER=100000; time (repeat $ITER; do old NUL; done); time (repeat $ITER; do new NUL; done); time (repeat $ITER; do new2 NUL; done)
( repeat $ITER; do; old > /dev/null 2>&1; done; ) 21.87s user 16.65s system 99% cpu 38.623 total
( repeat $ITER; do; new > /dev/null 2>&1; done; ) 22.54s user 11.58s system 99% cpu 34.143 total
( repeat $ITER; do; new2 > /dev/null 2>&1; done; ) 20.36s user 11.16s system 99% cpu 31.539 total
~/test/asdf7 ❱ source ~/bla\ foo/cancer/test.zsh; ITER=100000; time (repeat $ITER; do old NUL; done); time (repeat $ITER; do new NUL; done); time (repeat $ITER; do new2 NUL; done)
( repeat $ITER; do; old > /dev/null 2>&1; done; ) 19.11s user 14.54s system 99% cpu 33.706 total
( repeat $ITER; do; new > /dev/null 2>&1; done; ) 21.34s user 11.57s system 99% cpu 32.938 total
( repeat $ITER; do; new2 > /dev/null 2>&1; done; ) 18.26s user 10.96s system 99% cpu 29.238 total
❱ tree ~/test
/home/user/test
├── asdf
├── asdf100
├── asdf101
├── asdf102
├── asdf2
├── asdf3
├── asdf4
├── asdf5
├── asdf6
├── asdf7
├── asdf8
├── asdf89
└── asdf99
but
~/bla foo/cancer/d*reck ❱ source ~/bla\ foo/cancer/test.zsh; ITER=100000; time (repeat $ITER; do old NUL; done); time (repeat $ITER; do new NUL; done); time (repeat $ITER; do new2 NUL; done)
( repeat $ITER; do; old > /dev/null 2>&1; done; ) 16.06s user 12.77s system 99% cpu 28.942 total
( repeat $ITER; do; new > /dev/null 2>&1; done; ) 19.98s user 11.59s system 99% cpu 31.591 total
( repeat $ITER; do; new2 > /dev/null 2>&1; done; ) 18.21s user 11.13s system 99% cpu 29.364 total
❱ tree ~/bla\ foo
/home/user/bla foo
├── a
│ └── b
│ └── c
├── ca cer
│ ├── dareck
│ └── d*rwin
├── cancer
│ ├── dareck
│ ├── d*reck
│ └── test.zsh
└── cancer2
What I tested with:
# ~/bla\ foo/cancer/test.zsh
pwd=$(echo $PWD |sed 's#/home/user#~#')
old() {
local long_path paths cur_path trunc_path matching
#long_path='~/bla foo/ca cer/d*rwin'
#long_path='~/bla foo/cancer/d*reck'
long_path=$pwd
paths=(${(s:/:)long_path})
paths=(${paths[@]:1})
cur_path='/home/user/'
trunc_path='~/'
for directory in ${paths}; do
# finds out how many characters you need for the $directory to be unique
test_dir=''
for (( i=0; i < ${#directory}; i++ )); do
test_dir+="${directory:$i:1}"
matching=("$cur_path/$test_dir"*/)
if [[ ${#matching[@]} -eq 1 ]]; then
break
fi
done
trunc_path+="${test_dir}/"
cur_path+="${directory}/"
done
[[ ${#trunc_path} == 1 ]] \
&& echo "${trunc_path}" \
|| echo "${trunc_path: : -1}"
}
new() {
local long_path paths cur_path trunc_path matching pattern
#long_path='~/bla foo/ca cer/d*rwin'
#long_path='~/bla foo/cancer/d*reck'
long_path=$pwd
paths=(${(s:/:)long_path})
paths=(${paths[@]:1})
cur_path='/home/user/'
trunc_path='~/'
for directory in ${paths}; do
# finds out how many characters you need for the $directory to be unique
test_dir=''
matching=("$cur_path"*/)
for (( i=0; i < ${#directory}; i++ )); do
test_dir+="${directory:$i:1}"
pattern="${cur_path}${test_dir}"
matching=(${(M)matching:#${pattern}*})
if [[ ${#matching[@]} -eq 1 ]]; then
break
fi
done
trunc_path+="${test_dir}/"
cur_path+="${directory}/"
done
[[ ${#trunc_path} == 1 ]] \
&& echo "${trunc_path}" \
|| echo "${trunc_path: : -1}"
}
new2() {
local long_path paths cur_path trunc_path matching pattern
#long_path='~/bla foo/ca cer/d*rwin'
#long_path='~/bla foo/cancer/d*reck'
long_path=$pwd
paths=(${(s:/:)long_path})
paths=(${paths[@]:1})
cur_path='/home/user/'
trunc_path='~/'
for directory in ${paths}; do
# finds out how many characters you need for the $directory to be unique
test_dir=''
matching=("$cur_path"*/)
for (( i=0; i < ${#directory}; i++ )); do
test_dir+="${directory:$i:1}"
pattern="${cur_path}${test_dir}"
if [[ ${(M)#matching:#${pattern}*} -eq 1 ]]; then
break
fi
done
trunc_path+="${test_dir}/"
cur_path+="${directory}/"
done
[[ ${#trunc_path} == 1 ]] \
&& echo "${trunc_path}" \
|| echo "${trunc_path: : -1}"
}
Hm, locally the vcs_git tests fail, even on next, but the travis tests are ok. Let's see what happens to my travis pipelines... @dritter I'm not quite sure why you added the Also you introduced
Imagine you cd "into" a symlink and see the path the symlink linked to. In most cases |
The |
Well, currently not every strategy used the prefix thing, so I'm opting to not use it. ;-) In a perfect world I think it should work like this:
Interestingly you removed it in 8002cba Funny how a small PR can get this big, just by changes around it |
Not yet. But this is on my todo list in my head. I think it is not a good idea to let the various truncation strategies behave differently, even in small details. This leads to "why does feature X not work in strategy A, but does if I use strategy B" like errors quickly. I prefer consistency here. My perfect world for the truncation strategies failed. In this branch I tried to make the strategies more flexible, so that users could choose to apply different truncation strategies and for different things. Even now there are users who want to mix different strategies.
Yep. |
Do you want me to to rebase and squash this PR into one commit based on current |
- modifies __p9k_get_unique_path to be able to hande paths with ~ and relative paths. It now echos the full path (with leading "/" or "~") and is able to handle "shortened" $HOME (~) paths. Only a dot "." as input will echo nothing. - The changes to __p9k_get_unique_path make it possible to expand the functionality of truncate_to_unique to take an extra option: $POWERLEVEL9K_SHORTEN_DIR_LENGTH that controls how many of the last directories shall not be shortened, defaults to 1 if unset. - Adds a lot more tests for making sure everything works as expected.
I rebased to current |
I've resolved more conflicts with this because of code moving to other places than I care to count. I'm not doing it again unless it's going to get merged soon after. Please let me know if you want to merge and think the changes need improving. |
this is functionality I would love to see. Is there a way to achieve this currently, or is this PR the only solution? If so, what is currently holding up this getting merged in? |
@ccjensen the only thing that holds us back from merging is that we consider this PR as a new feature, and we are currently working hard to push out a new release (already in feature freeze phase). But we will merge this, once 0.7.0 is out. |
Note to self: This is a great idea for a feature request: #1277 (comment) TL;DR: |
I thought it would be nice to see the current directory in its full length and have the rest of the path truncated. I think it's a good compromise between space efficiency and readability/orientation.
I'd say it's a mix between
truncate_to_unique
andtruncate_from_right
A nice addition would be to use POWERLEVEL9K_SHORTEN_DIR_LENGTH to determine how many directories should not be truncated from the right. Maybe as $2 parameter to getUniqueFolder and poping that many items from the paths array.
If you like
truncate_to_unique_but_last
I could try to implement the DIR_LENGTH intotruncate_to_unique
instead of inventing a new "strategy".Please let me know what you think!