Giter Site home page Giter Site logo

Comments (54)

ShaneDelmore avatar ShaneDelmore commented on May 3, 2024

+1 I would actually love to be able to use an embedded shell without having to run in the terminal. I'm using tmux + vim right now but I would prefer to use a gui vim in many cases if it had an embedded shell.

from neovim.

andrewrk avatar andrewrk commented on May 3, 2024

What's the point? Should we also embed a web browser and video encoding library?

from neovim.

mdenchev avatar mdenchev commented on May 3, 2024

Wouldn't this be doable as a plugin or in the GUI on top of neovim? No point adding it in the core process.

from neovim.

tarruda avatar tarruda commented on May 3, 2024

I'm also interested in this, currently I use tmux + vim but better integration between the editor and the terminal would certainly be welcome, but I dont think that should be something hardcoded into the editor.

@aughblegh as @mdenchev stated, this will be possible with plugins and I bet it will be responsive, because unlike vim, neovim will run plugins in separate processes that can do asynchronous UI updates.

When the first iteration is complete, you can even try to adapt 'st' source code into a plugin that sends UI updates to neovim instead of drawing to a X server.

from neovim.

felipecrv avatar felipecrv commented on May 3, 2024

I would prioritize like this: terminal > browser > video encoding.

If vim had an embedded shell, I would stop using text based vim + tmux and
use the GUI version instead.

Learning 2 sets of navigation shortcuts is not good.
On Feb 22, 2014 5:28 PM, "Ben Klein" [email protected] wrote:

What's the point? Should we also embed a web browser and video encoding
library?

Yes we should.

Sent from my iPhone

Reply to this email directly or view it on GitHubhttps://github.com//issues/51#issuecomment-35813690
.

from neovim.

trusktr avatar trusktr commented on May 3, 2024

Yes. Using vim split windows as terminal emulators would be very nice.

from neovim.

adelarsq avatar adelarsq commented on May 3, 2024

There have been some attempts to do this, like https://github.com/rosenfeld/conque-term. But none works as expected. Would be good to bring some support for this.

from neovim.

PhilipDaniels avatar PhilipDaniels commented on May 3, 2024

Probably worth mentioning, in the spirit of learning from what has gone before, that Emacs has "comint" mode. Comint stands for command interpreter, and is a base mode for interacting with subprocesses (Think: tie their stdin/stdout to a buffer). It's used to build shell support and as a basis for modes that need a REPL. GUD is based on it, for example.

http://www.masteringemacs.org/articles/2010/11/01/running-shells-in-emacs-overview/

I was thinking of trying to port GUD to neovim, but I have a couple of other projects I need to put to bed first.

from neovim.

tarruda avatar tarruda commented on May 3, 2024

@PhilipDaniels Not sure if you are aware, but we already have job control. If we provided an option to open jobs with stdin/stdout/stderr connected to pseudo terminals, would that be enough to implement an efficient "comint mode" in Neovim?

from neovim.

Shougo avatar Shougo commented on May 3, 2024

Hi, I have created terminal emulator plugins(vimshell) in VimL.

I think this is not neovim's feature.
Although, neovim should provide features to implement it by neovim plugins.

If we provided an option to open jobs with stdin/stdout/stderr connected to pseudo terminals, would that be enough to implement an efficient "comint mode" in Neovim?

I think Yes.

I want to create new shell and terminal emulator plugin for neovim.

from neovim.

trusktr avatar trusktr commented on May 3, 2024

Considerations: the plugin (and neovim API) should allow for all keystrokes to be sent to jobs (e.g. a terminal) running in a window. Neovim should have something similar to tmux's "prefix" key that would allow you to escape from a job (terminal) using a second key press after the prefix key press, at which point the window buffer stops being updated by the job (the job can continue to run in the background, but the buffer doesn't update) and you then can interact with the buffer just like any you do with any other vim buffer (visually select things, yank, delete, insert, run commands, etc). A command can be used to return to the job, at which point the buffer gets updated back to the state it was in right before you escaped from the job. The command could be :jobenter or something similar.

That'd be powerful. And yes, when you've escaped from the job you can freely modify the job buffer so that you can i.e. format something before copying it to paste it online, etc. When you return to the job the buffer goes back to the state it was in right before you escaped.

