helix-editor / helix

A post-modern modal text editor.
https://helix-editor.com
Mozilla Public License 2.0
32.72k stars 2.41k forks source link

[Proposal] Buitin support for `Integrated Terminal` #1976

Open hh9527 opened 2 years ago

hh9527 commented 2 years ago

Nowadays, I switch to helix + Zellij (a modern tmux alternative) + Alacritty, the combo are very powerful.

But sometimes, I miss the time when I was using vscode (with vim extension). The Integrated Terminal feature is very useful.

What if we got an Integrated Terminal feature inside helix?

David-Else commented 2 years ago

Seems like a lot of effort for little gain. Surely it is the job of your terminal to be your terminal? Adding another terminal inside Helix seems a bit much. If your terminal software has Window management and tabs (like kitty) then you can do what you want? In kitty I just write little bash scripts to open workspaces setup how I want them.

I think I am the wrong audience for this, I tried tmux for a while and hated it, seems like a pointless idea. Remembering SSH sessions was cool, but why not just use a better terminal that does what you want? The author of Kitty has some good points on tmux and clones https://github.com/kovidgoyal/kitty/issues/391#issuecomment-638320745

Sorry to sound negative, if people want it then go for it! I just thought I would chime in with my personal opinion, people will have different views I am sure.

andreytkachenko commented 2 years ago

Neovim has integrated terminal and it is super useful to me both in toggle and float modes. It seems to me a good approach is not depend on some GUI terminal application (like kitty) and have everything you got used to have and do in any terminal emulator.

hh9527 commented 2 years ago

Neovim has integrated terminal and it is super useful to me both in toggle and float modes. It seems to me a good approach is not depend on some GUI terminal application (like kitty) and have everything you got used to have and do in any terminal emulator.

Yes, I do agree. I want integrated terminal too.

and @David-Else somehow, I agree with you about terminal multiplexer is hacky, so I don't want a tmux, nor zellij, I need an integrated terminal to play a role to support multi-pane/tab inside helix.

kirawi commented 2 years ago

This was discussed in the past on Matrix and there seems to be a desire to implement it, but it's pretty complicated and would take a lot of work.

archseer commented 2 years ago

