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

Multiplatform progress bar rewrite #151

Merged
merged 89 commits into from
Feb 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
89 commits
Select commit Hold shift + click to select a range
e9bd9b6
Add multi-progress builder
ajalt Oct 24, 2023
7bf2e4b
Use new layout in ProgressAnimation
ajalt Oct 25, 2023
f69b7e2
Use Duration for elapsed time
ajalt Oct 25, 2023
c6d6689
Make new progress builder stateless
ajalt Oct 28, 2023
295e6f7
Support unaligned progress layouts
ajalt Nov 1, 2023
c07dd9b
Add docs
ajalt Nov 2, 2023
5fb51be
Replace until with ..< operator
ajalt Nov 2, 2023
a308d78
Add compact timeRemaining style
ajalt Nov 2, 2023
a221a6e
Rename completedPerSecond to speed
ajalt Nov 15, 2023
dd40477
Use timestamps instead of durations in progress state
ajalt Nov 19, 2023
b2c75cf
Add AbstractProgressBarAnimation
ajalt Nov 24, 2023
3a49782
Add ExecutorProgressBarAnimation
ajalt Nov 27, 2023
9cbe91a
Add coroutines extension
ajalt Dec 2, 2023
a9799df
Make ExecutorProgressBarAnimation AutoCloseable
ajalt Dec 4, 2023
02d45e9
Use atomics isntead of locks for base progress animation
ajalt Dec 6, 2023
4f5bc48
Replace locks with atmoics for terminal interceptors
ajalt Dec 6, 2023
b897d89
Implement ProgressAnimation with new backend
ajalt Dec 9, 2023
3b88929
Make progress dsl optional
ajalt Dec 10, 2023
4d3fdd7
Update tests for new api
ajalt Dec 14, 2023
c598230
Add global fps setting to progress scope
ajalt Dec 14, 2023
ee5b44a
add coroutine animation extension
ajalt Dec 15, 2023
e0cb674
Simplify threaded implementation
ajalt Dec 15, 2023
9b8a255
Add test for threaded animation
ajalt Dec 15, 2023
31c9a09
Replace `clear` with `visible`
ajalt Dec 19, 2023
3a1ec9b
Use atomics for Animation state
ajalt Dec 19, 2023
fd2677b
Use class instead of lambda for ThreadFactory
ajalt Dec 19, 2023
ba83b12
Add CachedProgressBarWidgetMaker.timeSource
ajalt Dec 19, 2023
90072f7
Add ProgressTask.visible getter
ajalt Dec 19, 2023
183d5b0
Fix clear behavior
ajalt Dec 20, 2023
2ea0930
Add ProgressLayout tests
ajalt Dec 20, 2023
56e624c
Add elapsedWhenFinished to timeElapsed cell
ajalt Dec 21, 2023
e062300
Implement task pausing
ajalt Dec 23, 2023
5163045
Use sealed class for task status
ajalt Dec 26, 2023
6b4c747
Add ProgressState.frameCount
ajalt Jan 7, 2024
a7365b3
Add Crop widget
ajalt Jan 7, 2024
c5f82b3
Add offsets to Crop
ajalt Jan 9, 2024
8cb630f
Rename Crop to Viewport
ajalt Jan 9, 2024
87a1649
Handle splitting spans during horizontal scroll
ajalt Jan 10, 2024
ecf7f2f
Refactor line sizing to use indexes rather than mutatation
ajalt Jan 11, 2024
7c83e3d
Implement marquee cells
ajalt Jan 12, 2024
1ee601b
Support dynamic text cell content
ajalt Jan 12, 2024
d0b3a4e
Add final refresh for progress animations
ajalt Jan 13, 2024
9d0fec1
Set thread name in progress animation
ajalt Jan 14, 2024
8cfe908
Add precision parameter to `completed`
ajalt Jan 15, 2024
27d2a0d
Change default speed sufix to "/s"
ajalt Jan 15, 2024
2276c63
Add CachedProgressBarWidgetMaker.build extensions
ajalt Jan 17, 2024
ff7f741
Add vertical alignment to progress layout
ajalt Jan 17, 2024
8033627
Add style to percentage cell
ajalt Jan 17, 2024
23d31b3
Handle styled text in marquee
ajalt Jan 17, 2024
9709ca9
Support custom pulse duration in progress bar
ajalt Jan 17, 2024
fe461b8
Add hexviewer sample
ajalt Jan 17, 2024
883cee1
Add stop and clear to progress animations
ajalt Jan 18, 2024
c0cab20
Reduce ThreadProgressBarAnimationTest flakyness
ajalt Jan 18, 2024
d723c57
Add time calculation functions
ajalt Jan 22, 2024
443d2ff
Serialize terminal print requests
ajalt Jan 23, 2024
b25bcdb
Use internal Size type instead of Pair
ajalt Jan 23, 2024
043a46a
Handle terminal resize in Animations
ajalt Jan 23, 2024
8efc8ce
Restore support for multiple animations
ajalt Jan 27, 2024
c081200
Skip flaky test on CI
ajalt Jan 28, 2024
38cf30e
Add test for multi animation stop
ajalt Jan 29, 2024
fe5f449
Add buildCells for custom progress renders
ajalt Jan 30, 2024
503e0d4
Make the animators usable on all animations, not just progress
ajalt Jan 30, 2024
821395b
Keep the cursor hidden until animations are stopped
ajalt Jan 31, 2024
fd0a0fb
Run extension tests on CI
ajalt Jan 31, 2024
32f7c9d
Dump new API
ajalt Jan 31, 2024
f4b6c12
Add docs for BaseProgressLayoutScope
ajalt Feb 1, 2024
7c054a1
Support heterogeneous progress layouts
ajalt Feb 6, 2024
ec4d598
Add addPaddingWidthToFixedWidth
ajalt Feb 7, 2024
4773c40
Remove vararg layout builders
ajalt Feb 8, 2024
6114d38
Only align contiguous columns in multi progress layout
ajalt Feb 8, 2024
ea19836
Add extensions for running MultiProgressBarAnimation
ajalt Feb 12, 2024
43026f3
Expand progress sample
ajalt Feb 12, 2024
2bb6adf
Fix padding for left aligned cells in vertical layout
ajalt Feb 13, 2024
e745b02
Dump API
ajalt Feb 13, 2024
2aab388
Add addPaddingWidthToFixedWidth to grid
ajalt Feb 13, 2024
8f855e8
Add kdocs
ajalt Feb 14, 2024
fa2d276
Move buildCells out of ProgressBarWidgetMaker
ajalt Feb 15, 2024
d119578
Support hetergeneous context types
ajalt Feb 15, 2024
b368d26
Add website docs for progress bars
ajalt Feb 15, 2024
8cba682
Dump API
ajalt Feb 15, 2024
53c25d8
Enable dokka multi-module
ajalt Feb 16, 2024
91a6cdb
Add more progress tutorials
ajalt Feb 16, 2024
a64c2f4
Fix test
ajalt Feb 17, 2024
6a4a991
Dump api
ajalt Feb 17, 2024
e21cb22
Deprecate old progress DSLs
ajalt Feb 17, 2024
e3e50c3
Dump API
ajalt Feb 17, 2024
7b5362f
Add screenshot for hexviewer sample
ajalt Feb 17, 2024
808f4f6
Fix R8 test
ajalt Feb 18, 2024
d9c57ee
Remove obsolete flaky test
ajalt Feb 18, 2024
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
3 changes: 2 additions & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: Test and Publish
name: Build

