zellij icon indicating copy to clipboard operation
zellij copied to clipboard

Feature: move tab to other position

Open jaeheonji opened this issue 2 years ago • 11 comments

Reference #1654

  1. Tab can be moved forward or backward
<tab 1> | <tab 2 *> | <tab 3>

# backward
<tab 1> | <tab 3> | <tab 2 *>
<tab 1> | <tab 2 *> | <tab 3>

# forward
<tab 2 *> | <tab 1> | <tab 3> 
  1. Move tabs to the front or back
<tab 1 *> | <tab 2> | <tab 3>

# back
<tab 2> | <tab 3> | <tab 1 *>
<tab 1 > | <tab 2> | <tab 3 *>

# back
<tab 3 *> | <tab 1 > | <tab 2>

jaeheonji avatar Aug 13 '22 17:08 jaeheonji

I'll try to implement this since I think that it shouldn't take too long (or am I wrong?)

TornaxO7 avatar Aug 13 '22 17:08 TornaxO7

@TornaxO7 Awesome! If you want, you can do it anytime. No need to rush!

jaeheonji avatar Aug 13 '22 17:08 jaeheonji

@jaeheonji ScreenContext is only used for error messages, right? Because I'm thinking of creating just a MoveTab entry for this instead of MoveTabRight, MoveTabRight and so on

TornaxO7 avatar Aug 13 '22 17:08 TornaxO7

@jaeheonji Is it fine if I'm also trying to refactor a little bit the Screen struct? I'd like to move the tabs attribute to an extra-struct and move some methods of screen as well.

TornaxO7 avatar Aug 13 '22 19:08 TornaxO7

@jaeheonji I also have another question: Why are you picking up the history of the first entry according to this line? Why not creating a new history for the new client?

TornaxO7 avatar Aug 13 '22 21:08 TornaxO7

ScreenContext is only used for error messages, right? Because I'm thinking of creating just a MoveTab entry for this instead of MoveTabRight, MoveTabRight and so on

Yes! The context is used for errors. In order to implement this feature, you will need to implement a new action. So you will have to add something new to Context and Action such as MoveTabRight, MoveTabLeft

Is it fine if I'm also trying to refactor a little bit the Screen struct? I'd like to move the tabs attribute to an extra-struct and move some methods of screen as well.

Of course, If you need it you can. However, if there are a lot of refactoring contents, it would be good for a review to make a separate PR.

I also have another question: Why are you picking up the history of the first entry according to this line? Why not creating a new history for the new client?

As far as I know, this is meant to be a multiple session feature. Because multiple sessions share one session with multiple clients. Therefore, in the case of a tab, the history is loaded instead of creating a new one.

jaeheonji avatar Aug 14 '22 02:08 jaeheonji

@jaeheonji May I ask you what those slices represent?

TornaxO7 avatar Aug 14 '22 10:08 TornaxO7