A fully functioning xterm environment is a lot of work and slightly inefficient as pointed out by the comment above, we need to re-parse all possible terminal escape sequences and reinterpret them (https://github.com/alacritty/vte can help but that's just the parsing bits).

You're essentially building a virtual terminal that renders to a part of the application. It would be about as much work as rebuilding tmux/zellij in helix.

I'd be interested in a proposal/experiment that implements this but I don't intend to work on this feature any time soon: personally I just always use tmux so I don't have a lot of motivation to focus on this.

andreytkachenko commented 2 years ago

There is implemented terminal which can be included (with some code reduction, like vi mode etc.) - https://github.com/alacritty/alacritty/tree/master/alacritty_terminal

n0s4 commented 2 years ago

This would probably be quick to be made as a plugin, whenever plugin support is complete. It'd be a reasonable compromise; keeping the core from bloat whilst the people that really want it can just install it.

workingj commented 2 years ago

maybe look in to guake (linux) and conemu (win), those are configurable as drop down (quake style) consoles, hidden and only a shortcut away. following you to the active workspace and your cursor with multiple displays. even working well with i3 quite awesome dev tools in my opinion :> Edit: forgot to mention split views and tabs..

i3elj commented 2 years ago

I have to say that what made me happy about helix was it's non-bloated build. Maybe adding a built-in terminal it's a bit too much. I understand that this feature is useful, but I agree with @David-Else

Surely it is the job of your terminal to be your terminal? Adding another terminal inside Helix seems a bit much.

I just wanted to leave my comment here for you guys think about

hh9527 commented 2 years ago

If helix could work in client-server mode, each win/pane (include terminal) is a standalone client/process, share same server instance, same lsp server, same clipboard, and can communicate/cooperate with window manager(eg. wezterm) to provide interaction functions (eg. jumping to file, switching pane/tab). That would make sense, and no need for built-in terminals.

adamkpickering commented 2 years ago

I would really like this feature. This is the only thing that is keeping me from switching from neovim to helix.

I understand the argument that there are other tools that can be used to get helix and a terminal in the same window, but in different panes. This is very "Unix philosophy" thinking, and generally I'm a fan of it.

However, I want a setup that I can take to any OS, including config files, without having to worry about other tooling (as much as possible, since obviously LSP servers etc need to be installed separately). Recently I have had to do some dev work on Windows, and it has been impossible to bring the tmux + nvim setup I usually use on Linux to this environment. I have ended up setting neovim up with a toggle-able integrated terminal to fit this use case.

Also, an integrated terminal would be helpful once helix has a graphical mode. Without this, the user is left switching windows in order to get to a terminal - that seems like a bad user experience to me.

premell commented 2 years ago

I just want to quote a comment from the plugin discussion

I don't want to use anymore a text editor which relies for 95% on plugins to do the work. I think plugins, when overused like they are in Neovim world, are a total mess for the following reasons:

* UI/UX inconsistencies (between themselves and/or the editor)

* conflicting/overlapping features (between themselves and/or the editor)

* distribution and versioning problems (some plugins require the nightly version, some don't)

* a lot of copy/paste configuration that you see one time in your life and forget or don't understand anymore

* often are unreliable and become unmaintained or broken over time

To give plugins total freedom it's the easy path at first because you avoid the problem of designing a good set of APIs, but it's a road to hell.

One of my favorite things about Helix is that it includes quite a lot of functionality out of the box. One might see this as bloat, but honestly, something like vim feels way more bloated once you've added all plugins to achieve the same functionality. To have a terminal, fuzzy finder, file tree, lsp, snippets etc in vim it feels like something breaks every month.

I would guess around 80% of people want to have a integrated terminal (even if they dont use it all of the time). Also it is a standard feature in every modern editor, so I think it would be missed heavily by many people who use it daily.

i3elj commented 2 years ago

Is there anyone working on this? I would like to help if possible

wojpawlik commented 2 years ago

Could I configure fish to fg on ^Z? :think:

txtyash commented 1 year ago

Since adding a built-in terminal would be an overkill, resolving binding conflicts by looking at common applications would be a much better solution.

Zellij is obviously doing things right. Easier to press shortcuts instead of something like "Ctrl+Shift+`, etc. And it is modal so lesser area for conflicts. IG the problem lies in helix using the alt key as well. Super is left out which would be used by WMs.

Looking at all your points @hh9527:

kirawi commented 1 year ago

Adding support for Windows to zellij might be a more straightforward path.

txtyash commented 1 year ago

Could I configure fish to fg on ^Z? :think:

I have the same binding

dead10ck commented 1 year ago

Personally I don't think this belongs in core. The Unix philosophy is not hard and fast, as I think many people who use helix agree, but an entire terminal emulator and a text editor are about as orthogonal in functionality as it gets. This is the definition of bloat.

nezuo commented 1 year ago

I don't use helix because it has no integrated terminal. I'm very attached to the vscode workflow where I press a hotkey to create a terminal in the directory I'm working in. I could possibly replicate this workflow using other tools but I'm not aware of them and it would be convenient if it was built in. I would be fine if it was plugin feature but that seems like it is a far ways off.

ArikRahman commented 1 year ago

I would be fine prefixing all my commands with a :sh but that doesn't work for programs needing input. The videos presented in the documentation are also unfriendly, regarding on how to debug, which seemed to require the use of tmux as well.

xJonathanLEI commented 1 year ago

If even vim has this feature, it's probably not much of a bloat IMO.

xJonathanLEI commented 1 year ago

Sorry for spamming this thread, but I see tmux being suggested here as an alternative so I just wanna add my two cents as a heavy tmux user. I do everything inside tmux. I just attach to the tmux session right after SSH-ing into the machine, as this allows me to pick up my work anytime from another device very easily.

Personally, using tmux just for getting a terminal doesn't really work for me, as I already use <PREFIX> l for quickly switching between workspaces. Using tmux for simulating an integrated terminal would mean much more effort when switching between the 2 workspaces I'm working on at the same time, cuz I'll now have to actually look up that workspace window (instead of reflexively hitting <PREFIX> l), and actually also attach to the other workspace's "terminal window" first, just to set that terminal window as the "last window" so that I can use <PREFIX> l for getting into the terminal of that target workspace later on.

(A possible workaround for this is to put each workspace inside a tmux session instead of window, and use <PREFIX> L to switch between workspaces instead. However, this just throws the issue one level up and heavy users of tmux sessions are still screwed...)

That said, the neovim integrated terminal is far from perfect, and I actually indeed use tmux "just" for getting a terminal when I need to use it seriously. However, sometimes I just want to run a quick command (e.g. cargo clippy), and a quick and dirty terminal inside of the editor is very helpful without messing up my tmux window history.

Bugbert commented 1 year ago

Is there any idea on how this could be implemented? I was thinking it might be possible to use a pseudo terminal crate like portable-pty, turn it into a Document and use helix-veiw to display it.

adambubenicek commented 1 year ago

I would like to +1 @hh9527 comment - a client-server architecture would allow users seamlessly switch between helix and terminal windows. I think Kakoune has done this right:

With Kakoune, you can collaboratively edit the same file: all new windows created by the editor are clients, and can simultaneously modify the content of a file. As such, windows are fully under the control of your X11 window manager or can be managed in a single terminal through Kakoune's tmux support. - https://kakoune.org/

Because of this, they don't have to implement a full blown terminal emulator or even a window manager. All while users can move between their editor and terminal (and, of course, any other application like a web browser) with a single set of shortcuts.

theaungmyatmoe commented 1 year ago

+1 for that feature cuz it can be speed up my workflow out of the box.

I60R commented 1 year ago

I use neovim as terminal multiplexer in alacritty and it's very convenient. Why do I need tmux?

Also, integrated terminal could be reused to make text editor work as pager. Why do i need less?

lukepighetti commented 1 year ago

I don't think we should have an integrated terminal in Helix. There are too many good multiplexers out there. I see no point in adding the complexity to core.

xJonathanLEI commented 1 year ago

There are too many good multiplexers out there.

I use tmux and zellij a lot but I still want the integrated terminal.

IMO the point of an integrated terminal is that it's, well, integrated. It's not meant to be just another terminal.

For example, I can run a linter, get some warnings with file paths and line numbers. Then focus on the path, press gf and I get a buffer opened for that file (and even exactly at that line). This is not something a multiplexer can do. And this is just one example.

ksandvik commented 1 year ago

:sh that returns all the output to a scratch buffer, instead of the popup, ex sh cargo run, any interactivity is missing but at least unit tests and print output is shown. That might cover 80% of terminal needs. If the output is formatted like nushell, i.e structured return values, JSON and so on, even better. Then this could be handled intelligently by other helix core functions.

lukepighetti commented 1 year ago

There are too many good multiplexers out there.

I use tmux and zellij a lot but I still want the integrated terminal.

IMO the point of an integrated terminal is that it's, well, integrated. It's not meant to be just another terminal.

For example, I can run a linter, get some warnings with file paths and line numbers. Then focus on the path, press gf and I get a buffer opened for that file (and even exactly at that line). This is not something a multiplexer can do. And this is just one example.

Having trouble understanding your point. To me this feels like a use case for copying a linter warning file path and line number to system clipboard so it can be used outside Helix. But if there's a specific flow you can share to help me understand I would appreciate it.

RomeoV commented 1 year ago

Chiming in to mention that I love an integrated terminal in order to easily run a REPL. In Neovim, I like to open a terminal split and run a REPL there (say Python, Julia, etc.) Then I visual select some code, and use the NeoTerm plugin to paste the selection straight into the terminal/REPL. This is a very (for me) productive workflow, that seems to not be possible in helix.

archseer commented 1 year ago

There's a prototype PR draft so I don't think we need more convincing :) https://github.com/helix-editor/helix/pull/4649

Then I visual select some code, and use the NeoTerm plugin to paste the selection straight into the terminal/REPL.

You could use tmux splits, then space y / space p the code between the repl and the editor

goyalyashpal commented 1 year ago
debajyoti1990 commented 1 year ago

As a windows user, even I too think integrated terminal is not much worthy. Windows terminal will let you use tabs and splits. So for running code / REPL sort of things are easily addressed. Integrated terminal must be in the core if we ever get a GUI application in future.

goyalyashpal commented 1 year ago

Integrated terminal must be in the core if we ever get a GUI application in future.

u mean core as in

debajyoti1990 commented 1 year ago

Integrated terminal must be in the core if we ever get a GUI application in future.

u mean core as in technical name helix-core (the designated part of helix) or general core (i.e. just inbuilt)

I meant general core.

nathan-at-least commented 1 year ago

It seems clear from the discussion here that there are different groups of users with different environments and needs.

I'm in the tmux camp (and I'm zellij-curious). I always run hx within tmux. In fact, 99% of the terminals I ever open are running tmux. Because of this, reproducing the same functionality within hx has no appeal for me.