on:
pull_request:
Expand Down Expand Up @@ -37,6 +37,7 @@ jobs:
with:
arguments: |
:mordant:check
:extensions:mordant-coroutines:jvmTest
:test:proguard:r8jar
${{matrix.EXTRA_GRADLE_ARGS}}
--stacktrace
Expand Down
22 changes: 20 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,31 @@
# Changelog

## Unreleased
### Added
- New implementation of progress bars with a number of improvements:
- Any widget can be added to a progress layout, not just the built-in cell types
- TODO New cell: timeElapsed
- Added `compact` style to `timeRemaining` cells.
- Added `marquee` cell that can scroll text that is larger than a fixed width.
- Added `Viewport` widget that can crop or pad another widget to a fixed size, and scroll it within that size.
- Added `precision` parameter to `completed` progress cell that controls the number of decimal places shown.
- Animation now handle terminal resizing, although on some terminals, partially drawn frames may be visible. Due to a bug in JNI, the terminal size isn't automatically updated on JVM on macOS.
- Added `TableBuilder.addPaddingWidthToFixedWidth` option to control how padding is added to fixed width columns.

### Changed
- Animations now never add a trailing newline while they're running. They always add one once the animation is stopped. The `trailNewline` parameter is deprecated. This allows full screen animations without a blank line at the bottom.

### Fixed
- Vertical layout now correctly pads non-text cells when `align` is set to `TextAlign.LEFT`

