Eugeny / tabby

A terminal for a more modern age
https://tabby.sh
MIT License
58.6k stars 3.37k forks source link

Making zmodem file transfers supports tmux. #5928

Closed lonnywong closed 2 years ago

lonnywong commented 2 years ago

Zmodem ( rz / sz ) is not compatible with tmux.

I make a new file transfer tools trzsz ( trz / tsz ), similar to lrzsz ( rz / sz ), and compatible with tmux.

Trzsz ( trz / tsz ) supports iTerm2, just for MacOS users.

And, I make trzsz.js for cross-platform terminal apps.

I think tabby can support trzsz. Maybe as a plugin?

Maybe I can write the plugin myself. But, I'm not familiar with tabby. How to filter the input and output of the server? Could the plugin access the file system by require('fs')? Could the plugin open electron dialog?

Eugeny commented 2 years ago

Hey, great work! Yes, plugins can interact with the built-in upload/download manager without having to require('fs'). This will even work in Tabby Web. Check out how the actual Zmodem transfers are implemented: https://github.com/Eugeny/tabby/blob/master/tabby-terminal/src/features/zmodem.ts

Also, I to am working on a better file transfer spec here: https://github.com/shift-protocol/spec - which supports directory transfers and is transparent to terminal multiplexers. Would appreciate any feedback!

GitHub
tabby/zmodem.ts at master · Eugeny/tabby
A terminal for a more modern age. Contribute to Eugeny/tabby development by creating an account on GitHub.
GitHub
GitHub - shift-protocol/spec: SHIFT Protocol Specification
SHIFT Protocol Specification. Contribute to shift-protocol/spec development by creating an account on GitHub.
lonnywong commented 2 years ago

Thanks. I'm trying to make the trzsz plugin. https://github.com/trzsz/tabby-trzsz

After I installed the tabby-trzsz plugin, tabby restart fails, same as https://github.com/Eugeny/tabby/issues/4916 .

The tabby version is 1.0.173.0.

[19520:0313/215458.059:ERROR:node_bindings.cc(242)] Error parsing Node.js cli flags
[Glasstron/DWM] Trying to load the native module...
[Glasstron/DWM] Native module loaded
[19520:0313/215500.066:ERROR:CONSOLE(1)] "Uncaught TypeError: Cannot read properties of undefined (reading 'instance')", source: devtools://devtools/bundled/devtools_app.html?remoteBase=https://chrome-devtools-frontend.appspot.com/serve_file/@94ee59176aed5cdb90322df635ab5ca7d4cfcc3f/&can_dock=true&toolbarColor=rgba(223,223,223,1)&textColor=rgba(0,0,0,1)&experiments=true (1)
(node:18476) [DEP0005] DeprecationWarning: Buffer() is deprecated due to security and usability issues. Please use the Buffer.alloc(), Buffer.allocUnsafe(), or Buffer.from() methods instead.
(Use `Tabby --trace-deprecation ...` to show where the warning was created)
Checking for update
Update for version 1.0.173 is not available (latest version: 1.0.173, downgrade is disallowed).

Is npm i -D tabby-core cause the issue?

"tabby-core": "^1.0.171-nightly.3"
Eugeny commented 2 years ago

It's possible that an exception is swallowed somewhere during plugin initialization. You can add "--inspect-brk" to the Tabby command line, and then you'll be able to debug the main process through the NodeJS inspector, e.g. by opening chrome://inspect in your local Chrome.

lonnywong commented 2 years ago

Oh, run with --debug, There are some error in the console.

ERROR TypeError: Class constructor ToolbarButtonProvider cannot be invoked without 'new'
    at new MyButtonProvider
    function MyButtonProvider() {
        return _super !== null && _super.apply(this, arguments) || this;
    }

Maybe I didn't build the example right. https://github.com/Eugeny/tabby/blob/master/HACKING.md

import { NgModule, Injectable } from '@angular/core'
import { ToolbarButtonProvider, ToolbarButton } from 'tabby-core'

@Injectable()
export class MyButtonProvider extends ToolbarButtonProvider {
    provide (): ToolbarButton[] {
        return [{
            icon: 'star',
            title: 'Foobar',
            weight: 10,
            click: () => {
                alert('Woohoo!')
            }
        }]
    }
}

@NgModule({
    providers: [
        { provide: ToolbarButtonProvider, useClass: MyButtonProvider, multi: true },
    ],
})
export default class MyModule { }

The build result:

var MyButtonProvider = /** @class */ (function (_super) {
    __extends(MyButtonProvider, _super);
    function MyButtonProvider() {
        return _super !== null && _super.apply(this, arguments) || this;
    }
    MyButtonProvider.prototype.provide = function () {
        return [
            {
                icon: "star",
                title: "Foobar",
                weight: 10,
                click: function () {
                    alert("Woohoo!");
                }
            },
        ];
    };
    MyButtonProvider = __decorate([
        (0, core_1.Injectable)()
    ], MyButtonProvider);
    return MyButtonProvider;
}(tabby_core_1.ToolbarButtonProvider));
exports.MyButtonProvider = MyButtonProvider;
var MyModule = /** @class */ (function () {
    function MyModule() {
    }
    MyModule = __decorate([
        (0, core_1.NgModule)({
            providers: [
                { provide: tabby_core_1.ToolbarButtonProvider, useClass: MyButtonProvider, multi: true },
            ]
        })
    ], MyModule);
    return MyModule;
}());
exports["default"] = MyModule;
Eugeny commented 2 years ago

