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

Asynchronous build support #2

Open
dbarnett opened this issue Dec 15, 2016 · 11 comments
Open

Asynchronous build support #2

dbarnett opened this issue Dec 15, 2016 · 11 comments
Milestone

Comments

@dbarnett
Copy link
Contributor

If you invoke a slow bazel build that takes seconds or minutes, the build will currently steal focus and execute in the foreground, preventing you from doing anything else in your vim session until it finishes. It would be nice to have the build continue in the background and leave vim fully usable while it's running (possibly in some kind of interactive shell mode where you can see the bazel cli output as it's printed).

Vim 8's new job support looks like it will suit our needs. In Neovim, there's probably a native API to do what we want.

@dbarnett dbarnett modified the milestone: v0.1 Dec 15, 2016
@gregorias
Copy link

Plugin use

Continuing our internal discussion. Both vim and neovim use different async mechanisms, and the reason why I want to use neomake is, because it supports both editors (I didn't see this point addressed in the responses).

The alternative is for us to write the async handling code ourselves. In that case, I would write for both versions since, I am using neovim myself.

So I figure, trying out with neomake first, saves us from writing code at the expense of user having to add one more plugin to her settings. This trade-off seems OK to me, the user already has to download the bazel + maktaba plugins, so it's not like she's practicing ascetic approach to vim :).

Given that information, what's your opinion now?

Interface

Let's continue also our discussion about the interface:

What do you think about:

  • There will be a plugin variable 'g:bazel_use_async' that will be false on default. Iff neomake is available and the flag is set to true, then the plugin runs the build asynchronously.
  • User may only run one job at a time - if the user tries to call bazel when the last job hasn't finished, then she gets an error message.
  • We add two commands for async mode, :BazelShowCurrentJob and :BazelCancelJob, which respectively: display the progress of the current job if any, and kill the currently unfinished job if any.

Some alternatives are:

  • Rely on a different plugin or do not rely on any additional plugin at all.
  • Instead of a global flag, have async and sync version of the :Bazel command.
  • Allow running multiple jobs at the same time (for example, someone likes to have all workspaces in one vim session).

@tbelaire
Copy link

I'm behind the idea of using neomake, as I was actually hacking on doing just that already.
However, that does preclude also using :terminal to have the blaze output displayed in a pane somewhere, as I think neomake is pretty focused on just populating the quickfix list and gutter.

@dbarnett
Copy link
Contributor Author

My big question is will neomake support all the functionality we'll ultimately want? I admit I may just not understand how to use it properly, but I found a lot of apparent limitations. Doesn't seem to support any interactive terminal view of jobs and I'm anticipating limitations in how it handles quickfix.

Other comments:

  • I'd really like async to be the default since a lot of users won't understand why they're getting the slow clunky experience if that's the default. I'm hoping to really strive to avoid gotchas in the async mode so it's a great default, e.g. make sure it's simple and intuitive to check in on slow runs and interactively watch them.
  • If there's a more generic mechanism for managing async jobs that'd be great, e.g., integrated view of bazel jobs and other jobs from neomake or whatever. As far as cancelling, the most intuitive way to cancel jobs for me would be to pull up an interactive terminal view on them and ctrl-c instead of a separate command. (Interactive terminal view might be a significant undertaking in itself, but doable with vim 8 jobs AFAICT and seems well worth the implementation effort.)

OTOH, I'm a diehard idealist and you're the one volunteering to write code. What are your thoughts on all those tradeoffs?

@gregorias
Copy link

Let's focus on interface and features first - the implementation will follow

My big question is will neomake support all the functionality we'll ultimately want?

That's true that neomake has a specific workflow in mind, and we may have to ditch it if we can't fit our features into its model. That's why I'm trying to get some sense of what kind of workflow we have in mind. The interface that I roughly described in initial posts would be supportable by neomake. Interactive terminal? Not much, at least without resorting to hacks.

I would like to go a more idealistic route myself, so let's agree on what kind of stuff we want there to be in the plugin, and, then, we'll figure out how to support them. If neomake's model doesn't allow us to implement all the features we want, then I'm OK with implementing our own async job adapter around vim 8 and neovim (I did something similar and basic for vim-airline - excerpt). Are you OK with that?