## 2.3.0
### Added
- Vararg constructors for `UnorderedList` and `OrderedList`
- `UnorderedList` and `OrderedList` now support being empty
- `UnorderedList` and `OrderedList` now support being empty
- Added optional terminal frame to `TerminalRecorder.outputAsHtml`

### Changed
- When setting conflicting styles on a `Table` or its cells, the innermost style now takes precedence (i.e. if you set different styles on the whole table and a cell, the style applied to the cell will be used).
- When setting conflicting styles on a `Table` or its cells, the innermost style now takes precedence (i.e. if you set different styles on the whole table and a cell, the style applied to the cell will be used).

### Fixed
- Updated bundled proguard rules [(#130)](https://github.com/ajalt/mordant/issues/130)
Expand Down
15 changes: 15 additions & 0 deletions build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,9 +1,24 @@
import org.jetbrains.dokka.gradle.DokkaMultiModuleTask
import org.jetbrains.dokka.gradle.DokkaTask

plugins {
alias(libs.plugins.kotlinBinaryCompatibilityValidator)
id("org.jetbrains.dokka")
}

apiValidation {
// https://github.com/Kotlin/binary-compatibility-validator/issues/3
project("samples").subprojects.mapTo(ignoredProjects) { it.name }
project("test").subprojects.mapTo(ignoredProjects) { it.name }
}

tasks.withType<DokkaMultiModuleTask>().configureEach {
outputDirectory.set(rootProject.rootDir.resolve("docs/api"))
pluginsMapConfiguration.set(
mapOf(
"org.jetbrains.dokka.base.DokkaBase" to """{
"footerMessage": "Copyright &copy; 2017 AJ Alt"
}"""
)
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,8 @@ kotlin {
jvm { withJava() }

sourceSets {
val jvmMain by getting {
dependencies {
implementation(project(":mordant"))
}
jvmMain.dependencies {
implementation(project(":mordant"))
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,11 @@ plugins {
id("mordant-jvm-sample-conventions")
id("mordant-native-sample-conventions")
}

kotlin {
sourceSets {
commonMain.dependencies {
implementation(project(":mordant"))
}
}
}
14 changes: 3 additions & 11 deletions buildSrc/src/main/kotlin/mordant-publishing-conventions.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import com.vanniktech.maven.publish.JavadocJar
import com.vanniktech.maven.publish.KotlinMultiplatform
import com.vanniktech.maven.publish.SonatypeHost
import org.jetbrains.dokka.gradle.DokkaTask
import org.jetbrains.dokka.gradle.DokkaTaskPartial
import java.io.ByteArrayOutputStream

plugins {
Expand Down Expand Up @@ -35,22 +36,13 @@ fun getPublishVersion(): String {
mavenPublishing {
project.setProperty("VERSION_NAME", getPublishVersion())
pomFromGradleProperties()
configure(KotlinMultiplatform(JavadocJar.Dokka("dokkaHtml")))
configure(KotlinMultiplatform(JavadocJar.Dokka("dokkaHtmlPartial")))
publishToMavenCentral(SonatypeHost.DEFAULT)
signAllPublications()
}

tasks.named<DokkaTask>("dokkaHtml") {
outputDirectory.set(rootProject.rootDir.resolve("docs/api"))
pluginsMapConfiguration.set(
mapOf(
"org.jetbrains.dokka.base.DokkaBase" to """{
"footerMessage": "Copyright &copy; 2017 AJ Alt"
}"""
)
)
tasks.withType<DokkaTaskPartial>().configureEach {
dokkaSourceSets.configureEach {
reportUndocumented.set(false)
skipDeprecated.set(true)
}
}
Expand Down
2 changes: 1 addition & 1 deletion deploy_website.sh
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
set -ex

# Generate API docs
./gradlew dokkaHtml
./gradlew dokkaHtmlMultiModule

# Copy the changelog into the site, omitting the unreleased section
cat CHANGELOG.md \
Expand Down
47 changes: 11 additions & 36 deletions docs/guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -370,61 +370,34 @@ t.cursor.hide(showOnExit = true)
## Animations

You can animate any widget like a table with [Terminal.animation], or any regular
string with [Terminal.textAnimation].
string with [Terminal.textAnimation]. For progress bar animations, see [the docs on progress
bars](progress.md).

=== "Code"
```kotlin
val t = Terminal()
val a = t.textAnimation<Int> { frame ->
val terminal = Terminal()
val a = terminal.textAnimation<Int> { frame ->
(1..50).joinToString("") {
val hue = (frame + it) * 3 % 360
TextColors.hsv(hue, 1, 1)("━")
}
}

t.cursor.hide(showOnExit = true)
terminal.cursor.hide(showOnExit = true)
repeat(120) {
a.update(it)
Thread.sleep(25)
}
```

=== "Output"
![](img/animation.svg)


## Progress bars

You can create customizable progress bars that automatically compute speed and time remaining.

=== "Code"
```kotlin
val t = Terminal()
val progress = t.progressAnimation {
text("my-file.iso")
percentage()
progressBar()
completed()
speed("B/s")
timeRemaining()
}
```
=== "Output"
<div style="border-radius: 8px;width: fit-content;padding: 0.5em 1em;filter: drop-shadow(0.5em 0.5em 0.5em black);background-color: rgb(12 12 12);">
<div style="margin: -0.5em 0px;font-size: 2em"><span style="color: #ff5f56;">●&nbsp;</span><span style="color: #ffbd2e">●&nbsp;</span><span style="color: #27c93f">●&nbsp;</span></div>
<pre style="font-family: monospace">
<span>my-file.iso</span><span> </span><span>83%</span><span> </span><span style="color: #61afef">━━━━━━</span><span style="color: #68b2f0">━</span><span style="color: #88c2f4">━</span><span style="color: #b9dbf9">━</span><span style="color: #e5f2fd">━</span><span style="color: #fcfeff">━━</span><span style="color: #e5f2fd">━</span><span style="color: #b9dbf9">━</span><span style="color: #88c2f4">━</span><span style="color: #68b2f0">━</span><span style="color: #61afef">━━</span><span> </span><span style="color: #5c6370">━━━</span><span> </span><span>25.0/30.0G</span><span> </span><span>71.2MB/s</span><span> </span><span>eta</span><span> </span><span>0:01:10</span>
</pre>
</div>

Call [progress.start] to animate the progress, and [progress.update] or [progress.advance] as your
task completes.
![](img/animation_text.gif)

!!! note
The [progressAnimation] builder is currently JVM-only - see [issue #148](https://github.com/ajalt/mordant/issues/148).
On other platforms, you can still use `t.animation { progressLayout { ... } }` which will render the same widget,
you'll just need to call [progress.build] manually.
!!! tip

If you have an `animation<Unit>` or `textAnimation<Unit>`, you can refresh them automatically with
[animateOnThread] or [animateOnCoroutine].

## Prompting for input

Expand Down Expand Up @@ -464,6 +437,8 @@ creating a subclass of the [Prompt] class. Mordant includes [StringPrompt], [Yes
[Text]: api/mordant/com.github.ajalt.mordant.widgets/-text/index.html
[Whitespace]: api/mordant/com.github.ajalt.mordant.rendering/-whitespace/index.html
[YesNoPrompt]: api/mordant/com.github.ajalt.mordant.terminal/-yes-no-prompt/index.html
[animateOnCoroutine]: api/extensions/mordant-coroutines/com.github.ajalt.mordant.animation.coroutines/animate-in-coroutine.html
[animateOnThread]: api/mordant/com.github.ajalt.mordant.animation.progress/animate-on-thread.html
[color.bg]: api/mordant/com.github.ajalt.mordant.rendering/-text-style/bg.html
[color.on]: api/mordant/com.github.ajalt.mordant.rendering/-text-style/on.html
[cursor]: api/mordant/com.github.ajalt.mordant.terminal/-terminal/cursor.html
Expand Down
Binary file added docs/img/animation_text.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file removed docs/img/complex_table.png
Binary file not shown.
Binary file removed docs/img/example_basic.png
Binary file not shown.
Binary file removed docs/img/example_bg.png
Binary file not shown.
Binary file removed docs/img/example_fg_bg.png
Binary file not shown.
Binary file removed docs/img/example_multi.png
Binary file not shown.
Binary file removed docs/img/example_nesting.png
Binary file not shown.
Binary file removed docs/img/example_progress.png
Binary file not shown.
Binary file removed docs/img/example_rgb.png
Binary file not shown.
Binary file removed docs/img/example_styles.png
Binary file not shown.
Binary file removed docs/img/markdown.png
Binary file not shown.
Binary file added docs/img/progess_simple.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/img/progress_cells.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/img/progress_context.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/img/progress_multi.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file removed docs/img/simple_table.png
Binary file not shown.
Loading
Loading