You're transpiling classes into function - since you didn't set the "target" in tsconfig.json it's compiling into es6 (IIRC). Check out tsconfig.json that's used in the sample plugin (tabby-clippy), it's using target: es2016

lonnywong commented 2 years ago

You're transpiling classes into function - since you didn't set the "target" in tsconfig.json it's compiling into es6 (IIRC). Check out tsconfig.json that's used in the sample plugin (tabby-clippy), it's using target: es2016

Thanks @Eugeny , you saved me a lot of time.

After I published a new version, how long will it take to be updated? Seems like tabby always shows the old version.

Eugeny commented 2 years ago

Have you tried restarting Tabby already? It's pulling fresh info from NPM when you open the Plugins tab for the first time.

lonnywong commented 2 years ago

Yes, I restart tabby several times, and always shows the old version.

lonnywong commented 2 years ago

I reboot my computer, and it's still shows the old version. I try to install the plugin, it downloads the 0.1.0 version.

https://www.npmjs.com/package/tabby-trzsz is 0.1.1 35 minutes ago.

npm
tabby-trzsz
Supports trzsz ( trz / tsz ), which similar to rz / sz, and compatible with tmux.. Latest version: 0.1.1, last published: 36 minutes ago. Start using tabby-trzsz in your project by running `npm i tabby-trzsz`. There are no other projects in the npm registry using tabby-trzsz.
lonnywong commented 2 years ago

It works now after restart. Maybe we need to wait a few hours.

lonnywong commented 2 years ago

@Eugeny Please help. Thanks.

  1. How to disable showing the server output temporary? terminal.enablePassthrough = false seems not working.
  2. How to disable the user input while there are files transferring?
  3. Can you help me review the code? https://github.com/trzsz/tabby-trzsz/blob/main/src/decorator.ts It works except the server output and user input. Am I doing subscribeUntilDetached right?
Eugeny commented 2 years ago
  1. Are you sure this condition (https://github.com/trzsz/tabby-trzsz/blob/main/src/decorator.ts#L20) is correct? When passthrough is off, you're still writing the output to the terminal yourself.
  2. This is not possible with just a decorator, but your can write a Middleware that has complete control over the session data in both directions.

Create a subclass of SessionMiddleware, override its feedFromTerminal method, and push an instance of the middleware onto the stack. You can also move the Trzsz logic itself into the middleware as well and only keep attach/detach logic in the decorator.

  1. You should move all your subscribeUntilDetached calls (except terminal.sessionChanged$ which should be permanently subscribed) into attachToSession - otherwise the plugin will stop working when the active session in the tab changes (e.g. after an SSH reconnect). See how it's done in zmodem. The code looks good otherwise :+1:
GitHub
tabby-trzsz/decorator.ts at main · trzsz/tabby-trzsz
Tabby plugin supports trzsz ( trz / tsz ), which similar to rz / sz, and compatible with tmux. - tabby-trzsz/decorator.ts at main · trzsz/tabby-trzsz
lonnywong commented 2 years ago

Thanks for your help.

  1. I write a text progress bar to the terminal while passthrough is off.
  2. Let me try to use SessionMiddleware.
  3. Is terminal.resize$ not related to a session? Same as the cancelEvent. I'm a little confused.
Eugeny commented 2 years ago
  1. I've found the problem! It was due to incorrect handling in the actual zmodem decorator - it was relying on enablePassthrough instead of having its own "active" state - fixed in https://github.com/Eugeny/tabby/commit/780691413d6ec0fa82c591e51c2355d89d33e7dc - new build coming in https://github.com/Eugeny/tabby/actions/runs/2008672903

  1. Sorry - ignore that - you're correct to subscribe to non-session events in attach()
GitHub
fixed incorrect passthrough handling in zmodem · Eugeny/tabby@7806914
A terminal for a more modern age. Contribute to Eugeny/tabby development by creating an account on GitHub.
lonnywong commented 2 years ago

Can I just push a SessionMiddleware without remove?

Please help me review the code: https://github.com/trzsz/tabby-trzsz/tree/main/src

It works, but I don't know if there will be an issue in some cases.

GitHub
tabby-trzsz/src at main · trzsz/tabby-trzsz
Tabby plugin supports trzsz ( trz / tsz ), which similar to rz / sz, and compatible with tmux. - tabby-trzsz/src at main · trzsz/tabby-trzsz
Eugeny commented 2 years ago

Yes - looks great! :+1: You don't need to remove the middleware because decorators never get detached until the tab is closed.

lonnywong commented 2 years ago

@Eugeny Thank you again for helping me.

lonnywong commented 2 years ago

It works. https://github.com/trzsz/tabby-trzsz

GitHub
GitHub - trzsz/tabby-trzsz: Tabby plugin supports trzsz ( trz / tsz ), which similar to rz / sz, and compatible with tmux.
Tabby plugin supports trzsz ( trz / tsz ), which similar to rz / sz, and compatible with tmux. - GitHub - trzsz/tabby-trzsz: Tabby plugin supports trzsz ( trz / tsz ), which similar to rz / sz, and...