Commit Graph

340 Commits

Author SHA1 Message Date
Ethan Atkins 5238c78dfd Rename Terminal member fields for clarity
Also provide additional source commentary.
2020-06-25 11:46:07 -07:00
Ethan Atkins ddc4e850b5 Disable noisy jline log lines
JLine will spam the console with error messages if certain commands get
interrupted. This is very noticeable and annoying in tab completions.

We can stop doing work in background as well since we've silenced the
jline logging.
2020-06-25 10:37:56 -07:00
Ethan Atkins ab362397ba Add remote cancellation support
This commit makes it possible for a remote client to cancel a running
task initiated by a different client by typing `cancel` into the shell.
It can be useful if the remote client has run something blocking like
console.

The console task can't safely be interrupted, so instead we write some
newlines filed by ctrl+d to exit the console.
2020-06-24 19:40:17 -07:00
Ethan Atkins ba345dd797 Add multi-client ui to server
This commit makes it possible for the sbt server to render the same ui
to multiple clients. The network client ui should look nearly identical
to the console ui except for the log messages about the experimental
client.

The way that it works is that it associates a ui thread with each
terminal. Whenever a command starts or completes, callbacks are invoked
on the various channels to update their ui state. For example, if there
are two clients and one of them runs compile, then the prompt is changed
from AskUser to Running for the terminal that initiated the command
while the other client remains in the AskUser state. Whenever the client
changes uses ui states, the existing thread is terminated if it is
running and a new thread is begun.

The UITask formalizes this process. It is based on the AskUser class
from older versions of sbt. In fact, there is an AskUserTask which is
very similar. It uses jline to read input from the terminal (which could
be a network terminal). When it gets a line, it submits it to the
CommandExchange and exits. Once the next command is run (which may or
may not be the command it submitted), the ui state will be reset.

The debug, info, warn and error commands should work with the multi
client ui. When run, they set the log level globally, not just for the
client that set the level.
2020-06-24 19:40:17 -07:00
Ethan Atkins 1b03c9b1a9 Make Terminal a trait to support multiple clients
In order to support a multi-client sbt server ux, we need to factor
`Terminal` out into a class instead of a singleton. Each terminal provides
and outputstream and inputstream. In all of the places where we were
previously relying on the `Terminal` singleton we need to update the
code to use `Terminal.get`, which will redirect io to the terminal whose
command is currently running.

This commit does not implement the server side ui for network clients.
It is just preparatory work for the multi-client ui.

The Terminal implementations have thread safe access to the output
stream. For this reason, I had to remove the sychronization on the
ConsoleOut lockObject. There were code paths that led to deadlock when
synchronizing on the lockObject.
2020-06-24 19:22:57 -07:00
Ethan Atkins 120e6eb63d Route TaskProgress through CommandExchange
Rather than going through the console appender logging to make
TaskProgress work, we can instead use the CommandExchange. This will be
useful in future commits where there are multiple terminals that all
need to receive progress. By organizing the TaskProgress this way, we
can store a separate progress state for each terminal and update the
progress for all of the active terminals. We also can set the current
running command in command exchange which will be useful in future
commits to show what command is currently running.

This commit also reworks TaskProgress to always kill its thread when
there are no active tasks. It will start a new thread as soon as there
is another active task.
2020-06-24 19:19:06 -07:00
Ethan Atkins 034b9690c1 Add additional ansi-escape removal functions
This commit adds a number of functions for stripping ansi escape
characters and/or finding the position of the cursor in a line that may
contain colors and moves. The motivation for EscHelpers.cursorPosition
is that when printing progress lines, we need to know the visual
dimensions of the last line printed to the prompt. The
EscHelpers.stripColorsAndMoves can be used to remove all ansi escape
sequences. Finally EscHelpers.stripMoves leaves colors but strips out
all other escape sequences. This is so we can reprint the terminal
prompt during supershell. If we didn't strip out the escape sequences,
we could inadvertently blow away everything below the cursor in cases
where we actually want the lines below the cursor to persist.
2020-06-24 19:19:06 -07:00
Ethan Atkins a94d6dd77c Rename JLineCompletion parameter name
It was confusing that reader was used as a parameter name in two places.
2020-06-24 19:19:06 -07:00
Ethan Atkins e53c8f6f01 Add Util.ignoreResult
This adds a convenience macro for appending `()` to an expression if it
is the last expression in a block that is supposed to return Unit.
2020-06-24 19:19:06 -07:00
Ethan Atkins 52d19d8f0c Refactor Signal for graalvm
The graalvm issues warnings about the objects defined in
Signal.register, so I made them top level private classes instead.
2020-06-24 19:19:06 -07:00
eugene yokota 2b557851ca
Merge pull request #5041 from jsoref/https
Https
2020-06-14 17:34:58 -04:00
Eugene Yokota 2feecf8a1f Selective functor
This implements Selective functor for `Either[A, B]` "task" (`Initialize[Task[Either[A, B]]]`).
The selective functor allows an encoding of if-expression:

```
  def ifS[A](
      x: Def.Initialize[Task[Boolean]]
  )(t: Def.Initialize[Task[A]])(e: Def.Initialize[Task[A]]): Def.Initialize[Task[A]]
```

The benefit of this approach is that task dependencies are still visible to inspect command.
2020-05-17 23:36:04 -04:00
Ethan Atkins ae978b9337 Remove TaskProgressFormats autogenerated file
This file somehow got stuck in the repo although it wasn't actually
used. In fact, it fails to compile at all because
sbt.internal.util.TaskProgress is defined in main, not util-logging. I
noticed this because metals wasn't working well because it was failing
to compile util-logging because of this file. I think the file was
checked in by accident in e28e052b5b.
2020-05-05 08:23:56 -07:00
Ethan Atkins 079cf2178c Add ClearScreenAfterCursor
This communicates intent better than clearScreen(0).
2020-05-01 13:02:48 -07:00
Ethan Atkins 58822cc3f5 Add virtual System.out for supershell
In order to make supershell work with println, this commit introduces a
virtual System.out to sbt. While sbt is running, we override the default
java.lang.System.out, java.lang.System.in, scala.Console.out and
scala.Console.in (unless the property `sbt.io.virtual` is set to
something other than true). When using virtual io, we buffer all of the
bytes that are written to System.out and Console.out until flush is
called. When flushing the output, we check if there are any progress
lines. If so, we interleave them with the new lines to print.

The flushing happens on a background thread so it should hopefully not
impede task progress.

This commit also adds logic for handling progress when the cursor is not
all the way to the left. We now track all of the bytes that have been
written since the last new line. Supershell will then calculate the
cursor position from those bytes* and move the cursor back to the
correct position. The motivation for this was to make the run command
work with supershell even when multiple main classes were specified.

* This might not be completely reliable if the string contains ansi
cursor movement characters.
2020-05-01 12:35:43 -07:00
Ethan Atkins a449b1ff2d Move JLine apis into LineReader
It is better that sbt not expose the implementation detail that
LineReader is implemented by JLine. Other terminal related apis should
be handled by sbt.internal.util.Terminal.
2020-05-01 12:35:43 -07:00
Ethan Atkins 9218d3c087 Redraw command prompt after network command
Presently if a server command comes in while in the shell, the client
output can appear on the same line as the command prompt and the command
prompt will not appear again until the user hits enter. This is a
confusing ux. For example, if I start an sbt server and type
the partial command "comp" and then start up a client and run the clean
command followed by a compile, the output looks like:

[info] sbt server started at local:///Users/ethanatkins/.sbt/1.0/server/51cfad3281b3a8a1820a/sock
sbt:scala-compile> comp[info] new client connected: network-1
[success] Total time: 0 s, completed Dec 12, 2019, 7:23:24 PM
[success] Total time: 0 s, completed Dec 12, 2019, 7:23:27 PM
[success] Total time: 2 s, completed Dec 12, 2019, 7:23:31 PM

Now, if I type "ile\n", I get:
[info] sbt server started at local:///Users/ethanatkins/.sbt/1.0/server/51cfad3281b3a8a1820a/sock
ile
[success] Total time: 0 s, completed Dec 12, 2019, 7:23:34 PM
sbt:scala-compile>

Following the same set of inputs after this change, I get:
[info] sbt server started at local:///Users/ethanatkins/.sbt/1.0/server/51cfad3281b3a8a1820a/sock
sbt:scala-compile> comp
[info] new client connected: network-1
[success] Total time: 0 s, completed Dec 12, 2019, 7:25:58 PM
sbt:scala-compile> comp
[success] Total time: 0 s, completed Dec 12, 2019, 7:26:14 PM
sbt:scala-compile> comp
[success] Total time: 1 s, completed Dec 12, 2019, 7:26:17 PM
sbt:scala-compile> compile
[success] Total time: 0 s, completed Dec 12, 2019, 7:26:19 PM
sbt:scala-compile>

To implement this change, I added the redraw() method to LineReader
which is a wrapper around ConsoleReader.drawLine; ConsoleReader.flush().
We invoke LineReader.redraw whenever the ConsoleChannel receives a
ConsolePromptEvent and there is a running thread.