But, I can understand how users who don't use tmux or just a terminal with panes (like @david-else w/ kitty) would have this need. So… why not use tmux or zellij or kitty or some tool that provides exactly what you need?

For the record, I use a separate tmux session for every project I'm hacking on, and hx is in one of the screens. The sessions are started in the project directory, so if I need a new terminal in the project directory, it's a single tmux command. tmux can do pane layout, so I can show both hx and an interactive terminal session on the same screen. Since each project has a tmux session and I can close terminals and reattach later, or switch to different project sessions and the state (such as current directory) are specific to that project.

I simply can't see how hx could hope to reproduce all of that functionality. Would hx terminal support have sessions? Reattachment? Pane layouts? What would all the keybinds be? If it did have that functionality, what would I do if I needed that kind of functionality but I don't want to edit files (or run LSPs, etc…)? Then I'd have to reach for something like tmux anyway.

So, I'm firmly in the anti-terminal emulator camp, because I already have a tool that does this for me.

ArikRahman commented 1 year ago

I changed my mind on the topic, coming into ZelliJ. Realizing terminal functionality is a lot trickier to implement, especially one comparable with zellij, I've come to the conclusion that Helix has better things to worry about.

quantonganh commented 1 year ago

Although I like the Zellij's floating panes feature, I don't want to nest one more layer in my terminal. So, here's how I integrated WezTerm into Helix:

Firstly, I created a script to split WezTerm:

wezterm-split-pane.sh:

#!/bin/sh

pane_id=$(wezterm cli get-pane-direction down)
if [ -z "${pane_id}" ]; then
  pane_id=$(wezterm cli split-pane)
fi

wezterm cli activate-pane-direction --pane-id $pane_id down

Secondly, to run code in the newly created pane:

run.sh:

#!/bin/sh

source wezterm-split-pane.sh

program=$(wezterm cli list | awk -v pane_id="$pane_id" '$3==pane_id { print $6 }')
if [ "$program" = "lazygit" ]; then
  echo "q" | wezterm cli send-text --pane-id $pane_id --no-paste
fi

filename="$1"
basedir=$(dirname "$filename")
basename=$(basename "$filename")
basename_without_extension="${basename%.*}"
extension="${filename##*.}"

case "$extension" in
  "c")
    run_command="clang -lcmocka -lmpfr -Wall -O3 $filename -o $basedir/$basename_without_extension && $basedir/$basename_without_extension"
    ;;
  "go")
    run_command="go run $filename"
    ;;
  "scm"|"rkt")
    run_command="racket $filename"
    ;;
esac

echo "${run_command}" | wezterm cli send-text --pane-id $pane_id --no-paste
# wezterm cli activate-pane-direction up

And finally, I just added the following into the Helix config file (need this PR to expand filename):

[keys.normal.";"]
r = ":sh run.sh %val{filename} > /tmp/run.log 2>&1"

Now, I only need to press ;, followed by r to run my code.

For example, I can run a linter, get some warnings with file paths and line numbers. Then focus on the path, press gf and I get a buffer opened for that file (and even exactly at that line). This is not something a multiplexer can do. And this is just one example.

@xJonathanLEI WezTerm can do that:

config.hyperlink_rules = wezterm.default_hyperlink_rules()