For example, while in a job, pressing <prefix> and then <c-w> can give you access to the window commands to be able to move to another window and so that the job's buffer continues to be updated while you're in the other window. If you go back to the job window then do n you can go to NORMAL mode (you've escaped from the job) and start doing normal vim things. While in a job, you could do <prefix>i to go straight into INSERT mode (you've escaped from the job), or <prefix>: to go into command mode. In command mode, the job buffer will continue to update (you have't not escaped from the job), and if you leave command mode, you go back to the job, not back to NORMAL mode like you would in non-job buffers.

The prefix key might be <c-o> similar to how <c-o> let's you escape out of INSERT for a moment.

We should theoretically be able to run any number of console neovims inside a GUI or console neovim in which case you'd have to press the prefix key an extra time for it to work if you're in the inner neovim (or more times depending how recursive you like to be). It'd be convenient to some for neovim to be able to distinguish when it's running inside another neovim (e.g. perhaps a is_nested variable) so that vimrc can have certain settings for the outer neovim and certain settings for the inner neovim (i.e. the outer neovim settings cater to a terminal-multiplexer configuration, and the inner settings cater to text editing).

How about that, eh? :D

from neovim.

ZyX-I avatar ZyX-I commented on May 3, 2024

Considerations: the plugin (and neovim API) should allow for all keystrokes to be sent to jobs (e.g. a terminal) running in a window. Neovim should have something similar to tmux's "prefix" key that would allow you to escape from a job (terminal) using a second key press after the prefix key press, at which point the window buffer stops being updated by the job (the job can continue to run in the background, but the buffer doesn't update) and you then can interact with the buffer just like any you do with any other vim buffer (visually select things, yank, delete, insert, run commands, etc). A command can be used to return to the job, at which point the buffer gets updated back to the state it was in right before you escaped from the job. The command could be :jobenter or something similar.

That'd be powerful. And yes, when you've escaped from the job you can freely modify the job buffer so that you can i.e. format something before copying it to paste it online, etc. When you return to the job the buffer goes back to the state it was in right before you escaped.

No, that is not powerful. I do not think that in the state you describe it is worth bothering: better approach is allowing to define ones own modes.

Each new mode has the following properties:

  1. Identifier of some kind. Should be used to create mappings.
  2. A set of built-in commands.
  3. A function that is responsible for processing all input that was not caught by some command from 2. E.g. in insert mode it is β€œwrite to buffer”, in normal it is β€œbell”, etc. Defaults to bell.

One word about 2.: there is <C-\><C-n> command in all modes that allows escaping to normal mode from any other mode. I think that this command should be forced in 2. (i.e. not allowed to be redefined), but still remappable (as it is now).

Reasoning: there is a number of plugins like Command-T that create their own mode, but they use more or less hacky solutions. And yet they run completely in Vim: no external jobs. They also do not require escaping to normal or command mode.

In addition to this there should be an API useful to update any buffer, not necessary current. Python in Vim already has one, do not know about Neovim.


I do not see how nesting neovims can be useful.

from neovim.

trusktr avatar trusktr commented on May 3, 2024

@ZyX-I We agree on the main point: there would need to be a way to enter and leave the job mode (sure, it can be a custom mode) and <c-\><c-n> would be fine for leaving while all other keystrokes are sent to the job. <c-\><c-\> can be used to send <c-\> to the job when needed. I actually didn't know about <c-\><c-n> until just now, but that works, and we shall be able to map it to whatever key we want.

I do not see how nesting neovims can be useful.

If neovim-core runs as a server, then each embedded neovim can share the same buffers, session, etc, etc. The outer neovim can be configured with no tabline, no status line, etc, so that its space is maximized for terminal multiplexing, while inner neovims can have the bells an whistles like tablines, status lines, NERDtree buffer, etc. It might not be useful to you, but it might be to someone else. I'm just imagining possible scenarios. Plus I wouldn't want to quit the outer neovim just to open a new session for a new project. I might want to keep terminals around, but begin work on another project, in which case loading a session with my tabs and windows in an inner neovim makes sense. There are lots of possibilities with this feature.

I intend to replace tmux with neovim when neovim has this capability.

from neovim.

adelarsq avatar adelarsq commented on May 3, 2024

Will be possible for neovim buffers to work like a canvas and receive images from background processes?

from neovim.

trusktr avatar trusktr commented on May 3, 2024

