Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

integration with clink #941

Open
wincmd64 opened this issue Sep 10, 2024 · 8 comments
Open

integration with clink #941

wincmd64 opened this issue Sep 10, 2024 · 8 comments
Labels
enhancement New feature or request windows Windows specific problem

Comments

@wincmd64
Copy link

I already asked the neighbors, but they sent me to you :)

How can I make broot work in cmd+clink ?

@wincmd64 wincmd64 added the enhancement New feature or request label Sep 10, 2024
@Canop Canop added the windows Windows specific problem label Sep 10, 2024
@Canop
Copy link
Owner

Canop commented Sep 10, 2024

As the problem is specific to Windows (more specifically to the old CMD.exe), I'd like a Windows user to investigate this.

But I'm affraid that if clink uses the old CMD, which doesn't support terminal functions, then it won't support broot (or any TUI).

@wincmd64
Copy link
Author

no, clink works fine in WT

@oletf
Copy link

oletf commented Sep 17, 2024

I wanted to have it working some time ago, had to use a temporary file, don't even remember what it does but it works, and I've been using it since then...
Probably not the best way to do it, I have no experience in lua, nor the clink scripting API

Here's what I have in %LOCALAPPDATA%\clink\br.lua :

local function onfilterinput(text)
    args = string.explode(text, ' ', '"')
    
    if #args == 0 then
        return
    end

    if args[1] == "br" then
        local command
        local tmpoutfile_name = os.tmpname()
        local tmpoutfile = io.open(tmpoutfile_name, 'w+')
        tmpoutfile:close()

        table.remove(args, 1)
        br_args = table.concat(args, ' ')

        local br_command = string.format('broot --outcmd "%s" %s', tmpoutfile_name, br_args)
        local broot_out_file = io.popen(br_command, 'r')
        local broot_out = broot_out_file:read('*all')
        broot_out_file:close()

        tmpoutfile = io.open(tmpoutfile_name, 'r')
        local cd_command = tmpoutfile:read('*all')
        tmpoutfile:close()

        os.remove(tmpoutfile_name)

        return cd_command
    else
        return
    end
end


if clink.onfilterinput then
    clink.onfilterinput(onfilterinput)
else
    clink.onendedit(onfilterinput)
end

clink.argmatcher("br"):addarg(clink.dirmatches)

Lmk if it helps, would be glad to have it made clean by someone who knows how all this works 😄

@chrisant996
Copy link

As the problem is specific to Windows (more specifically to the old CMD.exe), I'd like a Windows user to investigate this.

But I'm affraid that if clink uses the old CMD, which doesn't support terminal functions, then it won't support broot (or any TUI).

CMD is a shell, not a terminal.
CMD is unrelated to support for ANSI escape codes.
Just like how xterm is what provides terminal support, not bash.

Windows 10 and newer have terminal support built in. And Clink happens to include a terminal emulator for when it runs on Windows 8.1 and older.

@oletf
Copy link

oletf commented Sep 17, 2024

The lua script I use and have shared above was just me trying to port the broot bash function to clink's lua,
to have it work at least in Windows Terminal, it works well enough for me at least (and I just checked it works as well on legacy cmd+clink (only tested on Windows 10)).

I made it in lua with clink tools because I didn't want to try scripting this in batch like it has been done for Powershell, because well...it's batch, and I thought it'd be more comfortable to write in lua, also to have clink highlighting it and have completion support for it.

It might be possible to write the equivalent of what I did in lua in pure batch just for the br shell function, might try later at some point if I'm bored...

As you said CMD is a shell and not a terminal,
so I agree that the whole problem does not have anything to do with clink, which I just used here as a support for scripting (and which probably helps to add terminal functions with its emulator to have broot work in legacy CMD).

@chrisant996
Copy link

would be glad to have it made clean by someone who knows how all this works

@oletf the Lua script is very readable, and it looks pretty clean (both from a Lua perspective and from a Clink perspective).

Two minor suggestions:

  1. Use local to declare args, so that it doesn't leak into the global namespace.
-    args = string.explode(text, ' ', '"')
+    local args = string.explode(text, ' ', '"')
  1. The else return part can be removed. There is nothing wrong with including it, but Lua functions automatically return when they reach the end, so an explicit return at the end of a function is unnecessary.
         return cd_command
-    else
-        return
     end
 end

Input filtering in Clink can let simple cases work, but not the following kinds of usage:

  • somecommand & br blah
  • >outfile br blah

and which probably helps to add terminal functions with its emulator to have broot work in legacy CMD

On Win8.1 and lower, things like ConEmu or AnsiCon could be used to add terminal support into Windows consoles.

It might be possible to write the equivalent of what I did in lua in pure batch just for the br shell function

It looks pretty straightforward. Redirect output from broot to a tempfile (the hardest part is just picking a unique tempfile name in batch), then use for to read the output, then use the output.

(I don't know what broot actually does, but from context I gather maybe it's a tool for changing the current directory, similar to z or zoxide or cddeluxe and etc.)

@Canop
Copy link
Owner

Canop commented Sep 17, 2024

(I don't know what broot actually does, but from context I gather maybe it's a tool for changing the current directory, similar to z or zoxide or cddeluxe and etc.)

It's a TUI file explorer, command launcher, etc. and one of its features is that indeed it lets you change the current directory, which involves calling cd after end.

(see https://dystroy.org/broot/ if interested)

@chrisant996
Copy link

chrisant996 commented Sep 17, 2024

@Canop Thanks.

It looks like the only integration needed for use in cmd.exe is a br.cmd script to add --outcmd tmpfile and upon exit run the tmpfile. It seems like a 4 line script is almost sufficient, which is essentially the same as the bash br function:

br.cmd

@echo off
echo.>broot.tmp.cmd
broot --outcmd tmpfile.cmd %*
if not errorlevel 1 call broot.tmp.cmd

Except that something needs to be done to make a unique temp file name, so that multiple concurrent broot don't stomp on each other. One way to accomplish that could be to call PowerShell to get the cmd.exe parent process ID (and maybe append %random%, or get %time% and convert the : to _ and append that). Since it's a br.cmd file, it's guaranteed that cmd.exe is running it, so the parent process will indeed be cmd.exe. The following outputs the parent process ID, and a for loop in the br.cmd script could read it:

powershell -NoProfile -Command "(Get-CimInstance -ClassName Win32_Process -Filter "ProcessId=`'$pid`'").ParentProcessId"

Credit: lit in answer on stack overflow.

Caution

I'm leaving out basic stuff: for example, of course add %TEMP%, and make sure %TEMP% is an actual directory, etc. I'm not writing the whole cmd shell integration, I'm just trying to point in the right direction so someone else can do it without necessarily having a lot of cmd experience.

The issue about terminal support isn't related to cmd -- it's instead related to what version of Windows is used. PowerShell and bash and etc have the same limitation as cmd when run in a legacy console (i.e. terminal) on Windows 8.1 or earlier. Mintty or ConEmu or AnsiCon are a few ways to have support for ANSI escape codes (i.e. "terminal support") on Windows 8.1 or earlier.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request windows Windows specific problem
Projects
None yet
Development

No branches or pull requests

4 participants