@TornaxO7 That is bracketed paste code such as \u{1b}[200~, \u{1b}[201~. Related information can be found on the following wiki.

jaeheonji avatar Aug 15 '22 06:08 jaeheonji

@jaeheonji general question because I'm getting a server error currently xD. What I've done now is adding my actions in zellij/zellij-utils/src/input/actions.rs and adjusted the stuff in zellij/zellij-server/src/screen.rs. Now I just added my actions to zellij/example/default.yaml and rebuild everything with cargo build. If I start zellij I'm getting a server-panic. Here's the output if you're interested in it:

[?1049h[?1l=[r[?1000l[?1002l[?1003l[?1005l[?1006l[?12l[?2004h[?1000h[?1002h[?1015h[?1006h[14t[16t]11;?\]10;?\]4;0;?\]4;1;?\]4;2;?\]4;3;?\]4;4;?\]4;5;?\]4;6;?\]4;7;?\]4;8;?\]4;9;?\]4;10;?\]4;11;?\]4;12;?\]4;13;?\]4;14;?\]4;15;?\]4;16;?\]4;17;?\]4;18;?\]4;19;?\]4;20;?\]4;21;?\]4;22;?\]4;23;?\]4;24;?\]4;25;?\]4;26;?\]4;27;?\]4;28;?\]4;29;?\]4;30;?\]4;31;?\]4;32;?\]4;33;?\]4;34;?\]4;35;?\]4;36;?\]4;37;?\]4;38;?\]4;39;?\]4;40;?\]4;41;?\]4;42;?\]4;43;?\]4;44;?\]4;45;?\]4;46;?\]4;47;?\]4;48;?\]4;49;?\]4;50;?\]4;51;?\]4;52;?\]4;53;?\]4;54;?\]4;55;?\]4;56;?\]4;57;?\]4;58;?\]4;59;?\]4;60;?\]4;61;?\]4;62;?\]4;63;?\]4;64;?\]4;65;?\]4;66;?\]4;67;?\]4;68;?\]4;69;?\]4;70;?\]4;71;?\]4;72;?\]4;73;?\]4;74;?\]4;75;?\]4;76;?\]4;77;?\]4;78;?\]4;79;?\]4;80;?\]4;81;?\]4;82;?\]4;83;?\]4;84;?\]4;85;?\]4;86;?\]4;87;?\]4;88;?\]4;89;?\]4;90;?\]4;91;?\]4;92;?\]4;93;?\]4;94;?\]4;95;?\]4;96;?\]4;97;?\]4;98;?\]4;99;?\]4;100;?\]4;101;?\]4;102;?\]4;103;?\]4;104;?\]4;105;?\]4;106;?\]4;107;?\]4;108;?\]4;109;?\]4;110;?\]4;111;?\]4;112;?\]4;113;?\]4;114;?\]4;115;?\]4;116;?\]4;117;?\]4;118;?\]4;119;?\]4;120;?\]4;121;?\]4;122;?\]4;123;?\]4;124;?\]4;125;?\]4;126;?\]4;127;?\]4;128;?\]4;129;?\]4;130;?\]4;131;?\]4;132;?\]4;133;?\]4;134;?\]4;135;?\]4;136;?\]4;137;?\]4;138;?\]4;139;?\]4;140;?\]4;141;?\]4;142;?\]4;143;?\]4;144;?\]4;145;?\]4;146;?\]4;147;?\]4;148;?\]4;149;?\]4;150;?\]4;151;?\]4;152;?\]4;153;?\]4;154;?\]4;155;?\]4;156;?\]4;157;?\]4;158;?\]4;159;?\]4;160;?\]4;161;?\]4;162;?\]4;163;?\]4;164;?\]4;165;?\]4;166;?\]4;167;?\]4;168;?\]4;169;?\]4;170;?\]4;171;?\]4;172;?\]4;173;?\]4;174;?\]4;175;?\]4;176;?\]4;177;?\]4;178;?\]4;179;?\]4;180;?\]4;181;?\]4;182;?\]4;183;?\]4;184;?\]4;185;?\]4;186;?\]4;187;?\]4;188;?\]4;189;?\]4;190;?\]4;191;?\]4;192;?\]4;193;?\]4;194;?\]4;195;?\]4;196;?\]4;197;?\]4;198;?\]4;199;?\]4;200;?\]4;201;?\]4;202;?\]4;203;?\]4;204;?\]4;205;?\]4;206;?\]4;207;?\]4;208;?\]4;209;?\]4;210;?\]4;211;?\]4;212;?\]4;213;?\]4;214;?\]4;215;?\]4;216;?\]4;217;?\]4;218;?\]4;219;?\]4;220;?\]4;221;?\]4;222;?\]4;223;?\]4;224;?\]4;225;?\]4;226;?\]4;227;?\]4;228;?\]4;229;?\]4;230;?\]4;231;?\]4;232;?\]4;233;?\]4;234;?\]4;235;?\]4;236;?\]4;237;?\]4;238;?\]4;239;?\]4;240;?\]4;241;?\]4;242;?\]4;243;?\]4;244;?\]4;245;?\]4;246;?\]4;247;?\]4;248;?\]4;249;?\]4;250;?\]4;251;?\]4;252;?\]4;253;?\]4;254;?\]4;255;?\[?1006l[?1015l[?1002l[?1000l[?1049l
[53;1HError occurred in server:

  [38;2;255;30;30m×[0m Thread '[0;31mwasm[0;0m' panicked.
[38;2;255;30;30m  ├─▶ [0mOriginating Thread(s)
[38;2;255;30;30m  │   [0m	[0;0m1. ipc_server: NewClient
[38;2;255;30;30m  │   [0m	[0;0m2. pty_thread: NewTab
[38;2;255;30;30m  │   [0m	[0;0m3. screen_thread: NewTab
[38;2;255;30;30m  │   [0m	[0;0m4. plugin_thread: Update
[38;2;255;30;30m  │   [0m
[38;2;255;30;30m  ├─▶ [0mAt zellij-server/src/wasm_vm.rs:145:42
[38;2;255;30;30m  ╰─▶ [0m[0;31mcalled `Result::unwrap()` on an `Err` value: RuntimeError { source: Trap(UnreachableCodeReached), wasm_trace: [FrameInfo { module_name: "<module>", func_index: 197, function_name: None,
[38;2;255;30;30m      [0mfunc_start: SourceLoc(118496), instr: SourceLoc(122024) }, FrameInfo { module_name: "<module>", func_index: 98, function_name: None, func_start: SourceLoc(60011), instr: SourceLoc(60258) },
[38;2;255;30;30m      [0mFrameInfo { module_name: "<module>", func_index: 103, function_name: None, func_start: SourceLoc(61807), instr: SourceLoc(61928) }, FrameInfo { module_name: "<module>", func_index: 509,
[38;2;255;30;30m      [0mfunction_name: None, func_start: SourceLoc(409017), instr: SourceLoc(427451) }], native_trace:    0: <unknown>
[38;2;255;30;30m      [0m   1: <unknown>
[38;2;255;30;30m      [0m   2: <unknown>
[38;2;255;30;30m      [0m   3: <unknown>
[38;2;255;30;30m      [0m   4: <unknown>
[38;2;255;30;30m      [0m   5: <unknown>
[38;2;255;30;30m      [0m   6: <unknown>
[38;2;255;30;30m      [0m   7: <unknown>
[38;2;255;30;30m      [0m   8: <unknown>
[38;2;255;30;30m      [0m   9: <unknown>
[38;2;255;30;30m      [0m  10: <unknown>
[38;2;255;30;30m      [0m  11: <unknown>
[38;2;255;30;30m      [0m  12: <unknown>
[38;2;255;30;30m      [0m }[0;0m
[38;2;255;30;30m      [0m   0: zellij_utils::errors::Panic::show_backtrace
[38;2;255;30;30m      [0m             at /windows/Programming/pull_requests/zellij/zellij-utils/src/errors.rs:32:42
[38;2;255;30;30m      [0m   1: <zellij_utils::errors::Panic as core::fmt::Display>::fmt
[38;2;255;30;30m      [0m             at /windows/Programming/pull_requests/zellij/zellij-utils/src/errors.rs:24:18
[38;2;255;30;30m      [0m   2: <T as alloc::string::ToString>::to_string
[38;2;255;30;30m      [0m             at /rustc/fe5b13d681f25ee6474be29d748c65adcd91f69e/library/alloc/src/string.rs:2405:9
[38;2;255;30;30m      [0m   3: miette::handlers::graphical::GraphicalReportHandler::render_causes
[38;2;255;30;30m      [0m             at .cargo/registry/src/github.com-1ecc6299db9ec823/miette-3.3.0/src/handlers/graphical.rs:206:51
[38;2;255;30;30m      [0m   4: miette::handlers::graphical::GraphicalReportHandler::render_report
[38;2;255;30;30m      [0m             at .cargo/registry/src/github.com-1ecc6299db9ec823/miette-3.3.0/src/handlers/graphical.rs:112:9
[38;2;255;30;30m      [0m   5: zellij_utils::errors::fmt_report
[38;2;255;30;30m      [0m             at /windows/Programming/pull_requests/zellij/zellij-utils/src/errors.rs:50:5
[38;2;255;30;30m      [0m   6: zellij_utils::errors::handle_panic
[38;2;255;30;30m      [0m             at /windows/Programming/pull_requests/zellij/zellij-utils/src/errors.rs:113:38
[38;2;255;30;30m      [0m   7: zellij_server::start_server::{{closure}}
[38;2;255;30;30m      [0m             at /windows/Programming/pull_requests/zellij/zellij-server/src/lib.rs:227:13
[38;2;255;30;30m      [0m   8: std::panicking::rust_panic_with_hook
[38;2;255;30;30m      [0m             at /rustc/fe5b13d681f25ee6474be29d748c65adcd91f69e/library/std/src/panicking.rs:702:17
[38;2;255;30;30m      [0m   9: std::panicking::begin_panic_handler::{{closure}}
[38;2;255;30;30m      [0m             at /rustc/fe5b13d681f25ee6474be29d748c65adcd91f69e/library/std/src/panicking.rs:588:13
[38;2;255;30;30m      [0m  10: std::sys_common::backtrace::__rust_end_short_backtrace
[38;2;255;30;30m      [0m             at /rustc/fe5b13d681f25ee6474be29d748c65adcd91f69e/library/std/src/sys_common/backtrace.rs:138:18
[38;2;255;30;30m      [0m  11: rust_begin_unwind
[38;2;255;30;30m      [0m             at /rustc/fe5b13d681f25ee6474be29d748c65adcd91f69e/library/std/src/panicking.rs:584:5
[38;2;255;30;30m      [0m  12: core::panicking::panic_fmt
[38;2;255;30;30m      [0m             at /rustc/fe5b13d681f25ee6474be29d748c65adcd91f69e/library/core/src/panicking.rs:143:14
[38;2;255;30;30m      [0m  13: core::result::unwrap_failed
[38;2;255;30;30m      [0m             at /rustc/fe5b13d681f25ee6474be29d748c65adcd91f69e/library/core/src/result.rs:1785:5
[38;2;255;30;30m      [0m  14: core::result::Result<T,E>::unwrap
[38;2;255;30;30m      [0m             at /rustc/fe5b13d681f25ee6474be29d748c65adcd91f69e/library/core/src/result.rs:1078:23
[38;2;255;30;30m      [0m  15: zellij_server::wasm_vm::wasm_thread_main
[38;2;255;30;30m      [0m             at /windows/Programming/pull_requests/zellij/zellij-server/src/wasm_vm.rs:145:25
[38;2;255;30;30m      [0m  16: zellij_server::init_session::{{closure}}
[38;2;255;30;30m      [0m             at /windows/Programming/pull_requests/zellij/zellij-server/src/lib.rs:713:21
[38;2;255;30;30m      [0m  17: std::sys_common::backtrace::__rust_begin_short_backtrace
[38;2;255;30;30m      [0m             at /rustc/fe5b13d681f25ee6474be29d748c65adcd91f69e/library/std/src/sys_common/backtrace.rs:122:18
[38;2;255;30;30m      [0m  18: std::thread::Builder::spawn_unchecked_::{{closure}}::{{closure}}
[38;2;255;30;30m      [0m             at /rustc/fe5b13d681f25ee6474be29d748c65adcd91f69e/library/std/src/thread/mod.rs:498:17
[38;2;255;30;30m      [0m  19: <core::panic::unwind_safe::AssertUnwindSafe<F> as core::ops::function::FnOnce<()>>::call_once
[38;2;255;30;30m      [0m             at /rustc/fe5b13d681f25ee6474be29d748c65adcd91f69e/library/core/src/panic/unwind_safe.rs:271:9
[38;2;255;30;30m      [0m  20: std::panicking::try::do_call
[38;2;255;30;30m      [0m             at /rustc/fe5b13d681f25ee6474be29d748c65adcd91f69e/library/std/src/panicking.rs:492:40
[38;2;255;30;30m      [0m  21: __rust_try
[38;2;255;30;30m      [0m  22: std::panicking::try
[38;2;255;30;30m      [0m             at /rustc/fe5b13d681f25ee6474be29d748c65adcd91f69e/library/std/src/panicking.rs:456:19
[38;2;255;30;30m      [0m  23: std::panic::catch_unwind
[38;2;255;30;30m      [0m             at /rustc/fe5b13d681f25ee6474be29d748c65adcd91f69e/library/std/src/panic.rs:137:14
[38;2;255;30;30m      [0m  24: std::thread::Builder::spawn_unchecked_::{{closure}}
[38;2;255;30;30m      [0m             at /rustc/fe5b13d681f25ee6474be29d748c65adcd91f69e/library/std/src/thread/mod.rs:497:30
[38;2;255;30;30m      [0m  25: core::ops::function::FnOnce::call_once{{vtable.shim}}
[38;2;255;30;30m      [0m             at /rustc/fe5b13d681f25ee6474be29d748c65adcd91f69e/library/core/src/ops/function.rs:227:5
[38;2;255;30;30m      [0m  26: <alloc::boxed::Box<F,A> as core::ops::function::FnOnce<Args>>::call_once
[38;2;255;30;30m      [0m             at /rustc/fe5b13d681f25ee6474be29d748c65adcd91f69e/library/alloc/src/boxed.rs:1861:9
[38;2;255;30;30m      [0m      <alloc::boxed::Box<F,A> as core::ops::function::FnOnce<Args>>::call_once
[38;2;255;30;30m      [0m             at /rustc/fe5b13d681f25ee6474be29d748c65adcd91f69e/library/alloc/src/boxed.rs:1861:9
[38;2;255;30;30m      [0m      std::sys::unix::thread::Thread::new::thread_start
[38;2;255;30;30m      [0m             at /rustc/fe5b13d681f25ee6474be29d748c65adcd91f69e/library/std/src/sys/unix/thread.rs:108:17
[38;2;255;30;30m      [0m  27: <unknown>
[38;2;255;30;30m      [0m  28: clone
[38;2;255;30;30m      [0m
[38;2;106;159;181m  help: [0mIf you are seeing this message, it means that something went wrong.
        Please report this error to the github issue.
        (https://github.com/zellij-org/zellij/issues)
        
        Also, if you want to see the backtrace, you can set the `RUST_BACKTRACE` environment variable to `1`.
        

So I'm wondering which steps I'm missing. To sum my steps up:

  1. Add actions in zellij/zellij-utils/src/input/actions.rs
  2. Add screen instruction (and screen context) in zellij/zellij-server/src/screen.rs.
  3. Adjusted zellij/zellij-utils/assets/config/default.yaml

TornaxO7 avatar Sep 04 '22 11:09 TornaxO7

Since the error occurs in wasm_vm.rs, it seems to be related to plugins. I guess it's a problem with default-plugins/tab-bar.

I don't know how far you've been working on it, so I'm assuming a few situations.

  1. If the tab is moved, it is also related to the rendering of the tab-bar. Therefore, the plugin may need to be modified.
  2. If you have already changed the plugin, it may be an error caused by the changed plugin not being loaded.

For example:

# custom.yaml
---
template:
  direction: Horizontal
  parts:
    - direction: Vertical
      borderless: true
      split_size:
        Fixed: 1
      run:
        plugin:
          location: "file:target/wasm32-wasi/debug/tab-bar.wasm"
    - direction: Vertical
      body: true
    - direction: Vertical
      borderless: true
      split_size:
        Fixed: 2
      run:
        plugin:
          location:  "file:target/wasm32-wasi/debug/status-bar.wasm"
tabs:
  - direction: Vertical

and start zellij with layout options ./target/debug/zellij -l custom.yaml

jaeheonji avatar Sep 04 '22 15:09 jaeheonji

If the tab is moved, it is also related to the rendering of the tab-bar. Therefore, the plugin may need to be modified.

ooof... ok, that should be the reason

TornaxO7 avatar Sep 04 '22 17:09 TornaxO7

@jaeheonji I'm sorry for the late reply but may I ask you what your intention is with that custom.yaml? Should that help me to find the bug?

TornaxO7 avatar Oct 03 '22 21:10 TornaxO7

It's okay. I was also busy. My intention is that if you modify the plugin code, in order to test the modified plugin, you have to make a custom.yaml file and test it as above. (The key is the location of the plugin item.)

But, unless you modified the plugin, it's not important.

jaeheonji avatar Oct 04 '22 06:10 jaeheonji

I haven't modified any plugin yet because I'm bit overhelmed by the plugins where I should start with xD

TornaxO7 avatar Oct 04 '22 12:10 TornaxO7

Do you have any tips how I can approach this?

TornaxO7 avatar Oct 04 '22 12:10 TornaxO7

@TornaxO7 Is there an error in the draft code you uploaded? Then, I will get the code and check it out. But I'm busy until this week, so please understand even if it takes a little time!

jaeheonji avatar Oct 05 '22 07:10 jaeheonji

@TornaxO7 Is there an error in the draft code you uploaded? Then, I will get the code and check it out.

Yes, the draft includes the current code, thank you for willing to try it out :)

TornaxO7 avatar Oct 05 '22 21:10 TornaxO7

All you need to do is adding the following keybinding:

keybinds:
    unbind: true
    normal:
        - action: [MoveTab: Left]
          key: [Char: 'H`]
        # and the rest of your config

TornaxO7 avatar Oct 05 '22 21:10 TornaxO7

any progress on this feature?? When will this feature be added?? I hope i had some knowledge on rust so i could help you with this feature but i am a beginner 💗.

theSafdarAwan avatar Apr 21 '23 16:04 theSafdarAwan

Hi! I'm sorry, but I I don't have the time and motivation at the moment to continue my PR. Feel free to replace my PR.

TornaxO7 avatar Apr 21 '23 17:04 TornaxO7

tmux is a mess to config, but this one feature is the sole reason why I still can't switch to zellij. Having un-movable tabs is a total deal-breaker. Is there really no workaround?

janos-r avatar Oct 16 '23 17:10 janos-r

I'm using zellij on a daily basis and I would love to have this feature - "Reorganizing order of tabs I already opened"

jamiecha avatar Nov 22 '23 01:11 jamiecha

This is my workaround until this feature is implemented

I have missed this feature a couple of times when I accidentally have deleted a tab (happened today). It's important for me that the tabs are in the correct order because that's how I've had it in Tmux for 15 years and it's in the muscle memory.

When creating a new Tab in Zellij, it ends up to the right of the other tabs and this is how I fix it.

  1. dump the layout for the connected session (my-session)
    zellij action dump-layout > $HOME/my-layout.kdl
    
  2. edit the layout (move tab)
    vim $HOME/my-layout.kdl
    
  3. open a new terminal and create a new temporary session with the newly edited layout and verify the result
    zellij -s test --layout=$HOME/my-layout.kdl
    
  4. If everything looks ok then delete the old session (be aware that the resurrection will also be deleted)
    zellij delete-session my-session --force
    
  5. create the session again with the new layout
    zellij -s my-session --layout=$HOME/my-layout.kdl
    

merikan avatar Dec 20 '23 09:12 merikan

Hi. I implemented the feature here.

Demo of current implementation:

  • first I'm changing the tab name
  • then showing the contents of all tabs
  • then moving the tab around
  • again showing contents of all tabs
  • again some moving around

zellij-tabs-showcase.webm

Edit: Demo of more complex scenarios:

zellij-tabs-complex-showcase.webm

devzbysiu avatar Dec 31 '23 14:12 devzbysiu

The feature was implemented in released in v0.40.1. Use alt-i and alt-o to move tabs around.

Not my work, just here for people to discover the default keybindings.

danielfleischer avatar Jul 04 '24 07:07 danielfleischer

OMG. There is no indicator of this. Thanks for the pointer to that, @danielfleischer You would think this would be much more widely disclosed :)

Daemoen avatar Jul 08 '24 19:07 Daemoen