table.insert(config.hyperlink_rules, {
  regex = '^/[^/\r\n]+(?:/[^/\r\n]+)*:\\d+:\\d+',
  format = "$0",
})
wezterm.on('open-uri', function(window, pane, uri)
  local user = os.getenv('USER')
  local start, _ = string.find(uri, '/Users/' .. user)
  if start == 1 then
    local direction = 'Up'
    local hx_pane = pane:tab():get_pane_direction(direction)
    if hx_pane == nil then
      local action = wezterm.action{
        SplitPane={
          direction = direction,
          command = { args = { 'hx', uri } }
        };
      };
      window:perform_action(action, pane);
    else
      local action = wezterm.action.SendString(':open ' .. uri .. '\r\n')
      window:perform_action(action, hx_pane);
    end
    -- prevent the default action from opening in a browser
    return false
  end
  -- otherwise, by not specifying a return value, we allow later
  -- handlers and ultimately the default action to caused the
  -- URI to be opened in the browser
end)
t-cadet commented 10 months ago

I think the real benefit of having a terminal in the editor is to be able to use all of the editor's actions & movements in the terminal.

Writing a small bash script and tweaking Helix's config, we can cover most of the above use case. Here is the result:

https://github.com/helix-editor/helix/assets/33122682/1a87227f-87f5-4f2f-8626-7f657f4695d8

Bash script

export TERM=xterm # disable color
export PAGER=""

if [ -e ~/.config/helix/exec.env ]; then
  source ~/.config/helix/exec.env 2> /dev/null
fi

if [ -e "$PWD" ]; then
  cd "$PWD"
else
  PWD=$(pwd)
fi

stdin=$(cat)
echo "$stdin"
echo
eval "$stdin"
echo '['"$PWD"']$'

env > ~/.config/helix/exec.env 2>/dev/null

Helix config:

[keys.insert]
C-t = ["extend_to_line_bounds", ":pipe sh ~/.config/helix/exec.sh 2>&1", "normal_mode", "open_below"]

[keys.normal]
C-t = ["extend_to_line_bounds", ":pipe sh ~/.config/helix/exec.sh 2>&1"]

[keys.select]
C-t = [":pipe sh ~/.config/helix/exec.sh 2>&1"]

This simple solution has issues, e.g. it isn't really interactive but just reports the output when the command ends, and it probably has a lot of other quirks (use at your own risk).

However in practice I find most shell commands end quickly so it's not much of an issue and the workflow seems "good enough" to be useful.

Reading through the thread it is not clear this proposition intends to enable Helix's movements & actions in the terminal, but I hope this is where it is headed.

Also (I am new to the topic but) rather than embedding a terminal in Helix, isn't possible to reuse Helix's parent terminal to execute commands and plug on its inputs/outputs?

PS: I couldn't map command execution on enter as I initially wanted (this would be annoying when typing text in insert mode in other buffers) which is slightly confusing. If anyone knows how to remap shortcuts on one buffer only I am interested.

gerion0 commented 6 months ago

Like already said here a few times, I think the real benefit of an integrated shell in comparison to a terminal multiplexer is an understanding of the editor for shell concepts:

This way, a user can scroll much more comfortable within the terminal and is able to select (and copy) conceptually belonging parts really fast (into a new buffer for example).

More interpretation is possible:

To prevent editorception, it would also be really handy, when a call of hx some/file would open the file in a new buffer of the editor itself and not in an editor within the editor.

Edit: I forgot: Open something in a helix buffer does not only affect calling hx directly but also every invocation of $EDITOR (like git commit) and should also be helpful for all usages of a pager (using terminal commands like less, man, systemctl status, ...)

willelind commented 6 months ago

After reading this thread I am surprised to see no one mention the ability to have all of your normal text manipulation bindings from the editor while still in the terminal. Extremely nice feature in my opinion.

And I also agree with the one commenter above that an integrated terminal avoids duplicated keybindings. Sure, you can rebind your multiplexer to not use the same keys for creating split windows as your editor, but you would still need to remember both keymaps and switch between them. It's vastly more efficient (from a keymap perspective) to have all of your keybindings inside the editor.

luccahuguet commented 2 months ago

hi, yazelix guy here

yazelix is a glorified config (that wanted to be a plugin) and it stabs at

Helix is nearing a plugin system release and Yazelix will change to accommodate that.

I probably won´t be writing any plugins myself but Yazelix is happy to work with or as part of file-tree helix plugins or integrated terminal plugins that arise

The important thing here is that everything works together nicely and integrated

DaniD3v commented 1 month ago

I really like jetbrains "Run Configurations", where I just need to press Ctrl-F10 and my projects gets run/tested and with Ctrl-F9 I can even bring up the debugger automatically.

That would honestly be my main use of a built in terminal. I could do something like this image

Having the terminal directly in the editor would allow e.g. jumping to file specified in the terminal output (see my cursor at the screenshot). Pressing gf on cargo output and going to the right file automatically sounds pretty nice.

I don't really know a lot about lsps or ansi escape codes but wouldn't it be possible to write an lsp that highlights ansi escape codes? If that wouldn't be possible with the current lsp protocol I'm sure we could just add a small extension.

That way we don't have to mess with the core code of helix + people that don't want the bloat could just not install the ansi-lsp.

That'd also allow us to write custom lsps for command line output. goto definition could work when cargo test fails running a test function. Not sure if that is really feasible considering how specific to programming languages the lsp protocol is.

ondrej-ivanko commented 1 month ago

Combining zellij with helix pretty much solves any issues regarding the terminal. Multiple tabs and popup panes(especially that) does solve all my concerns. Floating panes also allows automatic commands to be run.

adriangalilea commented 1 month ago

Combining zellij with helix pretty much solves any issues regarding the terminal. Multiple tabs and popup panes(especially that) does solve all my concerns. Floating panes also allows automatic commands to be run.

I disagree, it's still fragmented, buffers are different, edits on one pane need to be reloaded in the other one and so on. It seems good at first but you realise that it falls short and create other kinds of annoyances.

ondrej-ivanko commented 1 month ago

I disagree, it's still fragmented, buffers are different, edits on one pane need to be reloaded in the other one and so on. It seems good at first but you realise that it falls short and create other kinds of annoyances.

Have you tried Ctrl-t-s for complete tab synchronization and than splitting it to multiple panes? Than you can make changes in all panes/buffers at the same time. Hopefully that's the usecase you're looking for.

This setup can be built with customized layout and run on every zellij/shell startup.

TornaxO7 commented 1 month ago

I really like jetbrains "Run Configurations", where I just need to press Ctrl-F10 and my projects gets run/tested and with Ctrl-F9 I can even bring up the debugger automatically.

That would honestly be my main use of a built in terminal. I could do something like this image

Having the terminal directly in the editor would allow e.g. jumping to file specified in the terminal output (see my cursor at the screenshot). Pressing gf on cargo output and going to the right file automatically sounds pretty nice.

I don't really know a lot about lsps or ansi escape codes but wouldn't it be possible to write an lsp that highlights ansi escape codes? If that wouldn't be possible with the current lsp protocol I'm sure we could just add a small extension.

That way we don't have to mess with the core code of helix + people that don't want the bloat could just not install the ansi-lsp.

That'd also allow us to write custom lsps for command line output. goto definition could work when cargo test fails running a test function. Not sure if that is really feasible considering how specific to programming languages the lsp protocol is.

I've that in my workflow with zellij included:

image

You just need the EditScrollback action.

gerion0 commented 1 month ago

This is a good starting point, but Helix is not able to understand the scrollback, isn't it? So it does not get that "helix-term/src/commands.rs:104" does point to a line of the file that is opened on the left and it could directly jump there (additionally, the two Helix instances do not talk to each other).

Does zellij opens the whole scrollback in Helix or just the last command output (so is zellij able to interpret the prompt)? For example for C++ compiler output, it is a good rule of thumb to just handle the first error message given by the compiler so one need to jump the last prompt and scroll down from there on. Helix shouldn't be able to interpret the prompt, so the whole scrollback is only partially helpful here.

TornaxO7 commented 1 month ago

This is a good starting point, but Helix is not able to understand the scrollback, isn't it?

Yes.

So it does not get that "helix-term/src/commands.rs:104" does point to a line of the file that is opened on the left and it could directly jump there (additionally, the two Helix instances do not talk to each other).

No, but I don't mind. I just switch back to helix and open up the picker and go to the given line number.