@adelarsq Receive things from a background process, yes, that's intended in general for any plugin. Drawing things like images, that's for a different topic than this one terminals. I suppose neovim can lease out pixel space (in the GUI, or on supporting terminals) instead of character block space. Make a new feature request for it if it doesn't exist already.

from neovim.

ZyX-I avatar ZyX-I commented on May 3, 2024

If neovim-core runs as a server, then each embedded neovim can share the same buffers, session, etc, etc. The outer neovim can be configured with no tabline, no status line, etc, so that its space is maximized for terminal multiplexing, while inner neovims can have the bells an whistles like tablines, status lines, NERDtree buffer, etc.

Neovim is too bold replacement for tmux. I would not expect it run fast, and do not see much benefit in replacing tmux with it: the only two major differences I see are saner statusline configuration (as a powerline developer I can say it is much easier to get Vim statusline right then do this with tmux) and more features available for mappings.

Plus I wouldn't want to quit the outer neovim just to open a new session for a new project. I might want to keep terminals around, but begin work on another project, in which case loading a session with my tabs and windows in an inner neovim makes sense. There are lots of possibilities with this feature.

If you do not want to quit opened neovims WM with multiple virtual desktops is your friend. If you do not want WM use tmux or screen. I keep one browser window per one project and also have separate terminal for building and testing, may sometimes have debugger (kdbg) open, so any terminal multiplexer is of no use here.

I do not see any sense in doing what you request because there already is a number of ways to do what you describe. Why use such bad multiplexer (bold, designed for other uses) when there are other multiplexer available which were evolving specifically as multiplexers?

I intend to replace tmux with neovim when neovim has this capability.

Why? If you want to convince that making it possible to use neovim as a multiplexer has any sense you must not describe why multiplexers are useful. You must describe why neovim is better then other multiplexers.

from neovim.

aktau avatar aktau commented on May 3, 2024

I never even use vim's split-screen features. I don't want to remember many different shortcuts (window manager, terminal multiplex, vim) for the same thing. I prefer tmux everywhere.

from neovim.

tarruda avatar tarruda commented on May 3, 2024

Here are a few advantages I see in using Neovim as a multiplexer:

  • While tmux is extensible with shell scripts, Neovim would have the API immediately visible to any child process through the NEOVIM_LISTEN_ADDRESS environment variable. This would be especially useful for programs that provide the ability to write extensions that could leverage the remote API. For example:
    • Shells/interactive programs could use nvim for line editing
    • A gdb python extension could jump files while stepping through the code
    • Transparent integration with REPLs
  • Transparent way of moving between panes/windows, copying/pasting, etc. With tmux this only possible through hacks that not always work and are sometimes inconvenient
  • Integrate vim completion system with the shell(see vim-shell for an example)
  • Use vim syntax highlighting features with programs that have limited syntax highlighting capabilities(eg: gdb)
  • Better interface to terminal multiplexer with GUI toolkits

@trusktr mentioned having nested neovim instances, but this would be unnecessary. Consider this zsh function:

vi() {
  if [[ -z $NEOVIM_LISTEN_ADDRESS ]]; then
    # not running inside nvim
    nvim "$@"
  else
    python -c "import neovim; vim = neovim.connect('$NEOVIM_LISTEN_ADDRESS'); vim.command('e $1');"
  fi
}

There are just too many possibilities, many would only become clear after we start exploring the idea. Sure tmux + vim is already good, but if we can improve workflows, then why not?

from neovim.

tarruda avatar tarruda commented on May 3, 2024

@Shougo I'm investigating the possibility of adding a 'pty' option to jobstart through uv_spawn(https://groups.google.com/forum/#!topic/libuv/EhwAn3y9wWo) and while on UNIX it would be easy, I'm unsure how terminal programs are spawned on windows(to merge this on libuv I need a cross-platform solution). I googled and even asked a SO question but got no luck so far.

I see that your vimproc plugin supports windows, so it would be great if you could give me a hint on how terminals work on windows.

from neovim.

Shougo avatar Shougo commented on May 3, 2024

I see that your vimproc plugin supports windows, so it would be great if you could give me a hint on how terminals work on windows.

Yes. I support vimproc in Windows. But, I cannot support terminal application in vimproc.
I think Conque is using better solution.
It supports Windows terminal application by Win32 console APIs.
https://github.com/rosenfeld/conque-term

