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

Load windows terminal sizes using io.github.alexarchambault.windowsansi #4056

Open
wants to merge 17 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/run-mill-action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ jobs:
if: inputs.millargs != '' && !startsWith(inputs.os, 'windows')

- name: Run Mill (on Windows) '${{ inputs.millargs }}'
run: cmd /C %GITHUB_WORKSPACE%\ci\mill.bat -i -j3 -k ${{ inputs.millargs }}
run: cmd /C %GITHUB_WORKSPACE%\mill.bat -i -j3 -k ${{ inputs.millargs }}
if: inputs.millargs != '' && startsWith(inputs.os, 'windows')

- name: Run Mill (on Windows) Worker Cleanup
Expand Down
6 changes: 6 additions & 0 deletions build.mill
Original file line number Diff line number Diff line change
Expand Up @@ -576,6 +576,9 @@ trait MillStableScalaModule extends MillPublishScalaModule with Mima {
),
ProblemFilter.exclude[Problem](
"mill.scalalib.RunModule#RunnerImpl.*"
),
ProblemFilter.exclude[Problem](
"mill.util.PromptLogger#*"
)
)
def mimaPreviousVersions: T[Seq[String]] = Settings.mimaBaseVersions
Expand Down Expand Up @@ -689,6 +692,9 @@ implicit object DepSegment extends Cross.ToSegments[Dep]({ dep =>
*/
object dummy extends Cross[DependencyFetchDummy](dummyDeps)
trait DependencyFetchDummy extends ScalaModule with Cross.Module[Dep] {
// these cross module names cause problems on windows, and anyway they
// are not necessary in order to load the project into IntelliJ anyway
def skipIdea = true
def scalaVersion = Deps.scalaVersion
def compileIvyDeps = Agg(crossValue)
}
27 changes: 18 additions & 9 deletions dist/package.mill
Original file line number Diff line number Diff line change
Expand Up @@ -224,8 +224,9 @@ object `package` extends RootModule with build.MillPublishJavaModule {
)
}

val batExt = if (scala.util.Properties.isWin) ".bat" else ""
val DefaultLocalMillReleasePath =
s"target/mill-release${if (scala.util.Properties.isWin) ".bat" else ""}"
s"target/mill-release$batExt"

/**
* Build and install Mill locally.
Expand All @@ -240,7 +241,7 @@ object `package` extends RootModule with build.MillPublishJavaModule {

def installLocalCache() = Task.Command {
val path = installLocalTask(
Task.Anon((os.home / ".cache" / "mill" / "download" / build.millVersion()).toString())
Task.Anon((os.home / ".cache" / "mill" / "download" / (build.millVersion() + batExt)).toString())
)()
Task.log.outputStream.println(path.toString())
PathRef(path)
Expand All @@ -256,24 +257,30 @@ object `package` extends RootModule with build.MillPublishJavaModule {
targetFile
}

def millBootstrap = Task.Sources(Task.workspace / "mill")
def millBootstrap = Task.Source(Task.workspace / "mill")
def millBootstrapBat = Task.Source(Task.workspace / "mill.bat")

def bootstrapLauncher = Task {
val outputPath = Task.dest / "mill"
def prepareBootstrapLauncher(bootstrap: os.Path, dest: os.Path, buildVersion: String) = {
val outputPath = dest / "mill"
val millBootstrapGrepPrefix = "(\n *DEFAULT_MILL_VERSION=)"
val millDownloadUrlPrefix = "(\n *MILL_DOWNLOAD_URL=)"

os.write(
outputPath,
os.read(millBootstrap().head.path)
os.read(bootstrap)
.replaceAll(
millBootstrapGrepPrefix + "[^\\n]+",
"$1" + build.millVersion()
"$1" + buildVersion
)
)
os.perms.set(outputPath, "rwxrwxrwx")
PathRef(outputPath)
}
def bootstrapLauncher = Task {
prepareBootstrapLauncher(millBootstrap().path, Task.dest, build.millVersion())
}
def bootstrapLauncherBat = Task {
prepareBootstrapLauncher(millBootstrapBat().path, Task.dest, build.millVersion())
}

def examplePathsWithArtifactName:Task[Seq[(os.Path,String)]] = Task.Anon{
for {
Expand All @@ -292,6 +299,7 @@ object `package` extends RootModule with build.MillPublishJavaModule {
os.copy(examplePath, Task.dest / exampleStr, createFolders = true)
os.write(Task.dest / exampleStr / ".mill-version", build.millLastTag())
os.copy(bootstrapLauncher().path, Task.dest / exampleStr / "mill")
os.copy(bootstrapLauncherBat().path, Task.dest / exampleStr / "mill.bat")
val zip = Task.dest / s"$exampleStr.zip"
os.proc("zip", "-r", zip, exampleStr).call(cwd = Task.dest)
PathRef(zip)
Expand Down Expand Up @@ -319,7 +327,8 @@ object `package` extends RootModule with build.MillPublishJavaModule {

val zips = examples ++ Seq(
(build.dist.assembly().path, label + "-assembly"),
(bootstrapLauncher().path, label)
(bootstrapLauncher().path, label),
(bootstrapLauncherBat().path, label + ".bat")
)

for ((zip, name) <- zips) {
Expand Down
7 changes: 6 additions & 1 deletion docs/modules/ROOT/pages/cli/installation-ide.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,18 @@ globally.
[#_bootstrap_scripts]
== Bootstrap Scripts

Although the Mill example projects come with their own `./mill` bootstrap script,
Although the Mill example projects come with their own `./mill` and `./mill.bat` bootstrap script,
you can also download it manually:

[source,bash,subs="verbatim,attributes"]
----
# Mac/Linux
curl -L {mill-github-url}/releases/download/{mill-last-tag}/{mill-last-tag} > mill && chmod +x mill
echo {mill-last-tag} > .mill-version

# Windows
curl -L {mill-github-url}/releases/download/{mill-last-tag}/{mill-last-tag}.bat -o mill.bat
echo {mill-last-tag} > .mill-version
----

Downloading a `mill` bootstrap script to the root of your project repository helps make it easier for
Expand Down
3 changes: 2 additions & 1 deletion example/scalalib/basic/1-simple/build.mill
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@ object foo extends ScalaModule {
// You can download this example project using the *download* link above
// if you want to try out the commands below yourself, or browse the full sources
// of the example (including supporting files) via the *browse* link. The only requirement is
// that you have some version of the JVM installed; the `./mill` script takes
// that you have some version of the JVM installed; the `./mill` script
// (`./mill.bat` on windows) takes
// care of any further dependencies that need to be downloaded. All examples
// in this documentation site are executable and are continually exercised as
// part of Mill's CI workflows, and they range from the simple hello-world
Expand Down
9 changes: 5 additions & 4 deletions main/client/src/mill/main/client/ProxyStream.java
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,9 @@ public Pumper(InputStream src, OutputStream destOut, OutputStream destErr) {

public void preRead(InputStream src) {}

public void preWrite(byte[] buffer, int length) {}
public void write(OutputStream dest, byte[] buffer, int length) throws IOException {
dest.write(buffer, 0, length);
}

public void run() {

Expand Down Expand Up @@ -152,13 +154,12 @@ public void run() {

if (delta != -1) {
synchronized (synchronizer) {
this.preWrite(buffer, offset);
switch (stream) {
case ProxyStream.OUT:
destOut.write(buffer, 0, offset);
this.write(destOut, buffer, offset);
break;
case ProxyStream.ERR:
destErr.write(buffer, 0, offset);
this.write(destErr, buffer, offset);
break;
}
}
Expand Down
34 changes: 17 additions & 17 deletions main/util/src/mill/util/PromptLogger.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,7 @@ package mill.util

import mill.api.SystemStreams
import mill.main.client.ProxyStream
import mill.util.PromptLoggerUtil.{
Status,
clearScreenToEndBytes,
defaultTermHeight,
defaultTermWidth,
renderPrompt
}
import mill.util.PromptLoggerUtil.{Status, defaultTermHeight, defaultTermWidth, renderPrompt}
import pprint.Util.literalize

import java.io._
Expand Down Expand Up @@ -90,8 +84,8 @@ private[mill] class PromptLogger(
)

def refreshPrompt(ending: Boolean = false): Unit = synchronized {
promptLineState.updatePrompt(ending)
streamManager.refreshPrompt()
val updated = promptLineState.updatePrompt(ending)
if (updated) streamManager.refreshPrompt()
}

if (enableTicker && autoUpdate) promptUpdaterThread.start()
Expand Down Expand Up @@ -289,16 +283,21 @@ private[mill] object PromptLogger {
}
}

override def preWrite(buf: Array[Byte], end: Int): Unit = {
// Before any write, make sure we clear the terminal of any prompt that was
// written earlier and not yet cleared, so the following output can be written
// to a clean section of the terminal

override def write(dest: OutputStream, buf: Array[Byte], end: Int): Unit = {
lastCharWritten = buf(end - 1).toChar
if (interactive() && !paused() && promptShown) {
systemStreams0.err.write(clearScreenToEndBytes)
promptShown = false
}

// Clear each line as they are drawn, rather than relying on clearing
// the entire screen before each batch of writes, to try and reduce the
// amount of terminal flickering in slow terminals (e.g. windows)
// https://stackoverflow.com/questions/71452837/how-to-reduce-flicker-in-terminal-re-drawing
dest.write(
new String(buf, 0, end)
.replaceAll("(\r\n|\n)", AnsiNav.clearLine(0) + "$1")
.getBytes
)
}
}

Expand Down Expand Up @@ -338,7 +337,7 @@ private[mill] object PromptLogger {

def getCurrentPrompt() = currentPromptBytes

def updatePrompt(ending: Boolean = false): Unit = {
def updatePrompt(ending: Boolean = false): Boolean = {
val now = currentTimeMillis()
for (k <- statuses.keySet) {
val removedTime = statuses(k).beginTransitionTime
Expand Down Expand Up @@ -367,8 +366,9 @@ private[mill] object PromptLogger {
ending = ending
)

val oldPromptBytes = currentPromptBytes
currentPromptBytes = renderPromptWrapped(currentPromptLines, interactive, ending).getBytes

!java.util.Arrays.equals(oldPromptBytes, currentPromptBytes)
}

def clearStatuses(): Unit = { statuses.clear() }
Expand Down
4 changes: 3 additions & 1 deletion main/util/src/mill/util/PromptLoggerUtil.scala
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,9 @@ private object PromptLoggerUtil {
if (ending) "\n"
else AnsiNav.left(9999) + AnsiNav.up(currentPromptLines.length - 1)

AnsiNav.clearScreen(0) + currentPromptLines.mkString("\n") + backUp
currentPromptLines.map(_ + AnsiNav.clearLine(0)).mkString("\n") +
AnsiNav.clearScreen(0) +
backUp
}
}

Expand Down
Loading
Loading