unison
unison copied to clipboard
Improving the `move` experience with `moveTo` and `rename` commands
I love the premise of writing code without worrying about its location and namespace, and then doing all the organisation with move after the fact. However, in practice the experience is often quite unwieldy, and causes me to have to write commands in a scratch buffer and paste them in ucm one at the time, which is frustrating.
The problem
To give a simplified (but realistic) example of what I find myself doing, imagine I want to move durable.BTree.Id to durable.BTree.internal.Id and durable.BTree.randomId to durable.BTree.internal.randomId, and then a few minutes later decide to rename randomId to newId.
Currently I'd have to do this:
> move durable.BTree.Id durable.BTree.internal.Id
> move durable.BTree.randomId durable.BTree.internal.randomId
... couple of minutes later...
> move durable.BTree.internal.randomId durable.BTree.internal.newId
Although TAB completion helps, I still have to type 6 paths to do what I logically consider as 2 ops: 1) moving things inside a namespace, and 2) renaming a thing. This is compounded by the fact that most terminals don't let you edit in the middle of a line, that typos risk overriding something that already exists (move overrides), and that undo is slow. Plus, in real life my paths tend to be bigger, e.g. durable.BTree.internal.test.MapGeneration.generate, and that often I have to move like 5-6 things, and you can see how unwieldy it gets.
I think the situation could be improved by adding two commands that work on top of the basic move, provisionally namedmoveTo and rename.
moveTo
moveTo thing1...thingN namespaceDest will take a bunch of terms/types/namespaces, with support for numbered args, and move them inside a namespace, creating it if necessary, e.g:
moveTo foo.bar baz // ... produces baz.bar
moveTo a b there // ... produces there.a and there.b
moveTo 2 3 4 there // ... same as above, but selecting with numbers
This helps even if you are only moving a single thing because you don't have to repeat its name as part of the destination, which currently is not TAB completable and it's a source of typos for me. Furthermore, not having to repeat the name then enables moving multiple things at once.
rename
rename fully.qualified.name name2 will take a fully qualified name and change its last segment to name2, e.g.
rename thing.bar.baz Baz // ... produces thing.bar.Baz
which saves a bunch of TAB completion for the destination which you have already done for the source. I would love if this could accept a single numbered arg, especially if view with fzf produced one.
Solution
With these commands in place, the initial problem reduces to:
> find id
[..]
3. durable.BTree.Id
[..]
5. durable.BTree.randomId
> moveTo 3 5 durable.BTree.internal
... couple of minutes later...
> view (fzf) randomId
1. durable.BTree.internal.randomId
> rename 1 newId
which has a total of 1 paths typed, possibly with TAB completion.
@SystemFw thanks for opening this issue!
Thanks for reopening.
What do we want to have happen if you do this:
> moveTo bar.foo baz.foo quux
I guess you'd end up with quux.foo#abc quux.foo#def and a warning, and then you resolve the name conflict afterwards, which we already have some support for.
The warning should include the old name for context and maybe a pre-written rename command for the user to fill in.
guess you'd end up with quux.foo#abc quux.foo#def and a warning, and then you resolve the name conflict afterwards, which we already have some support for.
this would be great, but I'd be also happy with simply failing like e.g. delete does when your term is in use, it slows down this corner case but that's quickly solved by calling rename, and still speeds things up overall