To prevent log lines from being appended to the prompt line, in the
CommandExchange we print a newline character whenever a new command is
received from the network or a network client connects and we believe
that there is an active prompt.
2020-05-01 12:35:43 -07:00
Ethan Atkins 293e83ef9f Add Delete line to terminal prompt 2020-05-01 12:35:43 -07:00
Ethan Atkins 2e3a1e767d Don't poll System.in in ConsoleChannel
The ask user thread is a background thread so it's fine for it to block
on System.in. By blocking rather than polling, the cpu utilization of
sbt drops to 0 on idle. We have to explicitly handle <ctrl+d> if we
block though because the JLine console reader will return null both if
the input stream returns -1
2020-05-01 12:35:43 -07:00
Ethan Atkins 7902ec3b7d Add Terminal abstraction
This commit aims to centralize all of the terminal interactions
throughout sbt. It also seeks to hide the jline implementation details
and only expose the apis that sbt needs for interacting with the
terminal.

In general, we should be able to assume that the terminal is in
canonical (line buffered) mode with echo enabled. To switch to raw mode
or to enable/disable echo, there are apis: Terminal.withRawSystemIn and
Terminal.withEcho that take a thunk as parameter to ensure that the
terminal is reset back to the canonical mode afterwards.
2020-05-01 12:35:43 -07:00
Eugene Yokota 2396b449fe Contraband 0.4.6 2020-04-24 17:44:15 -04:00
nigredo-tori 11b7173ec7
Fix a message about an undefined setting
`defining` seems to be the setting or a task that references `referencedKey`, not the other way around.
2020-03-13 12:53:44 +07:00
Dale Wijnand 2608f8ade6 Document parts of AList & components of TupleSyntax
Also, extract the AList.SplitK type lambda helper for call-site reuse.
2020-02-17 07:15:37 +00:00
Ethan Atkins cf745255e8 Apply javafmt in sbt project 2020-01-14 14:38:08 -08:00
Ethan Atkins 639b812a01 Don't strip quotes in _sbt_ scripted command arguments
Stripping quotation marks makes it impossible to cleanly test certain
sbt features without resorting to weird hacks. For example:
> set Compile / scalacOptions += "-Xfatal-warnings"
did not work while
> set Compile / scalacOptions += '"-Xfatal-warnings"'
did.

I leave the single quote parser unchanged since single quotes are not
really used in sbt and so there is utility in leaving them as a way to
group arguments that should not be split apart.

This change should only affect the scripted tests in the sbt repo. We
can consider making stripQuotes = false the default for the plugin as
well.
2020-01-11 16:50:22 -08:00
Ethan Atkins aecdc44909 Update contraband sources
In 8bfae66b9d I upgraded contraband but
not all of the sources were regenerated because I didn't run clean
before recompiling.
2019-12-12 11:34:53 -08:00
Eugene Yokota 1ef83e9140 Fixes sbt new by restoring the terminal
Fixes https://github.com/sbt/sbt/issues/5063