Batteries included

So, working out of the box, without an additional plugin, necessitates our own implementation. Do we want to have this batteries included philosophy?

Interactive terminal

The terminal stuff, would require a fully functional adapter. However, I don't fully understand how that terminal would work. To get a terminal output of a blaze job, the blaze process needs to be attached to a terminal from the start. In neovim I could start a :terminal in the background and run the blaze asynchronously in there (already a bit hacky). I don't know how it would work in vim 8.

Do we really need a terminal? Can't we just have :BazelCancelJob, and :ShowBazelOutput that would open a text file with current or last output of a bazel job?

@tbelaire
Copy link

tbelaire commented Jan 16, 2017

I think if we're leaning towards using a terminal/showing the output in a buffer, then we should also think about the experience of running bazel test. I've currently bound <localleader>tt to neoterm's :T function with testing the current file.
That reused a single :terminal window, and doesn't move the cursor from the current buffer, which is nice. That also shows build failures, though they don't show up in the quickfix list or gutter.
I'm considering adding a binding to just build the current package too.

If we could magically also populate the quickfix after running those commands, this would be perfect, but I don't know how I would do that (maybe some shenannagins with tee and a pipe into vim?).
But running a second build with Neomake does fill in that gap for me.

EDIT:
Another upside of that is that I can just <C-W>j into the window and edit the command and rerun it if I want.

@dbarnett
Copy link
Contributor Author

dbarnett commented Jan 17, 2017

An interactive terminal view isn't necessarily a "must", but looks straightforward to implement in vim 8 at least. I think we'd want some kind of "view log" operation if we didn't have a live view, so I could imagine neovim falling back to just showing the latest contents of the log if neovim really couldn't show it interactively. I'm not super attached to that view being embedded into vim either, I'd just expect to be able to watch it in a terminal somehow in my workflow.

Re "batteries included", I'm not particularly opposed to having plugin dependencies, but depending on plugins that aren't made to be depended on can get weird. And it seems like delegating everything to Neomake adds significant limitations without actually saving much maintenance burden in practice. I expect a few conditionals like what you linked to in vim-airline, doable if not trivial AFAICT.

Re quickfix, it's always possible to populate it after the fact using setqflist() or :cgetexpr, so it shouldn't take any clever shenanigans to get more-or-less the behavior we want.

@gregorias
Copy link

An interactive terminal view isn't necessarily a "must", but looks straightforward to implement in vim 8 at least. I think we'd want some kind of "view log" operation if we didn't have a live view, so I could imagine neovim falling back to just showing the latest contents of the log if neovim really couldn't show it interactively. I'm not super attached to that view being embedded into vim either, I'd just expect to be able to watch it in a terminal somehow in my workflow.

It doesn't look straightforward to me at all. Could you elaborate on how it would work?

Looks to me that we feel comfortable with working directly with vim 8's and neovim's async inferface. I'll start hacking the most important features, keeping in mind that it has to support the fancy stuff you mention.

@dbarnett
Copy link
Contributor Author

dbarnett commented Jan 20, 2017

An interactive terminal view isn't necessarily a "must", but looks straightforward to implement in vim 8 at least.

It doesn't look straightforward to me at all. Could you elaborate on how it would work?

Jobs and channels can set a out_buf='buffer' option to append to a buffer, and there's a job_setoptions() function that looks like it can change those options on the fly.

@ngzhian
Copy link

ngzhian commented Jul 8, 2018

There can be an option to use syscall.CallAsync or use term_start to run a background job without losing interactivity of the main editing session. That way we can accommodate both user interfaces. This two options both take a callback, which we can set errorformat, and from there populate quickfix/location list. If there are errors, show location list. The tricky part is probably handling the output of bazel using errorformat.

@jin
Copy link
Member

jin commented Jul 8, 2018

@ngzhian consider using BEP's TestResult instead of parsing the stdout?

@ngzhian
Copy link

ngzhian commented Jul 10, 2018

It doesn't look like TestResult contains information about build failures. In the event of a compile error (say in a java file), the error output is stderr of the Progress message. So it will still have to be parsed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants