Add support for tab-local directories#4212
Conversation
Codecov Report
@@ Coverage Diff @@
## master #4212 +/- ##
==========================================
- Coverage 79.93% 79.88% -0.06%
==========================================
Files 108 108
Lines 141624 141774 +150
==========================================
+ Hits 113211 113257 +46
- Misses 28413 28517 +104
Continue to review full report at Codecov.
|
|
I don't see why this is necessary. Some Vimscript and |
|
Hi,
On Fri, Apr 5, 2019 at 9:32 AM chdiza ***@***.***> wrote:
I don't see why this is necessary. Some Vimscript and :lcd'ing should handle all of this.
When you have more than one tab page with multiple windows in each, changing
the global directory using ":cd" will change the directories of all the windows
across the tab pages unless you have specified a window local directory using
:lcd in each of the windows. The ":tcd" command allows you to use a separate
working directory for each of the tab pages which are dedicated to a separate
workflow.
I am listing some of the links I found where this feature is discussed:
https://hiphish.github.io/blog/2016/04/22/neovim-tcd/
https://dmerej.info/blog/post/vim-cwd-and-neovim/
https://www.reddit.com/r/vim/comments/4q2wmi/keep_working_directory_per_tab/
http://vim.1045645.n5.nabble.com/Different-working-directories-in-different-tabs-td4441751.html
- Yegappan
|
|
Yegappan wrote:
Add support for tab-local directories. Introduces the ":tcd" command
to change the directory of the current tabpage.
Credit: Idea from the neovim implementation.
Thanks. It's also been in the todo list for a long time. I believe it
to be useful, for people who use one tab per project.
I'll wait a bit to give others a chance to try it out and comment on the
details of how it works.
…--
hundred-and-one symptoms of being an internet addict:
203. You're an active member of more than 20 newsgroups.
/// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\
/// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\
\\\ an exciting new programming language -- http://www.Zimbu.org ///
\\\ help me help AIDS victims -- http://ICCF-Holland.org ///
|
8da916c to
186b4c5
Compare
|
I do like the idea of a tab-local cwd. Few comments though:
|
|
Hi,
On Sun, Apr 7, 2019 at 6:06 PM Yee Cheng Chin ***@***.***> wrote:
I do like the idea of a tab-local cwd. Few comments though:
I found a bug in the current implementation. Do the following to reproduce the bug:
tcd foo
lcd bar
mksession session.vim
source session.vim
echo getcwd()
This script should output "bar", but it shows "foo" instead. Note that this
only happens for the first split of a tab. It works properly for the other
splits as far as I can tell.
Thanks for trying out the patch and reporting the issue. I am able to
reproduce it. I will send out an updated patch with a fix for this.
If my current window already as a local window dir (:lcd), then I do :tcd, it
overrides the current localdir. I guess this makes sense since a :cd would
override both :tcd and :lcd anyway so it's consistent but just wanted to
point that out.
Yes. When you invoke the ":tcd" command, the working directory of
the current window is also changed. This is similar to how the ":cd"
command works (as you pointed out).
- Yegappan
…
I'm wondering if the logical extension of this would balloon to tab vs
window-local settings (e.g. tab versions of :setlocal) and other related
requests. But maybe that's for another day.
|
|
Is |
|
Hi,
On Mon, Apr 8, 2019 at 8:13 AM Luc Hermitte ***@***.***> wrote:
Is :tcd just a convenience command equivalent to :tabdo :lcd?
No.
Or will Vim remember there is a current directory in the current tab?
Yes. Vim will remember a separate working directory for each of the tab pages.
You now have a global working directory, a tab-local working directory and a
window-local working directory.
- Yegappan
|
But what is gained by this that couldn't just be had by making all windows in a tab have the same window-local directory? I looked at the links mentioned, but none of them seem to really justify this tab-local business. ("I don't want to put some Vimscript in my .vimrc" is not a justification.) Some of them even show that there's a plugin that works, and in another, the OP was completely satisifed with just opening a new tab and doing |
So why don't you just do the part after the word "unless"? |
In that case, it'll be interesting to have access to this information from vim scripts. This means that (*) It's my function! lh#path#cd_without_sideeffects(path) abort
let cd = exists('*haslocaldir') && haslocaldir()
\ ? 'lcd '
\ : 'cd '
exe cd . a:path
endfunction(I've seem a very similar pattern in plugins other than mine: I'm thinking about fugitive) |
|
> Vim will remember a separate working directory for each of the tab pages
But what is gained by this that couldn't just be had by making all
windows in a tab have the same window-local directory?
That you don't need to have the same window-local directory in all
windows in the tab. That's the whole point, you can ":tcd somewhere"
and all windows follow. Without scripts or other stuff. And if a
window has used ":lcd elsewhere" it will keep that (which is actually
difficult to do with a plugin).
For me, I often use ":grep" which depends on the local directory to find
the right files. Manually having to make sure all windows in a tab have
the right local directory is a hassle.
It also makes sense from a higher level, if you use tabs as a workspace.
…--
hundred-and-one symptoms of being an internet addict:
231. You sprinkle Carpet Fresh on the rugs and put your vacuum cleaner
in the front doorway permanently so it always looks like you are
actually attempting to do something about that mess that has amassed
since you discovered the Internet.
/// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\
/// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\
\\\ an exciting new programming language -- http://www.Zimbu.org ///
\\\ help me help AIDS victims -- http://ICCF-Holland.org ///
|
|
Hi,
On Mon, Apr 8, 2019 at 9:59 AM Luc Hermitte ***@***.***> wrote:
Or will Vim remember there is a current directory in the current tab?
Yes. Vim will remember a separate working directory for each of the tab pages.
You now have a global working directory, a tab-local working directory and a
window-local working directory.
In that case, it'll be interesting to have access to this information from
vim scripts. This means that has_localdir() should return 1 or 2 depending on
the locality of the directory (*). We can also imagine a 3 value the day we
have real project-local directories.
In the first set of changes to haslocaldir(), I did implement haslocaldir() to
return 1 or 2 depending on whether the current window has a win-local or
a tab-local directory. But then I decided to change it to always return 1 for
both cases (because the existing scripts are not distinguishing between 1 and 2,
and to be consistent with the neovim implementation). We can change this
implementation, if it will be more useful to return different values.
Regards,
Yegappan
…
(*) It's my cd_without_sideeffects() function that makes me guess we'll need more information
function! lh#path#cd_without_sideeffects(path) abort
let cd = exists('*haslocaldir') && haslocaldir()
\ ? 'lcd '
\ : 'cd '
exe cd . a:path
endfunction
(I've seem a very similar pattern in plugins other than mine: I'm thinking about fugitive)
|
I'm not questioning whether there's a use case for this; I'm questioning why this needs to be a built-in function rather than done by scripts/plugins. (E.g., What's the point of the new "win_id" functions if not to use them for something like this?) Perhaps a better idea instead is a more general new command, |
I don't understand. If you ":tcd somewhere" and all windows follow, then all windows in the tab have the same window-local directory. (Or else, I have no idea what "follow" means.) |
|
Otherwise you could use the same logic and argue you don’t actually need |
It wouldn't be annoying to keep track of, if you wrapped it in a custom command called ":Cd"! For the life of me, I don't see why something like that can't be done instead of :tcd. Just define a function in Vimscript and call it from a command called ":Tcd". That's what Vimscript is for. Make it one of the standard plugins that's shipped if need be. |
|
How do you keep track of whether a window’s lcd is set by a user’s manual Even with a plugin working not everyone will use the same plugin (even if it’s shipped with Vim) so if you are writing scripts to take advantage of this new feature, you suddenly need to decide if you want to bundle this random “Tcd” plugin as well. Functions like A lot of features and key bindings can technically be implemented in scripts too but it is a matter of compromise (ongoing maintainence cost vs benefit of built in availability). |
|
Hi,
On Mon, Apr 8, 2019 at 2:03 PM chdiza ***@***.***> wrote:
as you could use Vimscript to do :tabdo windo lcd every time you want to do :cd, but that’s annoying to keep track of.
It wouldn't be annoying to keep track of, if you wrapped it in a custom command called ":Cd"!
For the life of me, I don't see why something like that can't be done instead
of :tcd. Just define a function in Vimscript and call it from a command
called ":Tcd". That's what Vimscript is for. Make it one of the standard
plugins that's shipped if need be.
You also need to provide new getcwd() and haslocaldir() functions that return
the proper win-local or tab-local directories. For example, you can directly
query the tab-local working directory independent of a window in the tab page
using a win-local directory.
The Vim plugin has to implement all of these functionality. I think it is better
to provide a native implementation as changing working directories is part
of the core Vim functionality.
- Yegappan
|
You would store that info in some tablocal or windowlocal variable, in whatever function gets called by :Tcd. Then if you want to retrieve it, it's just
This makes no sense. Every window has but one current working dir, and getcwd() tells you what it is. It doesn't stop working just because you lcd'd.
There's nothing "random" about a built-in plugin. To make sure it's there, use |
|
Something I don't like in the Neovim implementation: creating a new tabpage ( This is annoying. We did it this way to mimic window-local directories, but I don't think it's necessary. If someone wants "sticky" behavior they can use What is the behavior of this PR is that respect? |
|
Something I don't like in the Neovim implementation: creating a new
tabpage (`:tabnew`, `:tabedit`) "inherits" the tab-local dir of the
current tabpage. Example:
```
:tcd /
:tabnew
:echo getcwd() " => /
```
This is annoying. We did it this way to mimic window-local
directories, but I don't think it's necessary. If someone wants
"sticky" behavior they can use `:lcd`. Tab-local directories are more
useful as an "alternative global CWD" for _only_ a particular tab.
What is the behavior of this PR is that respect?
When opening a new tabpage, it would make sense to have it start in the
global directory. On the other hand, when doing:
:tabedit somefile
You don't really expect to jump to another directory. I know some
people like to jump to the directory that file is in, setting
'autochdir' does that. But otherwise it seems wrong to jump to another
directory than what is currently the effective directory.
And then it's probably best to have :tabedit do the same no matter what
arguments are given.
In the new tab we have a choice to only set the local directory of the
new window, or set the directory of the tab. Perhaps it works best if
we make the tab use the global directory, and set the window-local
directory if it was set in the previous window? It's probably also
needed for backwards compatibility. So long as you split a window in
the tab, the tab-local directory won't matter anyway.
…--
hundred-and-one symptoms of being an internet addict:
270. You are subscribed to a mailing list for every piece of software
you use.
/// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\
/// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\
\\\ an exciting new programming language -- http://www.Zimbu.org ///
\\\ help me help AIDS victims -- http://ICCF-Holland.org ///
|
|
Hi,
On Sat, Apr 13, 2019 at 5:06 AM Justin M. Keyes ***@***.***> wrote:
Something I don't like in the Neovim implementation: creating a new tabpage
(:tabnew, :tabedit) "inherits" the tab-local dir of the current tabpage.
Example:
:tcd /
:tabnew
:echo getcwd() " => /
What is the behavior of this PR is that respect?
The behavior of the current implementation is the same as that of the
neovim behavior. When a new tabpage is created, it inherits the
directory state of the previous tabpage and window. If the previous
tabpage had a tab-local directory set, then the new tabpage also has the
same tab-local directory set. If the previous window had a window-local
directory, then the new window in the new tabpage also has a
window-local directory.
This is annoying. We did it this way to mimic window-local directories, but I
don't think it's necessary. If someone wants "sticky" behavior they can use
:lcd. Tab-local directories are more useful as an "alternative global CWD"
for only a particular tab.
Are you suggesting that we use the tab-local directory (if set) of the
previous tabpage for the new window in the new tabpage? If it is not
set, then use the global directory. This will not be backward compatible
though.
Regards,
Yegappan
|
No. I am speaking specifically of the case where there is no window-local directory, only a tab-local directory. Having that tab-local directory "stick" to all new tabs is really annoying. |
|
Hi Bram,
On Sat, Apr 13, 2019 at 5:53 AM Bram Moolenaar ***@***.***> wrote:
> Something I don't like in the Neovim implementation: creating a new
> tabpage (`:tabnew`, `:tabedit`) "inherits" the tab-local dir of the
> current tabpage. Example:
>
> ```
> :tcd /
> :tabnew
> :echo getcwd() " => /
> ```
>
> This is annoying. We did it this way to mimic window-local
> directories, but I don't think it's necessary. If someone wants
> "sticky" behavior they can use `:lcd`. Tab-local directories are more
> useful as an "alternative global CWD" for _only_ a particular tab.
>
> What is the behavior of this PR is that respect?
When opening a new tabpage, it would make sense to have it start in the
global directory. On the other hand, when doing:
:tabedit somefile
You don't really expect to jump to another directory. I know some
people like to jump to the directory that file is in, setting
'autochdir' does that. But otherwise it seems wrong to jump to another
directory than what is currently the effective directory.
And then it's probably best to have :tabedit do the same no matter what
arguments are given.
In the new tab we have a choice to only set the local directory of the
new window, or set the directory of the tab. Perhaps it works best if
we make the tab use the global directory, and set the window-local
directory if it was set in the previous window? It's probably also
needed for backwards compatibility. So long as you split a window in
the tab, the tab-local directory won't matter anyway.
The behavior of the current implementation is for the new tabpage
to inherit the tab-local directory of the previous tabpage. The new
window in the new tabpage inherits the directory of the previous
window.
Regards,
Yegappan
|
|
Hi,
On Sat, Apr 13, 2019 at 8:53 AM Justin M. Keyes ***@***.***> wrote:
> Are you suggesting that we use the tab-local directory (if set) of the
> previous tabpage for the new window in the new tabpage? If it is not set,
> then use the global directory.
No. I am speaking specifically of the case where there is no window-local
directory, only a tab-local directory. Having that tab-local directory
"stick" to all new tabs is really annoying.
So a new tabpage will not have a tab-local directory, but the new window
in the tabpage will use the directory of the previous window? or the new
window will either use the global directory or the window-local directory of
the previous window?
- Yegappan
|
5f2c556 to
4517142
Compare
…aslocaldir() functions
…lated information
…n-local directory. Support using 0 to refer to the current tabpage. Update the documentation.
… tests. Update documentation
|
Great, now plugins have to change directories like this: " change directory with right command
function! s:chdir(path)
if has('nvim')
let cmd = haslocaldir()? 'lcd' : (haslocaldir(-1, 0)? 'tcd' : 'cd')
else
let cmd = haslocaldir()? ((haslocaldir() == 1)? 'lcd' : 'tcd') : 'cd'
endif
silent execute cmd . ' '. fnameescape(a:path)
endfunc
let previous= getcwd()
call s:chdir(somewhere)
...
call s:chdir(previous) |
|
Great, now plugins have to change directories like this:
```viml
" change directory with right command
function! s:chdir(path)
if has('nvim')
let cmd = haslocaldir()? 'lcd' : (haslocaldir(-1, 0)? 'tcd' : 'cd')
else
let cmd = haslocaldir()? ((haslocaldir() == 1)? 'lcd' : 'tcd') : 'cd'
endif
silent execute cmd . ' '. fnameescape(a:path)
endfunc
let previous= getcwd()
call s:chdir(somewhere)
...
call s:chdir(previous)
```
I suppose we could add a command to change the effective directory.
":ecd" ? Then it would be:
let previous = getcwd()
ecd somewhere
...
exe "ecd " .. previous
…--
ARTHUR: Be quiet!
DENNIS: --but by a two-thirds majority in the case of more--
ARTHUR: Be quiet! I order you to be quiet!
WOMAN: Order, eh -- who does he think he is?
ARTHUR: I am your king!
The Quest for the Holy Grail (Monty Python)
/// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\
/// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\
\\\ an exciting new programming language -- http://www.Zimbu.org ///
\\\ help me help AIDS victims -- http://ICCF-Holland.org ///
|
|
temporarily changing directory is used widely in plugins, maybe a function form is better: It will change current directory to And life will be much easier with let previous = chdir(somewhere, 1)
...
chdir(previous)No need for "exe" statement, no need for "fnameescape" too. |
|
Or, introduce a bang modifier to command |
Problem: Cannot set a directory for a tab page. Solution: Add the tab-local directory. (Yegappan Lakshmanan, closes vim/vim#4212) vim/vim@00aa069
Problem: Cannot set a directory for a tab page. Solution: Add the tab-local directory. (Yegappan Lakshmanan, closes vim/vim#4212) vim/vim@00aa069
Problem: Cannot set a directory for a tab page. Solution: Add the tab-local directory. (Yegappan Lakshmanan, closes vim/vim#4212) vim/vim@00aa069 Session-related changes only. Co-authored-by: Bram Moolenaar <Bram@vim.org>
Add support for tab-local directories. Introduces the ":tcd" command
to change the directory of the current tabpage.
Credit: Idea from the neovim implementation.