This fixes "sbt new" on Ubuntu by restoring the terminal state after supershell querying for the terminal width.
2019-12-11 13:05:20 -05:00
Ethan Atkins ad59e71b1a Add util headers
None of the util files had headers.
2019-12-08 10:29:22 -08:00
Ethan Atkins 8bfae66b9d Update build.sbt to handle util projects
As part of re-integrating util into the sbt main project, I had to
update the build.sbt and a few dependencies (like the contraband plugin).
2019-12-08 10:28:31 -08:00
Ethan Atkins 4d1bd18296 Merge remote-tracking branch 'util-integration/develop' into util-integration 2019-12-07 17:49:46 -08:00
Diego E. Alonso-Blas 3657910063 ConsoleAppender: reuse/recycle StringBuilder storage.
A StringBuilder is a mutable data structure to create a String.
When the String is created, the new String does not share any
storage with the StringBuilder. Thus, we can keep a same
StringBuilder, and reuse its internal storage between different
iterations.
2019-10-22 23:30:09 +02:00
Eugene Yokota 54b3405f42 apply -Yno-lub
To demonstrate [-Yno-lub](http://eed3si9n.com/stricter-scala-with-ynolub), this shows the code changes that removes lubing (Not all subprojects are done).

After I made the changes, I switched the Scala back to normal 2.12.10.
2019-10-13 23:46:23 -04:00
Ethan Atkins 43f25520a0 Don't include DeleteLine in progress length
I incorrectly included the DeleteLine in the progress line length and
this could cause certain progress lines to be incorrectly reported as
multi line when they actually fit on a single terminal line.
2019-10-07 09:30:41 -07:00
Ethan Atkins 9c2dd05b6a Avoid possible divide by zero
On the off chance that in some configurations the terminal width is set
to zero, avoid an exception by returning 0 for terminal lines. It is
likely that supershell will not work well if terminal width is zero, but
that's better than a potential crash (I think the crash would be in the
progress background thread, so I'm not sure how bad it would be, but
still its good to avoid).
2019-09-24 16:35:03 -07:00
Ethan Atkins 5cfab4c9a9 Cleanup implementation of progress report
It was a bit cleaner to consolidate `extra` and
(previousLines|info).length into prevLength and currentLength.
2019-09-24 16:33:42 -07:00
Ethan Atkins 7597cdb19b Take terminal width into account in supershell
Sometimes if the progress lines are wider than the terminal width,
the supershell blank zone can expand indefinitely because be do not move
the cursor far enough up to properly re-fill the blank zone.
2019-09-24 10:59:53 -07:00
eugene yokota 3f20cc1583
Merge pull request #221 from eatkins/lazy-success-event-tag
Load SuccessEventTag lazily
2019-09-18 22:14:28 -04:00
Ethan Atkins b3165b5c8c Load SuccessEventTag lazily
It takes about a second to load scala.reflect.runtime.universe. If we
lazy load here, we can load scala.relect.runtime.universe in the
background to speed up the sbt start up time. See
0ebb7a5662.
2019-09-18 15:33:42 -07:00
Eugene Yokota 5d0793fece Scala 2.12.10 2019-09-11 23:02:50 -04:00
Josh Soref 747416173a https://apocalisp.wordpress.com 2019-09-05 14:10:59 -04:00
Ethan Atkins f20b275045 Fix supershell position bug
The previous implementation of supershell log line interlacing with
regular line interlacing relied on state in a global object. A somewhat
better approach is for each appender to hold a reference to a state
object. Every time tasks run, new appenders are created, so the state
should always reflect the current progress state.
2019-09-03 13:07:51 -07:00
Ethan Atkins 635316902d Allow supershell to work in no color mode
Supershell actually works quite well in no color mode. On the sbt side,
we still want to disable supershell automatically if the output is not a
terminal or no color is set, but this commit allows the user to force
supershell through -Dsbt.supershell or the useSuperShell setting even
when no color is set.
2019-09-02 11:10:42 -07:00
Ethan Atkins a5666e97b6 Manage progress padding
With this commit, I improved the padding management so that padding is
now added above the progress report. Whenever a line is logged at the
info or greater level, we can reduce the padding level by one since that
line has effectively filled in the padding.
2019-09-01 22:26:57 -07:00
Ethan Atkins d9fe5540f5 Interlace log lines with task progress
With the current supershell implementation, the progress display
flickers when there is heavy console logging during task evaluation.
This is because the console appender clears out the task progress and it
isn't restored until the next periodic super shell report (which
runs every 100ms by default). To remove the flickering, I reworked the
implementation to interlace the log lines with progress reports. In
order to ensure that the log lines remained contiguous, I had to apply
padding at the bottom of the supershell region whenever the new report
contained fewer lines than the old report. The report shifts down as new
log lines are appended. This isn't optimal, but I think removing
the flickering while preserving contiguous log lines is worth it.
2019-09-01 21:06:48 -07:00
xuwei-k dfe789d7c6 avoid deprecated /: and :\
use foldLeft and foldRight

https://github.com/scala/scala/blob/v2.13.0/src/library/scala/collection/IterableOnce.scala#L682-L686
2019-08-30 11:20:53 +09:00
xuwei-k 1f3ce5f9ee use Vector instead of List. avoid O(n) append 2019-08-29 21:44:31 +09:00
Ethan Atkins dcb8e18f0e Filter single semicolons from tab completions
Fixes https://github.com/sbt/sbt/issues/4989.
2019-08-27 09:01:53 -07:00
Ethan Atkins 4bb2f4e968 Used Seq instead of Stream
Streams generically perform poorly and weren't needed here.
2019-08-22 20:35:12 -07:00
Ethan Atkins 1700b89ea4 Parallelize Init.addLocal
During akka startup, addLocal was caused twice and prior to this change,
it took roughly 200ms per call on my computer. After this change, it
took about 100ms.
2019-08-22 20:35:11 -07:00
Eugene Yokota 39fdf70c21 reimplement stacktrace suppression
Ref https://github.com/sbt/sbt/issues/4964
2019-08-20 12:35:13 -04:00