I think neovim can support this APIs.

from neovim.

trusktr avatar trusktr commented on May 3, 2024

What you just described up there @thiago is like a paradise. This will afford so many different types of new powerful workflows for developers everywhere.

from neovim.

tarruda avatar tarruda commented on May 3, 2024

@Shougo I did some research on how to implement this on windows in order to add a cross-platform flag to libuv, but it's very troublesome and libuv probably won't ever support this. More details here.

A solution would be to implement a "terminal proxy" program that takes care of spawning the terminal process and communicates to Neovim job control, something like this:

let job_id = jobstart('python-repl', 'console-proxy.exe', ['c:\python27\python.exe'])

console-proxy.exe would spawn python in a hidden console window and transfer data between the console buffers and Neovim

from neovim.

Shougo avatar Shougo commented on May 3, 2024

console-proxy.exe would spawn python in a hidden console window and transfer data between the console buffers and Neovim

It seems good. πŸ‘

from neovim.

tarruda avatar tarruda commented on May 3, 2024

To those interested: I ended up implementing this feature in the core(WIP): #2076

from neovim.

khalidchawtany avatar khalidchawtany commented on May 3, 2024

πŸ‘ Great

from neovim.

adelarsq avatar adelarsq commented on May 3, 2024

πŸ‘ good job
@trusktr I didn't forgot about your advice. I still thinking about how to make it work.

from neovim.

trusktr avatar trusktr commented on May 3, 2024

Todo list:

  • Drop tmux for neovim (pending stability).
  • Set login shell to nvim. zsh -c "nvim +term zsh" is working in my iTerm2 profile and Terminal general settings.

from neovim.

justinmk avatar justinmk commented on May 3, 2024

@trusktr πŸ˜† tmux is still useful for sessions and recovering dropped connections :)

from neovim.

trusktr avatar trusktr commented on May 3, 2024

@justinmk True! I can't wait for mksession to save :terminal commands, and to try running neovim as a server remotely. :D Imagine Atom or Sublime running your terminals! The eye candy.

from neovim.

deckardbsd avatar deckardbsd commented on May 3, 2024

Awesome ! It is a feature that I would love to see. Having support for terminal in a NVim buffer, means that we could have something like SLIME for NVim ??? :D I mean, we could all become then lisp devs, right ? (because in order to become one, you have to run emacs + SLIME).

from neovim.

trusktr avatar trusktr commented on May 3, 2024

@tarruda Hey, just an idea, but what about -- INSERT (terminal) --?

from neovim.

tarruda avatar tarruda commented on May 3, 2024

@tarruda Hey, just an idea, but what about -- INSERT (terminal) --?

-- TERMINAL -- is shorter and passes the same information :)

from neovim.

trusktr avatar trusktr commented on May 3, 2024

Agreed, nevermind, since replace mode is -- REPLACE -- and not -- INSERT (replace) --.

from neovim.

justinmk avatar justinmk commented on May 3, 2024

in order to become one, you have to run emacs + SLIME).

@deckardbsd If you consider clojure as a lisp, then, no. https://github.com/tpope/vim-fireplace works extremely well while maintaining harmony with Vim conventions.

from neovim.

trusktr avatar trusktr commented on May 3, 2024

@tarruda You mentioned something like

vi() {
  if [[ -z $NEOVIM_LISTEN_ADDRESS ]]; then
    # not running inside nvim
    nvim "$@"
  else
    python -c "import neovim; vim = neovim.connect('$NEOVIM_LISTEN_ADDRESS'); vim.command('e $1');"
  fi
}

I don't see such any $NEO* vars after starting neovim. Is that example assuming we've created an env var on our own?

Doh! Nevermind, it's NVIM_LISTEN_ADDRESS.

from neovim.

trusktr avatar trusktr commented on May 3, 2024

@tarruda How do we exit -- TERMINAL -- mode in a nested nvim? Seems like I can only exit terminal mode of the outermost nvim with <c-\><c-n>. xD

from neovim.

tarruda avatar tarruda commented on May 3, 2024

@tarruda How do we exit -- TERMINAL -- mode in a nested nvim? Seems like I can only exit terminal mode of the outermost nvim with <c->. xD

unfocus nested terminal: <c-\><c-\><c-n>.
unfocus doubly nested terminal: <c-\><c-\><c-\><c-\><c-n>

And so on

from neovim.

deckardbsd avatar deckardbsd commented on May 3, 2024

@justinmk Thanks ! But for scheme, common lisp ?

from neovim.

tarruda avatar tarruda commented on May 3, 2024

@deckardbsd I'm not familiar with slime, but I was using slimux to send text to REPLs in other panes and have successfully replaced it with this configuration for the terminal emulator branch. More advanced integration with REPLs will be possible using the job control autocommands(which will become callbacks in the near future)

from neovim.

justinmk avatar justinmk commented on May 3, 2024

which will become callbacks in the near future)

Without closures I don't think that will gain anything.

from neovim.

kopischke avatar kopischke commented on May 3, 2024

which will become callbacks in the near future)

Without closures I don't think that will gain anything.

Agreed.

from neovim.

tarruda avatar tarruda commented on May 3, 2024

Without closures I don't think that will gain anything.

One thing we'll gain a better API with less dependency on global state. Here's a job control example in the current API:

:let srv1_id = jobstart('netcat-server-1', 'nc', ['-l', '9991'])
:let srv2_id = jobstart('netcat-server-2', 'nc', ['-l', '9991'])

function JobEvent()
  if v:job_data[1] == 'stdout'
    let str = 'Message from job '.v:job_data[0].': '.v:job_data[2]
  elseif v:job_data[1] == 'stderr'
    let str = 'Error message from job '.v:job_data[0].': '.v:job_data[2]
  else
    let str = 'Job '.v:job_data[0].' exited with code '.v:job_data[2]
  endif

  call append(line('$'), str)
endfunction

au JobActivity netcat-server-* call JobEvent()

Here's what the API will look like with callbacks:

let callbacks = {}

function callbacks.on_stdout(id, data)
  call append(line('$'), 'Message from job '.a:id.': '.a:arg)
endfunction

function callbacks.on_stderr(id, data)
  call append(line('$'), 'Error message from job '.a:id.': '.a:arg)
endfunction

function! callbacks.on_exit(id, code)
  call append(line('$'), 'Job '.a:id.' exited with code '.a:code)
endfunction

let srv1_id = jobstart('nc', ['-l', '9991'], callbacks)
let srv2_id = jobstart('nc', ['-l', '9992'], callbacks)

Advantages of using callbacks:

  • get rid of v:job_data, JobActivity and the first parameter of jobstart which is useless
  • flexible with stdout/stderr redirection: we can redirect to /dev/null by omitting the callbacks or to files by passing file paths
  • better for termopen(#2076), we don't need to call has_autocmd before deciding if the data should be piped to vimscript.

from neovim.

kopischke avatar kopischke commented on May 3, 2024

@tarruda half of that is a matter of implementation:

let callbacks = {}

function callbacks.stdout(id, data)
  call append(line('$'), 'Message from job '.a:id.': '.a:arg)
endfunction

function callbacks.stderr(id, data)
  call append(line('$'), 'Error message from job '.a:id.': '.a:arg)
endfunction

function! callbacks.exit(id, code)
  call append(line('$'), 'Job '.a:id.' exited with code '.a:code)
endfunction

:let srv1_id = jobstart('netcat-server-1', 'nc', ['-l', '9991'])
:let srv2_id = jobstart('netcat-server-2', 'nc', ['-l', '9991'])

autocmd JobActivity netcat-server-* call call(get(callbacks, v:job_data[1], callbacks.exit), [v:job_data[0], v:job_data[2]], callbacks)

I agree that callbacks are cleaner software design wise than globals, but without closures, you end up relying on an implicit call syntax highly conascent on the jobstart interface, never mind the semantics that feel oddly out of place in Vim.

from neovim.

justinmk avatar justinmk commented on May 3, 2024

With callbacks,

  • a job can't be set up as a one-liner on the command line
  • multiple handlers cannot subscribe to the job output
  • the callbacks must be defined before calling jobstart()
  • it is not idiomatic

get rid of v:job_data,

Read-only globals are not such a big deal. I think it should be renamed v:job, though.

flexible with stdout/stderr redirection: we can redirect to /dev/null by omitting the callbacks or to files by passing file paths

Sounds good, but we could do that with optional parameters to jobstart(), without losing the JobActivity approach.

better for termopen(#2076), we don't need to call has_autocmd before deciding if the data should be piped to vimscript.

Is that a performance optimization?

from neovim.

tarruda avatar tarruda commented on May 3, 2024

a job can't be set up as a one-liner on the command line

Its very unlikely someone will use a one line command to spawn a job, the common thing to do is install an autocmd that calls a function. If the user wants to ignore the job output and just have it running silently in background, the callback API is actually shorter: call jobstart('job-name', 'cmd', [], {}) vs call jobstart('cmd', [], {}).

Even if job one-liners are wanted, the callback API does not block it. Say we add a data option that is used to identify the job callback "user", a generic one-line command can be defined in pure vimscript withe something like this:

function! s:InvokeCmd(id, code, data)
 " data is the value of the "data" option passed to `jobstart`.
 " In this specific case, it is the name of a command that must be executed after the job exits
  exe data
endfunction

function! JobStartFn(cmd, args, data)
  let jobopts = {'data': data, 'exit_cb': function('s:InvokeCmd')}
  call jobstart(cmd, args, jobopts)
endfunction

command! -nargs=% let JobStart call JobStartFn(<f-args>)

With the above(which we can distribute as a standard plugin in $VIMRUNTIME, the user may start one line jobs with something like this:

:JobStart ctags ['-R'] "echo ctags done!"

multiple handlers cannot subscribe to the job output

I cant imagine a situation where a plugin will need to subscribe to a job it didn't start. The common scenario is to

  • Setup JobActivity autocmds with a job name or pattern
  • Call jobstart passing a name that matches the pattern chosen in the first step

The name parameter of jobstart is only used to wire it with the autocmd with jobstart, but nothing stops multiple plugins from using similar names that can result in conflicts(plugins handling autocmds it did not subscribe for). With the callback API this is not an issue.

But multiple subscribers to one job is still possible with callback API. funcrefs or even the User autocmd can be used if a plugin wants to notify other plugins when one of its job completes.

the callbacks must be defined before calling jobstart()

Yes but why would they be defined after? If multiple subscribers to one job are required it can still be done even after the job has started:

let callbacks = []
function! InvokeSubcribedCmds(id, code)
  for cb in callbacks
    cb(code)
  endfor
endfunction

command! -nargs=% let JobStart call jobstart(<f-args>, {' 'exit_cb': function('InvokeSubscribedCmds')})
command! -nargs=1 JobSubscribe call add(callbacks, <f-args>)

IMO its not very useful but still there if required.

it is not idiomatic

That was my initial thought when I added the JobActivity autocmd, but it is a forced idiom in the context of jobs. Autocmds are for "global events" and jobs simply don't fall into this category: When you start a job you dont want to create global events, you just want your code to be called when the job responds.

Sounds good, but we could do that with optional parameters to jobstart(), without losing the JobActivity approach.

True, but then the API would be even more complex

Is that a performance optimization?

Yes. For every job data event that has an associated terminal window we can do one of two things:

  • Always call push_job_event which will process the data for vimscript: replace NULs by NL, split NLs and create a list with a duplicate of every result string)
  • Check for has_autocmd to decide if we need to call push_job_event

To avoid the unnecessary string processing and allocation, I've opted for the second option in #2076, but a loop for matching existing autocmd patterns is executed:

  for (ap = first_autopat[(int)event]; ap != NULL; ap = ap->next)
    if (ap->pat != NULL && ap->cmds != NULL
        && (ap->buflocal_nr == 0
            ? match_file_pat(NULL, ap->reg_prog,
                fname, sfname, tail, ap->allow_dirs)
            : buf != NULL && ap->buflocal_nr == buf->b_fnum
            )) {
      retval = TRUE;
      break;
    }

That means every JobActivity autocmd results in a pattern match for every incoming data event of every running job. With the callback API we can simply store the funcref in a field of the TerminalJobData struct and change the check to cb != NULL which is much faster.

With that said, I dont want to force an API that plugin developers are not confortable with, so I ask @junegunn(vim-plug) and @benekastah(neomake) what are their thoughts on this API change

from neovim.

junegunn avatar junegunn commented on May 3, 2024

Personally I like autocmd abstraction; event and handlers. I can't come up with a realistic example right now, but I think it's conceivable that there would be a plugin with a long-running background "job", where different handlers are incrementally attached on demand. You've shown that it's already possible without autocmd abstraction (command! -nargs=1 JobSubscribe call add(callbacks, <f-args>), does JobSubscribe exist now?), but I seem to prefer the idiomatic way of attaching handlers using autocmd. But it's just a matter of preference.

But I also do not like having to come up with an incidental unique "name" when calling jobstart(). In case of vim-plug, I'm just using the name of the plugin for it. There's a possibility of name clash, but I guess it hardly matters in practice.

Basically what vim-plug does right now can be summarized as follows:

function! s:job_handler(name) abort
  " a:name is updated!
endfunction

for name in plugin_names
  call jobstart(name, 'sh', ['-c', 'git pull '.name])
  augroup PlugJobControl
    execute 'autocmd JobActivity' name printf('call s:job_handler(%s)', string(a:name))
  augroup END
endfor

You see, it reuses the same handler function, but passes extra data as the argument to it on autocmd. Do you think the same can be easily achieved using the suggested API? The return value of jobstart is not available until the job (and its callback) is started.

You're not going to support both versions of the API at the same time, right? Then the users of vim-plug must use the matching version of Neovim. One runs :PlugUpgrade and vim-plug suddenly stops working with strange errors ("You call it an upgrade?!") Will there be a way to prevent such cases? Like has(something) so vim-plug can gracefully notify the user to upgrade Neovim accordingly.

from neovim.

justinmk avatar justinmk commented on May 3, 2024

@tarruda we could skip pattern matching and only match literals (for JobActivity) to make has_autocmd fast. Making events fast is something we should do anyways. If we introduce callbacks, now we have 2 different event concepts that need to be optimized.

from neovim.

tarruda avatar tarruda commented on May 3, 2024

does JobSubscribe exist now?), but I seem to prefer the idiomatic way of attaching handlers using autocmd. But it's just a matter of preference.

No, that was just an example of what a plugin that allows others to subscribe to its own job events would look like.

You see, it reuses the same handler function, but passes extra data as the argument to it on autocmd. Do you think the same can be easily achieved using the suggested API? The return value of jobstart is not available until the job (and its callback) is started.

Here's how it could look like with the callback API:

function! s:job_handler(job_id, data_or_return_code, name, event) abort
endfunction
let s:handler_ref = function('s:job_handler')

for name in plugin_names
  call jobstart('sh', ['-c', 'git pull '.name], { 'stdout': s:handler_ref , 'stderr': s:handler_ref , 'exit': s:handler_ref, 'data': name})
endfor

In my examples I used a different function for stdout/stderr and exit events, but we can just as easily use a single function if the event name is passed as a argument. The second argument is the data received for the "stdout" or "stderr" events, and the return code for the "exit" event. The 'data' option passed to jobstart can be anything that the caller wants to be passed to the job handler, in this case it is the plugin name.

from neovim.

benekastah avatar benekastah commented on May 3, 2024

When I first started coding up neomake with the jobs, I was wishing it would be callback based. I think it is a more natural idiom. That being said, it's been demonstrated here that you can use both approaches to accomplish the same thing. In my plugin, using autocommands certainly hasn't caused problems or difficulty developing features. Since neovim is still in a stage where code and features are going to change a lot, I can accept that this might change, but I don't feel a lot of personal pressure to advocate one way or the other. I share @junegunn's concerns about plugins breaking, but that isn't insurmountable, and changes like this sometimes have to happen for the greater good.

from neovim.

curvi avatar curvi commented on May 3, 2024

Without using the external session capability and for example running matlab or the like in a session side by side with nvim, this feature could certainly replace tmux (which needs pretty ugly hacks anyway). However in my version of nvim there is no text reflow in the terminal session, which is kind of a bummer. I use iTerm2 and nvim 0.0.0-alpha+201504060149 (compiled Apr 6 2015 14:18:57).

from neovim.

trusktr avatar trusktr commented on May 3, 2024

Yeah!!!! Text reflow (wrap) would be very nice.

from neovim.

bfredl avatar bfredl commented on May 3, 2024

urxvt has, at least. (and is on per default, I think). It makes sense for output text (but not tui:s, of course)

from neovim.

elmart avatar elmart commented on May 3, 2024

Terminal.app on OSX does reflow when you change window size, which I find pretty useful.

from neovim.

trusktr avatar trusktr commented on May 3, 2024

iTerm does it too. I made a new topic for this: #2514

from neovim.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.