Compare commits
1 Commits
master
...
dependabot
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
206d70766b |
@@ -1,20 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "terminal-ui",
|
|
||||||
"image": "mcr.microsoft.com/devcontainers/java:1-21-bookworm",
|
|
||||||
"features": {
|
|
||||||
"ghcr.io/devcontainers/features/java:1": {
|
|
||||||
"version": "21",
|
|
||||||
"installGradle": "true",
|
|
||||||
"installMaven": "false"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"postCreateCommand": "java -version && ./gradlew --version",
|
|
||||||
"customizations": {
|
|
||||||
"vscode": {
|
|
||||||
"extensions": [
|
|
||||||
"vscjava.vscode-java-pack",
|
|
||||||
"vscjava.vscode-gradle"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
# EditorConfig: consistent style across editors
|
|
||||||
# https://editorconfig.org
|
|
||||||
|
|
||||||
root = true
|
|
||||||
|
|
||||||
[*]
|
|
||||||
charset = utf-8
|
|
||||||
end_of_line = lf
|
|
||||||
insert_final_newline = true
|
|
||||||
trim_trailing_whitespace = true
|
|
||||||
|
|
||||||
[*.{java,kts}]
|
|
||||||
indent_style = space
|
|
||||||
indent_size = 4
|
|
||||||
|
|
||||||
[*.{yml,yaml,md,json}]
|
|
||||||
indent_size = 2
|
|
||||||
|
|
||||||
[*.bat]
|
|
||||||
end_of_line = crlf
|
|
||||||
9
.gitattributes
vendored
9
.gitattributes
vendored
@@ -1,9 +0,0 @@
|
|||||||
# Normalize line endings
|
|
||||||
* text=auto eol=lf
|
|
||||||
*.bat text eol=crlf
|
|
||||||
*.cmd text eol=crlf
|
|
||||||
|
|
||||||
# GitHub linguist: don't count these as language
|
|
||||||
gradle/wrapper/gradle-wrapper.jar binary
|
|
||||||
*.jar binary
|
|
||||||
*.zip binary
|
|
||||||
27
.github/release-drafter.yml
vendored
27
.github/release-drafter.yml
vendored
@@ -1,27 +0,0 @@
|
|||||||
# Config for release-drafter v6: categorizes PRs in draft release notes
|
|
||||||
# https://github.com/release-drafter/release-drafter
|
|
||||||
|
|
||||||
template: |
|
|
||||||
## What's Changed
|
|
||||||
|
|
||||||
$CHANGES
|
|
||||||
|
|
||||||
**Full Changelog**: https://github.com/jakubbbdev/terminal-ui/compare/$PREVIOUS_TAG...v$RESOLVED_VERSION
|
|
||||||
|
|
||||||
name-template: 'v$RESOLVED_VERSION'
|
|
||||||
tag-template: 'v$RESOLVED_VERSION'
|
|
||||||
|
|
||||||
categories:
|
|
||||||
- title: '🚀 Features'
|
|
||||||
labels: [feature, enhancement]
|
|
||||||
- title: '🐛 Bug Fixes'
|
|
||||||
labels: [bug, fix]
|
|
||||||
- title: '📚 Documentation'
|
|
||||||
labels: [documentation]
|
|
||||||
- title: '⬆️ Dependencies'
|
|
||||||
labels: [dependencies]
|
|
||||||
- title: 'Other'
|
|
||||||
labels: ['*']
|
|
||||||
|
|
||||||
exclude-labels:
|
|
||||||
- skip-changelog
|
|
||||||
1
.github/workflows/ci.yml
vendored
1
.github/workflows/ci.yml
vendored
@@ -6,6 +6,7 @@ on:
|
|||||||
pull_request:
|
pull_request:
|
||||||
branches: [ main, master ]
|
branches: [ main, master ]
|
||||||
|
|
||||||
|
# Alte Läufe abbrechen, wenn ein neuer Push kommt (spart Zeit)
|
||||||
concurrency:
|
concurrency:
|
||||||
group: ${{ github.workflow }}-${{ github.ref }}
|
group: ${{ github.workflow }}-${{ github.ref }}
|
||||||
cancel-in-progress: true
|
cancel-in-progress: true
|
||||||
|
|||||||
35
.github/workflows/codeql.yml
vendored
Normal file
35
.github/workflows/codeql.yml
vendored
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
# CodeQL: static security analysis (free for public repos).
|
||||||
|
name: CodeQL
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [ main, master ]
|
||||||
|
pull_request:
|
||||||
|
branches: [ main, master ]
|
||||||
|
schedule:
|
||||||
|
- cron: '0 6 * * 1'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
analyze:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
permissions:
|
||||||
|
security-events: write
|
||||||
|
actions: read
|
||||||
|
contents: read
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Initialize CodeQL
|
||||||
|
uses: github/codeql-action/init@v3
|
||||||
|
with:
|
||||||
|
languages: java
|
||||||
|
|
||||||
|
- name: Build (for CodeQL)
|
||||||
|
run: |
|
||||||
|
chmod +x gradlew
|
||||||
|
./gradlew compileJava --no-daemon
|
||||||
|
|
||||||
|
- name: Perform CodeQL Analysis
|
||||||
|
uses: github/codeql-action/analyze@v3
|
||||||
53
.github/workflows/pages.yml
vendored
53
.github/workflows/pages.yml
vendored
@@ -1,53 +0,0 @@
|
|||||||
# Deploy docs to GitHub Pages (optional)
|
|
||||||
# Enable in repo: Settings → Pages → Source: GitHub Actions
|
|
||||||
# Site will be at https://jakubbbdev.github.io/terminal-ui/
|
|
||||||
|
|
||||||
name: Pages
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches: [master, main]
|
|
||||||
workflow_dispatch:
|
|
||||||
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
pages: write
|
|
||||||
id-token: write
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
deploy:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
environment: github-pages
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Setup Pages
|
|
||||||
uses: actions/configure-pages@v4
|
|
||||||
|
|
||||||
- name: Build site
|
|
||||||
run: |
|
|
||||||
mkdir -p _site
|
|
||||||
cp -r docs _site/
|
|
||||||
cat > _site/index.html << 'EOF'
|
|
||||||
<!DOCTYPE html>
|
|
||||||
<html><head><meta charset="utf-8"><title>terminal-ui</title></head>
|
|
||||||
<body style="font-family:sans-serif;max-width:600px;margin:2rem auto;padding:0 1rem">
|
|
||||||
<h1>terminal-ui</h1>
|
|
||||||
<p>Java library for terminal UIs: tables, prompts, menus, and more.</p>
|
|
||||||
<ul>
|
|
||||||
<li><a href="https://github.com/jakubbbdev/terminal-ui">GitHub repo</a></li>
|
|
||||||
<li><a href="https://github.com/jakubbbdev/terminal-ui#install">Install (README)</a></li>
|
|
||||||
<li><a href="https://github.com/jakubbbdev/terminal-ui/releases">Releases</a></li>
|
|
||||||
<li><a href="https://github.com/jakubbbdev/terminal-ui/tree/master/docs">Docs (markdown)</a></li>
|
|
||||||
</ul>
|
|
||||||
</body></html>
|
|
||||||
EOF
|
|
||||||
|
|
||||||
- name: Upload artifact
|
|
||||||
uses: actions/upload-pages-artifact@v3
|
|
||||||
with:
|
|
||||||
path: _site
|
|
||||||
|
|
||||||
- name: Deploy to GitHub Pages
|
|
||||||
id: deployment
|
|
||||||
uses: actions/deploy-pages@v4
|
|
||||||
22
.github/workflows/release-drafter.yml
vendored
22
.github/workflows/release-drafter.yml
vendored
@@ -1,22 +0,0 @@
|
|||||||
# Drafts release notes from merged PRs when you create a release.
|
|
||||||
# Install: add a Release Drafter config (see below), then create a release on GitHub;
|
|
||||||
# this workflow will update the draft with categorized PRs.
|
|
||||||
name: Release Drafter
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches: [main, master]
|
|
||||||
workflow_dispatch:
|
|
||||||
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
pull-requests: write
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
update_release_draft:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Draft Release
|
|
||||||
uses: release-drafter/release-drafter@v6
|
|
||||||
env:
|
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
18
.github/workflows/release.yml
vendored
18
.github/workflows/release.yml
vendored
@@ -1,4 +1,4 @@
|
|||||||
# On push of a version tag (e.g. v1.0.0): build, publish to GitHub Packages, create Release, upload JARs.
|
# On push of a version tag (e.g. v1.0.0): build, create GitHub Release, upload JARs.
|
||||||
name: Release
|
name: Release
|
||||||
|
|
||||||
on:
|
on:
|
||||||
@@ -8,13 +8,10 @@ on:
|
|||||||
|
|
||||||
permissions:
|
permissions:
|
||||||
contents: write
|
contents: write
|
||||||
packages: write
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
release:
|
release:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
env:
|
|
||||||
RELEASE_VERSION: ${{ github.ref_name }}
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
@@ -26,18 +23,7 @@ jobs:
|
|||||||
java-version: 21
|
java-version: 21
|
||||||
cache: gradle
|
cache: gradle
|
||||||
|
|
||||||
- name: Strip v from version
|
- run: chmod +x gradlew && ./gradlew build --no-daemon
|
||||||
run: echo "RELEASE_VERSION=${RELEASE_VERSION#v}" >> $GITHUB_ENV
|
|
||||||
|
|
||||||
- name: Build
|
|
||||||
run: chmod +x gradlew && ./gradlew build --no-daemon
|
|
||||||
|
|
||||||
- name: Publish to GitHub Packages
|
|
||||||
run: ./gradlew publish --no-daemon
|
|
||||||
env:
|
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
continue-on-error: true
|
|
||||||
# 409 = version already exists; use a new tag (e.g. v1.0.2) next time
|
|
||||||
|
|
||||||
- name: Create Release
|
- name: Create Release
|
||||||
uses: softprops/action-gh-release@v2
|
uses: softprops/action-gh-release@v2
|
||||||
|
|||||||
3
.idea/misc.xml
generated
3
.idea/misc.xml
generated
@@ -1,9 +1,10 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<project version="4">
|
<project version="4">
|
||||||
<component name="ExternalStorageConfigurationManager" enabled="true" />
|
<component name="ExternalStorageConfigurationManager" enabled="true" />
|
||||||
<component name="FrameworkDetectionExcludesConfiguration">
|
<component name="FrameworkDetectionExcludesConfiguration">
|
||||||
<file type="web" url="file://$PROJECT_DIR$" />
|
<file type="web" url="file://$PROJECT_DIR$" />
|
||||||
</component>
|
</component>
|
||||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_21" default="true" project-jdk-name="corretto-21" project-jdk-type="JavaSDK">
|
<component name="ProjectRootManager" version="2" languageLevel="JDK_17" project-jdk-name="corretto-21" project-jdk-type="JavaSDK">
|
||||||
<output url="file://$PROJECT_DIR$/out" />
|
<output url="file://$PROJECT_DIR$/out" />
|
||||||
</component>
|
</component>
|
||||||
</project>
|
</project>
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
# Code of Conduct
|
|
||||||
|
|
||||||
## Our Pledge
|
|
||||||
|
|
||||||
We are committed to providing a welcoming and harassment-free experience for everyone. Be respectful, inclusive, and constructive when contributing or discussing this project.
|
|
||||||
|
|
||||||
## Unacceptable Behavior
|
|
||||||
|
|
||||||
Harassment, trolling, insulting comments, personal or political attacks, and other conduct that could make others feel unsafe are not acceptable.
|
|
||||||
|
|
||||||
## Enforcement
|
|
||||||
|
|
||||||
Maintainers may remove or edit content that violates this code. Repeated or serious violations may result in being blocked from the repository.
|
|
||||||
|
|
||||||
## Contact
|
|
||||||
|
|
||||||
If you have concerns, open an issue or contact the maintainers privately if preferred.
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
# Optional: Uncomment to show "Sponsor" button on the repo
|
|
||||||
# github: [jakubbbdev]
|
|
||||||
# patreon: your-username
|
|
||||||
# ko_fi: your-username
|
|
||||||
# custom: ['https://your-link.com']
|
|
||||||
43
Jenkinsfile
vendored
43
Jenkinsfile
vendored
@@ -1,43 +0,0 @@
|
|||||||
pipeline {
|
|
||||||
agent any
|
|
||||||
|
|
||||||
environment {
|
|
||||||
GITHUB_ACTOR = 'jakubbbdev'
|
|
||||||
GITHUB_TOKEN = credentials('github-credentials')
|
|
||||||
}
|
|
||||||
|
|
||||||
stages {
|
|
||||||
stage('Checkout') {
|
|
||||||
steps {
|
|
||||||
checkout scm
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
stage('Build') {
|
|
||||||
steps {
|
|
||||||
sh 'chmod +x gradlew && ./gradlew build'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
stage('Test') {
|
|
||||||
steps {
|
|
||||||
sh './gradlew test'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
stage('Publish') {
|
|
||||||
steps {
|
|
||||||
sh './gradlew publish'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
post {
|
|
||||||
success {
|
|
||||||
echo '✅ Build erfolgreich!'
|
|
||||||
}
|
|
||||||
failure {
|
|
||||||
echo '❌ Build fehlgeschlagen!'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
57
README.md
57
README.md
@@ -3,51 +3,6 @@
|
|||||||
Java library for terminal UI: tables, rules, colors, prompts, menus, SelectList, pager, and more. Fluent API, ANSI support, testable.
|
Java library for terminal UI: tables, rules, colors, prompts, menus, SelectList, pager, and more. Fluent API, ANSI support, testable.
|
||||||
|
|
||||||
[](https://github.com/jakubbbdev/terminal-ui/actions/workflows/ci.yml)
|
[](https://github.com/jakubbbdev/terminal-ui/actions/workflows/ci.yml)
|
||||||
[](https://openjdk.org/)
|
|
||||||
[](LICENSE)
|
|
||||||
[](https://github.com/jakubbbdev/terminal-ui/releases)
|
|
||||||
|
|
||||||
[](https://codespaces.new/jakubbbdev/terminal-ui)
|
|
||||||
|
|
||||||
## Install
|
|
||||||
|
|
||||||
**Gradle (Kotlin DSL):**
|
|
||||||
|
|
||||||
```kotlin
|
|
||||||
repositories {
|
|
||||||
mavenCentral()
|
|
||||||
maven { url = uri("https://maven.pkg.github.com/jakubbbdev/terminal-ui") }
|
|
||||||
}
|
|
||||||
dependencies {
|
|
||||||
implementation("dev.jakub.terminal:terminal-ui:VERSION")
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
**Gradle (Groovy):**
|
|
||||||
|
|
||||||
```groovy
|
|
||||||
repositories {
|
|
||||||
mavenCentral()
|
|
||||||
maven { url "https://maven.pkg.github.com/jakubbbdev/terminal-ui" }
|
|
||||||
}
|
|
||||||
dependencies {
|
|
||||||
implementation "dev.jakub.terminal:terminal-ui:VERSION"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
**Maven:**
|
|
||||||
|
|
||||||
```xml
|
|
||||||
<repository>
|
|
||||||
<id>github</id>
|
|
||||||
<url>https://maven.pkg.github.com/jakubbbdev/terminal-ui</url>
|
|
||||||
</repository>
|
|
||||||
<dependency>
|
|
||||||
<groupId>dev.jakub.terminal</groupId>
|
|
||||||
<artifactId>terminal-ui</artifactId>
|
|
||||||
<version>VERSION</version>
|
|
||||||
</dependency>
|
|
||||||
```
|
|
||||||
|
|
||||||
## Requirements
|
## Requirements
|
||||||
|
|
||||||
@@ -66,6 +21,18 @@ Run tests:
|
|||||||
./gradlew test
|
./gradlew test
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Demo (non-interactive):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./gradlew run
|
||||||
|
```
|
||||||
|
|
||||||
|
Interactive demo (best run in a real terminal):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./gradlew runDemo2
|
||||||
|
```
|
||||||
|
|
||||||
## Usage (excerpt)
|
## Usage (excerpt)
|
||||||
|
|
||||||
```java
|
```java
|
||||||
|
|||||||
11
SECURITY.md
11
SECURITY.md
@@ -1,11 +0,0 @@
|
|||||||
# Security
|
|
||||||
|
|
||||||
## Reporting a vulnerability
|
|
||||||
|
|
||||||
If you find a security issue, please report it responsibly:
|
|
||||||
|
|
||||||
1. **Do not** open a public issue.
|
|
||||||
2. Email the maintainers or report via [GitHub Security Advisories](https://github.com/jakubbbdev/terminal-ui/security/advisories/new) (if enabled).
|
|
||||||
3. Give a clear description and steps to reproduce; we’ll respond as soon as we can.
|
|
||||||
|
|
||||||
Thank you for helping keep this project safe.
|
|
||||||
@@ -2,19 +2,15 @@ plugins {
|
|||||||
id("java")
|
id("java")
|
||||||
id("java-library")
|
id("java-library")
|
||||||
id("application")
|
id("application")
|
||||||
id("maven-publish")
|
|
||||||
}
|
|
||||||
|
|
||||||
application {
|
|
||||||
mainClass.set("dev.jakub.terminal.example.Examples")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks.named<JavaExec>("run") {
|
tasks.named<JavaExec>("run") {
|
||||||
jvmArgs("-Ddev.jakub.terminal.ansi=true", "-Dfile.encoding=UTF-8")
|
jvmArgs("-Ddev.jakub.terminal.ansi=true", "-Dfile.encoding=UTF-8")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
group = "dev.jakub.terminal"
|
group = "dev.jakub.terminal"
|
||||||
version = System.getenv("RELEASE_VERSION") ?: "1.0-SNAPSHOT"
|
version = "1.0-SNAPSHOT"
|
||||||
|
|
||||||
java {
|
java {
|
||||||
sourceCompatibility = JavaVersion.VERSION_21
|
sourceCompatibility = JavaVersion.VERSION_21
|
||||||
@@ -34,24 +30,3 @@ dependencies {
|
|||||||
tasks.test {
|
tasks.test {
|
||||||
useJUnitPlatform()
|
useJUnitPlatform()
|
||||||
}
|
}
|
||||||
|
|
||||||
publishing {
|
|
||||||
publications {
|
|
||||||
create<MavenPublication>("maven") {
|
|
||||||
groupId = project.group.toString()
|
|
||||||
artifactId = "terminal-ui"
|
|
||||||
version = project.version.toString()
|
|
||||||
from(components["java"])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
repositories {
|
|
||||||
maven {
|
|
||||||
name = "GitHubPackages"
|
|
||||||
url = uri("https://maven.pkg.github.com/jakubbbdev/terminal-ui")
|
|
||||||
credentials {
|
|
||||||
username = System.getenv("GITHUB_ACTOR") ?: project.findProperty("gpr.user")?.toString()
|
|
||||||
password = System.getenv("GITHUB_TOKEN") ?: project.findProperty("gpr.token")?.toString()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,71 +0,0 @@
|
|||||||
# Components
|
|
||||||
|
|
||||||
Overview of what terminal-ui provides. All entry points are on `Terminal.*`.
|
|
||||||
|
|
||||||
## Output & text
|
|
||||||
|
|
||||||
| API | Description |
|
|
||||||
|-----|-------------|
|
|
||||||
| `Terminal.print(String)` | Styled text (chain `.color()`, `.bold()`, `.println()`) |
|
|
||||||
| `Terminal.rule()` | Horizontal rule (e.g. `====`) |
|
|
||||||
| `Terminal.keyValue()` | Key-value pairs |
|
|
||||||
| `Terminal.box()` | Box around content |
|
|
||||||
|
|
||||||
## Tables & layout
|
|
||||||
|
|
||||||
| API | Description |
|
|
||||||
|-----|-------------|
|
|
||||||
| `Terminal.table()` | Tables with header/rows |
|
|
||||||
| `Terminal.tree()` | Tree structure |
|
|
||||||
| `Terminal.columns()` | Multi-column layout |
|
|
||||||
| `Terminal.steps()` | Step indicator |
|
|
||||||
| `Terminal.breadcrumb()` | Breadcrumb trail |
|
|
||||||
| `Terminal.toc()` | Table of contents |
|
|
||||||
|
|
||||||
## Interactive
|
|
||||||
|
|
||||||
| API | Description |
|
|
||||||
|-----|-------------|
|
|
||||||
| `Terminal.prompt(String)` | Text input (`.ask()`, `.masked().ask()`, `.validate(Predicate).retryMessage(String)`) |
|
|
||||||
| `Terminal.confirm(String)` | Y/n confirmation |
|
|
||||||
| `Terminal.menu()` | Numbered menu (`.option()`, `.select()`) |
|
|
||||||
| `Terminal.selectList()` | List with arrow keys + Enter |
|
|
||||||
| `Terminal.pager()` | Paged output (Enter/arrows/q) |
|
|
||||||
| `Terminal.help()` | CLI usage block (`.option(opt, desc)`, `.title()`) |
|
|
||||||
|
|
||||||
## Live / progress
|
|
||||||
|
|
||||||
| API | Description |
|
|
||||||
|-----|-------------|
|
|
||||||
| `Terminal.progressBar()` | Progress bar (`.total()`, `.build()`) |
|
|
||||||
| `Terminal.spinner()` | Spinning indicator (`.message()`, `.start()`) |
|
|
||||||
| `Terminal.dashboard()` | Refreshing widget panel |
|
|
||||||
|
|
||||||
## Data & visuals
|
|
||||||
|
|
||||||
| API | Description |
|
|
||||||
|-----|-------------|
|
|
||||||
| `Terminal.diff()` | Diff view |
|
|
||||||
| `Terminal.log()` | Log-style output |
|
|
||||||
| `Terminal.timeline()` | Timeline |
|
|
||||||
| `Terminal.heatmap()` | Heatmap |
|
|
||||||
| `Terminal.chart()` | Charts |
|
|
||||||
|
|
||||||
## Terminal control (ANSI)
|
|
||||||
|
|
||||||
| API | Description |
|
|
||||||
|-----|-------------|
|
|
||||||
| `Terminal.clearScreen()` | Clear entire screen |
|
|
||||||
| `Terminal.cursorTo(row, col)` | Move cursor (1-based) |
|
|
||||||
|
|
||||||
## Other
|
|
||||||
|
|
||||||
| API | Description |
|
|
||||||
|-----|-------------|
|
|
||||||
| `Terminal.badge(String, Color)` | Colored badge |
|
|
||||||
| `Terminal.notify(String, Type)` | Notification (info/success/warning/error) |
|
|
||||||
| `Terminal.code(String)` | Code block with language |
|
|
||||||
| `Terminal.sysinfo()` | System info (OS, Java, etc.) |
|
|
||||||
| `Terminal.markdown(String)` | Render markdown to terminal |
|
|
||||||
|
|
||||||
Use the fluent API from `Terminal.*`. For tests or to disable ANSI, inject a custom `TerminalSupport`.
|
|
||||||
314
docs/Examples.md
314
docs/Examples.md
@@ -1,314 +0,0 @@
|
|||||||
# Examples
|
|
||||||
|
|
||||||
All examples use `import dev.jakub.terminal.Terminal;` and `import dev.jakub.terminal.core.Color;` where needed. Use `System.out` or omit the argument where `.print()` has a no-arg overload.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Text & rules
|
|
||||||
|
|
||||||
```java
|
|
||||||
Terminal.print("Hello").color(Color.CYAN).bold().println();
|
|
||||||
|
|
||||||
Terminal.rule().character('=').print();
|
|
||||||
Terminal.rule().doubles().prefix("-- ").suffix(" --").print();
|
|
||||||
```
|
|
||||||
|
|
||||||
## Key-value & box
|
|
||||||
|
|
||||||
```java
|
|
||||||
Terminal.keyValue()
|
|
||||||
.row("Name", "terminal-ui")
|
|
||||||
.row("Version", "1.0")
|
|
||||||
.separator(" = ")
|
|
||||||
.print(System.out);
|
|
||||||
|
|
||||||
Terminal.box()
|
|
||||||
.title("Info")
|
|
||||||
.line("First line")
|
|
||||||
.lines("Second", "Third")
|
|
||||||
.print(System.out);
|
|
||||||
```
|
|
||||||
|
|
||||||
## Table
|
|
||||||
|
|
||||||
```java
|
|
||||||
Terminal.table()
|
|
||||||
.header("Col A", "Col B", "Col C")
|
|
||||||
.row("1", "2", "3")
|
|
||||||
.row("4", "5", "6")
|
|
||||||
.print(System.out);
|
|
||||||
|
|
||||||
// From a list of rows (e.g. from CSV or DB)
|
|
||||||
List<String[]> rows = List.of(
|
|
||||||
new String[]{"Alice", "10"},
|
|
||||||
new String[]{"Bob", "20"}
|
|
||||||
);
|
|
||||||
Terminal.table()
|
|
||||||
.header("Name", "Score")
|
|
||||||
.rows(rows)
|
|
||||||
.print(System.out);
|
|
||||||
|
|
||||||
// One-liner with header + data
|
|
||||||
Terminal.table()
|
|
||||||
.fromRows(new String[]{"A", "B"}, List.of(new String[]{"1", "2"}, new String[]{"3", "4"}))
|
|
||||||
.print(System.out);
|
|
||||||
```
|
|
||||||
|
|
||||||
## Tree
|
|
||||||
|
|
||||||
```java
|
|
||||||
Terminal.tree()
|
|
||||||
.node("root")
|
|
||||||
.child("src")
|
|
||||||
.child("main").end()
|
|
||||||
.child("test").end()
|
|
||||||
.end()
|
|
||||||
.child("docs")
|
|
||||||
.end()
|
|
||||||
.print(System.out);
|
|
||||||
```
|
|
||||||
|
|
||||||
## Columns
|
|
||||||
|
|
||||||
```java
|
|
||||||
Terminal.columns()
|
|
||||||
.column("Left\ncolumn\ntext")
|
|
||||||
.column("Middle")
|
|
||||||
.column("Right")
|
|
||||||
.print(System.out);
|
|
||||||
```
|
|
||||||
|
|
||||||
## Steps (wizard-style)
|
|
||||||
|
|
||||||
```java
|
|
||||||
Terminal.steps()
|
|
||||||
.step("Setup", Steps.Status.DONE)
|
|
||||||
.step("Build", Steps.Status.RUNNING)
|
|
||||||
.step("Deploy", Steps.Status.PENDING)
|
|
||||||
.print(System.out);
|
|
||||||
```
|
|
||||||
|
|
||||||
(Use `import dev.jakub.terminal.components.Steps;` for `Steps.Status`.)
|
|
||||||
|
|
||||||
## Breadcrumb
|
|
||||||
|
|
||||||
```java
|
|
||||||
Terminal.breadcrumb()
|
|
||||||
.crumb("Home")
|
|
||||||
.crumb("Projects")
|
|
||||||
.crumb("terminal-ui")
|
|
||||||
.separator(" / ")
|
|
||||||
.print(System.out);
|
|
||||||
```
|
|
||||||
|
|
||||||
## Interactive: Prompt
|
|
||||||
|
|
||||||
```java
|
|
||||||
String name = Terminal.prompt("Name: ").ask();
|
|
||||||
String secret = Terminal.prompt("Password: ").masked().ask();
|
|
||||||
// With shared scanner (e.g. in a loop):
|
|
||||||
String line = Terminal.prompt("Input: ").ask(sharedScanner);
|
|
||||||
|
|
||||||
// With validation (asks again until input matches):
|
|
||||||
String age = Terminal.prompt("Age: ").validate(s -> s.matches("\\d+")).ask();
|
|
||||||
String email = Terminal.prompt("Email: ")
|
|
||||||
.validate(s -> s.contains("@"))
|
|
||||||
.retryMessage("Invalid email, try again: ")
|
|
||||||
.ask();
|
|
||||||
```
|
|
||||||
|
|
||||||
## Interactive: Confirm
|
|
||||||
|
|
||||||
```java
|
|
||||||
boolean yes = Terminal.confirm("Continue?").defaultYes().ask();
|
|
||||||
boolean no = Terminal.confirm("Delete?").defaultNo().ask();
|
|
||||||
boolean answer = Terminal.confirm("Proceed?").ask(sharedScanner);
|
|
||||||
```
|
|
||||||
|
|
||||||
## Interactive: Menu
|
|
||||||
|
|
||||||
```java
|
|
||||||
String env = Terminal.menu()
|
|
||||||
.title("Choose environment")
|
|
||||||
.option("Development")
|
|
||||||
.option("Staging")
|
|
||||||
.option("Production")
|
|
||||||
.select();
|
|
||||||
```
|
|
||||||
|
|
||||||
## Interactive: SelectList (arrows + Enter)
|
|
||||||
|
|
||||||
```java
|
|
||||||
String choice = Terminal.selectList()
|
|
||||||
.title("Pick one")
|
|
||||||
.option("Option A")
|
|
||||||
.option("Option B")
|
|
||||||
.option("Option C")
|
|
||||||
.select();
|
|
||||||
```
|
|
||||||
|
|
||||||
## Interactive: Pager
|
|
||||||
|
|
||||||
```java
|
|
||||||
Terminal.pager()
|
|
||||||
.lines("Line 1", "Line 2", "Line 3", "Line 4", "Line 5")
|
|
||||||
.pageSize(3)
|
|
||||||
.interactive();
|
|
||||||
```
|
|
||||||
|
|
||||||
## Progress bar
|
|
||||||
|
|
||||||
```java
|
|
||||||
ProgressBar bar = Terminal.progressBar()
|
|
||||||
.total(100)
|
|
||||||
.width(40)
|
|
||||||
.style(ProgressBar.Style.BLOCK)
|
|
||||||
.build();
|
|
||||||
for (int i = 0; i <= 100; i++) {
|
|
||||||
bar.update(i);
|
|
||||||
Thread.sleep(30);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
(Use `import dev.jakub.terminal.live.ProgressBar;`.)
|
|
||||||
|
|
||||||
## Spinner
|
|
||||||
|
|
||||||
```java
|
|
||||||
Spinner spin = Terminal.spinner().message("Loading...").start();
|
|
||||||
// ... do work ...
|
|
||||||
spin.stop();
|
|
||||||
```
|
|
||||||
|
|
||||||
(Use `import dev.jakub.terminal.live.Spinner;`.)
|
|
||||||
|
|
||||||
## Diff
|
|
||||||
|
|
||||||
```java
|
|
||||||
Terminal.diff()
|
|
||||||
.before("old line 1\nold line 2")
|
|
||||||
.after("new line 1\nnew line 2\nnew line 3")
|
|
||||||
.print(System.out);
|
|
||||||
```
|
|
||||||
|
|
||||||
## Log
|
|
||||||
|
|
||||||
```java
|
|
||||||
Terminal.log()
|
|
||||||
.info("Started")
|
|
||||||
.warn("Deprecation notice")
|
|
||||||
.error("Something failed")
|
|
||||||
.withTimestamp()
|
|
||||||
.print(System.out);
|
|
||||||
|
|
||||||
// Only WARN and ERROR (e.g. for production)
|
|
||||||
Terminal.log()
|
|
||||||
.info("Hidden")
|
|
||||||
.warn("Visible")
|
|
||||||
.error("Visible")
|
|
||||||
.minLevel(Log.Level.WARN)
|
|
||||||
.print(System.out);
|
|
||||||
```
|
|
||||||
|
|
||||||
(Use `import dev.jakub.terminal.components.Log;` for `Log.Level`.)
|
|
||||||
|
|
||||||
## Timeline
|
|
||||||
|
|
||||||
```java
|
|
||||||
Terminal.timeline()
|
|
||||||
.event("2024-01-01", "First release")
|
|
||||||
.event("2024-06-01", "Added SelectList")
|
|
||||||
.event("2025-01-01", "GitHub Packages")
|
|
||||||
.print(System.out);
|
|
||||||
```
|
|
||||||
|
|
||||||
## Heatmap
|
|
||||||
|
|
||||||
```java
|
|
||||||
Terminal.heatmap()
|
|
||||||
.row("Mon", 10, 20, 5, 30)
|
|
||||||
.row("Tue", 15, 25, 10, 20)
|
|
||||||
.row("Wed", 5, 15, 25, 35)
|
|
||||||
.print(System.out);
|
|
||||||
```
|
|
||||||
|
|
||||||
## Chart (sparkline / bar)
|
|
||||||
|
|
||||||
```java
|
|
||||||
Terminal.chart()
|
|
||||||
.data(1.0, 2.0, 1.5, 3.0, 2.5)
|
|
||||||
.height(5)
|
|
||||||
.print(System.out);
|
|
||||||
```
|
|
||||||
|
|
||||||
## Badge & notification
|
|
||||||
|
|
||||||
```java
|
|
||||||
Terminal.badge("OK", Color.GREEN).println();
|
|
||||||
Terminal.badge("WARN", Color.YELLOW).print(System.out);
|
|
||||||
|
|
||||||
Terminal.notify("Done!", Notification.Type.SUCCESS);
|
|
||||||
Terminal.notify("Warning", Notification.Type.WARNING);
|
|
||||||
Terminal.notify("Error", Notification.Type.ERROR);
|
|
||||||
Terminal.notify("Info", Notification.Type.INFO);
|
|
||||||
```
|
|
||||||
|
|
||||||
(Use `import dev.jakub.terminal.components.Notification;`.)
|
|
||||||
|
|
||||||
## Code block
|
|
||||||
|
|
||||||
```java
|
|
||||||
Terminal.code("java")
|
|
||||||
.line("public static void main(String[] args) {")
|
|
||||||
.line(" System.out.println(\"Hello\");")
|
|
||||||
.line("}")
|
|
||||||
.lineNumbers()
|
|
||||||
.print(System.out);
|
|
||||||
```
|
|
||||||
|
|
||||||
## Help (CLI usage)
|
|
||||||
|
|
||||||
```java
|
|
||||||
Terminal.help()
|
|
||||||
.title("Options")
|
|
||||||
.option("-v, --verbose", "Enable verbose output")
|
|
||||||
.option("-h, --help", "Show this help")
|
|
||||||
.option("--file <path>", "Input file path")
|
|
||||||
.print(System.out);
|
|
||||||
```
|
|
||||||
|
|
||||||
## Clear screen & cursor
|
|
||||||
|
|
||||||
```java
|
|
||||||
Terminal.clearScreen(); // Clear terminal (ANSI)
|
|
||||||
Terminal.cursorTo(1, 1); // Move cursor to row 1, col 1 (1-based)
|
|
||||||
```
|
|
||||||
|
|
||||||
No-op when ANSI is disabled.
|
|
||||||
|
|
||||||
## SysInfo
|
|
||||||
|
|
||||||
```java
|
|
||||||
Terminal.sysinfo().print(System.out);
|
|
||||||
```
|
|
||||||
|
|
||||||
## Markdown
|
|
||||||
|
|
||||||
```java
|
|
||||||
Terminal.markdown("# Title\n\n**Bold** and *italic*.\n\n- Item 1\n- Item 2\n\n---")
|
|
||||||
.print(System.out);
|
|
||||||
```
|
|
||||||
|
|
||||||
## Table of contents
|
|
||||||
|
|
||||||
```java
|
|
||||||
Terminal.toc()
|
|
||||||
.section("Introduction").sub("Overview").sub("Install")
|
|
||||||
.section("API").sub("Reference")
|
|
||||||
.section("Examples")
|
|
||||||
.print(System.out);
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
For more, see the [README](https://github.com/jakubbbdev/terminal-ui#usage-excerpt) and the source.
|
|
||||||
25
docs/Home.md
25
docs/Home.md
@@ -1,25 +0,0 @@
|
|||||||
# terminal-ui
|
|
||||||
|
|
||||||
Java library for building terminal UIs: tables, rules, colors, prompts, menus, SelectList, pager, and more. Fluent API, ANSI support, testable.
|
|
||||||
|
|
||||||
## Quick links
|
|
||||||
|
|
||||||
- **[Install](Install)** – Gradle / Maven dependency
|
|
||||||
- **[Components](Components)** – What's in the library
|
|
||||||
- **[Examples](Examples)** – Code snippets
|
|
||||||
|
|
||||||
## Requirements
|
|
||||||
|
|
||||||
- Java 21
|
|
||||||
- Gradle 9.x or Maven (wrapper included in repo)
|
|
||||||
|
|
||||||
## Build from source
|
|
||||||
|
|
||||||
```bash
|
|
||||||
./gradlew build
|
|
||||||
./gradlew test
|
|
||||||
```
|
|
||||||
|
|
||||||
## License
|
|
||||||
|
|
||||||
MIT – see [LICENSE](https://github.com/jakubbbdev/terminal-ui/blob/master/LICENSE) in the repo.
|
|
||||||
@@ -1,45 +0,0 @@
|
|||||||
# Install
|
|
||||||
|
|
||||||
Published to [GitHub Packages](https://github.com/jakubbbdev/terminal-ui/packages). Use a [release](https://github.com/jakubbbdev/terminal-ui/releases) version (e.g. `1.0.1`) for `VERSION`.
|
|
||||||
|
|
||||||
## Gradle (Kotlin DSL)
|
|
||||||
|
|
||||||
```kotlin
|
|
||||||
repositories {
|
|
||||||
mavenCentral()
|
|
||||||
maven { url = uri("https://maven.pkg.github.com/jakubbbdev/terminal-ui") }
|
|
||||||
}
|
|
||||||
dependencies {
|
|
||||||
implementation("dev.jakub.terminal:terminal-ui:VERSION")
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Gradle (Groovy)
|
|
||||||
|
|
||||||
```groovy
|
|
||||||
repositories {
|
|
||||||
mavenCentral()
|
|
||||||
maven { url "https://maven.pkg.github.com/jakubbbdev/terminal-ui" }
|
|
||||||
}
|
|
||||||
dependencies {
|
|
||||||
implementation "dev.jakub.terminal:terminal-ui:VERSION"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Maven
|
|
||||||
|
|
||||||
```xml
|
|
||||||
<repository>
|
|
||||||
<id>github</id>
|
|
||||||
<url>https://maven.pkg.github.com/jakubbbdev/terminal-ui</url>
|
|
||||||
</repository>
|
|
||||||
<dependency>
|
|
||||||
<groupId>dev.jakub.terminal</groupId>
|
|
||||||
<artifactId>terminal-ui</artifactId>
|
|
||||||
<version>VERSION</version>
|
|
||||||
</dependency>
|
|
||||||
```
|
|
||||||
|
|
||||||
## Auth (if required)
|
|
||||||
|
|
||||||
For public packages, resolution often works without credentials. If your build asks for auth, use a [GitHub PAT](https://github.com/settings/tokens) with `read:packages`: username = your GitHub username, password = token.
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
# terminal-ui
|
|
||||||
|
|
||||||
Java library for terminal UIs: tables, prompts, menus, and more.
|
|
||||||
|
|
||||||
- **[Home](Home)** – overview
|
|
||||||
- **[Install](Install)** – Gradle / Maven
|
|
||||||
- **[Components](Components)** – what's in the library
|
|
||||||
- **[Examples](Examples)** – runnable code snippets
|
|
||||||
|
|
||||||
[GitHub repo](https://github.com/jakubbbdev/terminal-ui) · [Releases](https://github.com/jakubbbdev/terminal-ui/releases) · [Packages](https://github.com/jakubbbdev/terminal-ui/packages)
|
|
||||||
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
Binary file not shown.
4
gradle/wrapper/gradle-wrapper.properties
vendored
4
gradle/wrapper/gradle-wrapper.properties
vendored
@@ -1,6 +1,6 @@
|
|||||||
#Fri Mar 13 15:14:45 CET 2026
|
|
||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-9.0.0-bin.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-9.4.0-bin.zip
|
||||||
|
networkTimeout=10000
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
||||||
|
|||||||
50
gradlew
vendored
Normal file → Executable file
50
gradlew
vendored
Normal file → Executable file
@@ -1,7 +1,7 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
|
||||||
#
|
#
|
||||||
# Copyright © 2015-2021 the original authors.
|
# Copyright © 2015 the original authors.
|
||||||
#
|
#
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
# you may not use this file except in compliance with the License.
|
# you may not use this file except in compliance with the License.
|
||||||
@@ -15,6 +15,8 @@
|
|||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
#
|
#
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
#
|
||||||
|
|
||||||
##############################################################################
|
##############################################################################
|
||||||
#
|
#
|
||||||
@@ -55,7 +57,7 @@
|
|||||||
# Darwin, MinGW, and NonStop.
|
# Darwin, MinGW, and NonStop.
|
||||||
#
|
#
|
||||||
# (3) This script is generated from the Groovy template
|
# (3) This script is generated from the Groovy template
|
||||||
# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
|
# https://github.com/gradle/gradle/blob/b631911858264c0b6e4d6603d677ff5218766cee/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
|
||||||
# within the Gradle project.
|
# within the Gradle project.
|
||||||
#
|
#
|
||||||
# You can find Gradle at https://github.com/gradle/gradle/.
|
# You can find Gradle at https://github.com/gradle/gradle/.
|
||||||
@@ -80,13 +82,11 @@ do
|
|||||||
esac
|
esac
|
||||||
done
|
done
|
||||||
|
|
||||||
APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
|
# This is normally unused
|
||||||
|
# shellcheck disable=SC2034
|
||||||
APP_NAME="Gradle"
|
|
||||||
APP_BASE_NAME=${0##*/}
|
APP_BASE_NAME=${0##*/}
|
||||||
|
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
|
||||||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit
|
||||||
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
|
||||||
|
|
||||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||||
MAX_FD=maximum
|
MAX_FD=maximum
|
||||||
@@ -114,7 +114,6 @@ case "$( uname )" in #(
|
|||||||
NONSTOP* ) nonstop=true ;;
|
NONSTOP* ) nonstop=true ;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
|
||||||
|
|
||||||
|
|
||||||
# Determine the Java command to use to start the JVM.
|
# Determine the Java command to use to start the JVM.
|
||||||
@@ -133,22 +132,29 @@ location of your Java installation."
|
|||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
JAVACMD=java
|
JAVACMD=java
|
||||||
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
if ! command -v java >/dev/null 2>&1
|
||||||
|
then
|
||||||
|
die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||||
|
|
||||||
Please set the JAVA_HOME variable in your environment to match the
|
Please set the JAVA_HOME variable in your environment to match the
|
||||||
location of your Java installation."
|
location of your Java installation."
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Increase the maximum file descriptors if we can.
|
# Increase the maximum file descriptors if we can.
|
||||||
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
|
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
|
||||||
case $MAX_FD in #(
|
case $MAX_FD in #(
|
||||||
max*)
|
max*)
|
||||||
|
# In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
|
||||||
|
# shellcheck disable=SC2039,SC3045
|
||||||
MAX_FD=$( ulimit -H -n ) ||
|
MAX_FD=$( ulimit -H -n ) ||
|
||||||
warn "Could not query maximum file descriptor limit"
|
warn "Could not query maximum file descriptor limit"
|
||||||
esac
|
esac
|
||||||
case $MAX_FD in #(
|
case $MAX_FD in #(
|
||||||
'' | soft) :;; #(
|
'' | soft) :;; #(
|
||||||
*)
|
*)
|
||||||
|
# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
|
||||||
|
# shellcheck disable=SC2039,SC3045
|
||||||
ulimit -n "$MAX_FD" ||
|
ulimit -n "$MAX_FD" ||
|
||||||
warn "Could not set maximum file descriptor limit to $MAX_FD"
|
warn "Could not set maximum file descriptor limit to $MAX_FD"
|
||||||
esac
|
esac
|
||||||
@@ -165,7 +171,6 @@ fi
|
|||||||
# For Cygwin or MSYS, switch paths to Windows format before running java
|
# For Cygwin or MSYS, switch paths to Windows format before running java
|
||||||
if "$cygwin" || "$msys" ; then
|
if "$cygwin" || "$msys" ; then
|
||||||
APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
|
APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
|
||||||
CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
|
|
||||||
|
|
||||||
JAVACMD=$( cygpath --unix "$JAVACMD" )
|
JAVACMD=$( cygpath --unix "$JAVACMD" )
|
||||||
|
|
||||||
@@ -193,18 +198,27 @@ if "$cygwin" || "$msys" ; then
|
|||||||
done
|
done
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Collect all arguments for the java command;
|
|
||||||
# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
|
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||||
# shell script including quotes and variable substitutions, so put them in
|
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
||||||
# double quotes to make sure that they get re-expanded; and
|
|
||||||
# * put everything else in single quotes, so that it's not re-expanded.
|
# Collect all arguments for the java command:
|
||||||
|
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
|
||||||
|
# and any embedded shellness will be escaped.
|
||||||
|
# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
|
||||||
|
# treated as '${Hostname}' itself on the command line.
|
||||||
|
|
||||||
set -- \
|
set -- \
|
||||||
"-Dorg.gradle.appname=$APP_BASE_NAME" \
|
"-Dorg.gradle.appname=$APP_BASE_NAME" \
|
||||||
-classpath "$CLASSPATH" \
|
-jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \
|
||||||
org.gradle.wrapper.GradleWrapperMain \
|
|
||||||
"$@"
|
"$@"
|
||||||
|
|
||||||
|
# Stop when "xargs" is not available.
|
||||||
|
if ! command -v xargs >/dev/null 2>&1
|
||||||
|
then
|
||||||
|
die "xargs is not available"
|
||||||
|
fi
|
||||||
|
|
||||||
# Use "xargs" to parse quoted args.
|
# Use "xargs" to parse quoted args.
|
||||||
#
|
#
|
||||||
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
|
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
|
||||||
|
|||||||
40
gradlew.bat
vendored
40
gradlew.bat
vendored
@@ -13,8 +13,10 @@
|
|||||||
@rem See the License for the specific language governing permissions and
|
@rem See the License for the specific language governing permissions and
|
||||||
@rem limitations under the License.
|
@rem limitations under the License.
|
||||||
@rem
|
@rem
|
||||||
|
@rem SPDX-License-Identifier: Apache-2.0
|
||||||
|
@rem
|
||||||
|
|
||||||
@if "%DEBUG%" == "" @echo off
|
@if "%DEBUG%"=="" @echo off
|
||||||
@rem ##########################################################################
|
@rem ##########################################################################
|
||||||
@rem
|
@rem
|
||||||
@rem Gradle startup script for Windows
|
@rem Gradle startup script for Windows
|
||||||
@@ -25,7 +27,8 @@
|
|||||||
if "%OS%"=="Windows_NT" setlocal
|
if "%OS%"=="Windows_NT" setlocal
|
||||||
|
|
||||||
set DIRNAME=%~dp0
|
set DIRNAME=%~dp0
|
||||||
if "%DIRNAME%" == "" set DIRNAME=.
|
if "%DIRNAME%"=="" set DIRNAME=.
|
||||||
|
@rem This is normally unused
|
||||||
set APP_BASE_NAME=%~n0
|
set APP_BASE_NAME=%~n0
|
||||||
set APP_HOME=%DIRNAME%
|
set APP_HOME=%DIRNAME%
|
||||||
|
|
||||||
@@ -40,13 +43,13 @@ if defined JAVA_HOME goto findJavaFromJavaHome
|
|||||||
|
|
||||||
set JAVA_EXE=java.exe
|
set JAVA_EXE=java.exe
|
||||||
%JAVA_EXE% -version >NUL 2>&1
|
%JAVA_EXE% -version >NUL 2>&1
|
||||||
if "%ERRORLEVEL%" == "0" goto execute
|
if %ERRORLEVEL% equ 0 goto execute
|
||||||
|
|
||||||
echo.
|
echo. 1>&2
|
||||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
|
||||||
echo.
|
echo. 1>&2
|
||||||
echo Please set the JAVA_HOME variable in your environment to match the
|
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
|
||||||
echo location of your Java installation.
|
echo location of your Java installation. 1>&2
|
||||||
|
|
||||||
goto fail
|
goto fail
|
||||||
|
|
||||||
@@ -56,32 +59,33 @@ set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
|||||||
|
|
||||||
if exist "%JAVA_EXE%" goto execute
|
if exist "%JAVA_EXE%" goto execute
|
||||||
|
|
||||||
echo.
|
echo. 1>&2
|
||||||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
|
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
|
||||||
echo.
|
echo. 1>&2
|
||||||
echo Please set the JAVA_HOME variable in your environment to match the
|
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
|
||||||
echo location of your Java installation.
|
echo location of your Java installation. 1>&2
|
||||||
|
|
||||||
goto fail
|
goto fail
|
||||||
|
|
||||||
:execute
|
:execute
|
||||||
@rem Setup the command line
|
@rem Setup the command line
|
||||||
|
|
||||||
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
|
||||||
|
|
||||||
|
|
||||||
@rem Execute Gradle
|
@rem Execute Gradle
|
||||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
|
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %*
|
||||||
|
|
||||||
:end
|
:end
|
||||||
@rem End local scope for the variables with windows NT shell
|
@rem End local scope for the variables with windows NT shell
|
||||||
if "%ERRORLEVEL%"=="0" goto mainEnd
|
if %ERRORLEVEL% equ 0 goto mainEnd
|
||||||
|
|
||||||
:fail
|
:fail
|
||||||
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
||||||
rem the _cmd.exe /c_ return code!
|
rem the _cmd.exe /c_ return code!
|
||||||
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
|
set EXIT_CODE=%ERRORLEVEL%
|
||||||
exit /b 1
|
if %EXIT_CODE% equ 0 set EXIT_CODE=1
|
||||||
|
if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
|
||||||
|
exit /b %EXIT_CODE%
|
||||||
|
|
||||||
:mainEnd
|
:mainEnd
|
||||||
if "%OS%"=="Windows_NT" endlocal
|
if "%OS%"=="Windows_NT" endlocal
|
||||||
|
|||||||
@@ -205,27 +205,6 @@ public final class Terminal {
|
|||||||
return new Pager(DEFAULT.getSupport());
|
return new Pager(DEFAULT.getSupport());
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Returns a help/usage builder for CLI --help output. */
|
|
||||||
public static Help help() {
|
|
||||||
return new Help(DEFAULT.getSupport());
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Clears the terminal screen (ANSI). No-op if ANSI is disabled. */
|
|
||||||
public static void clearScreen() {
|
|
||||||
if (DEFAULT.getSupport().isAnsiEnabled()) {
|
|
||||||
System.out.print(dev.jakub.terminal.core.Ansi.CLEAR_SCREEN);
|
|
||||||
System.out.flush();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Moves the cursor to the given 1-based row and column (ANSI). No-op if ANSI is disabled. */
|
|
||||||
public static void cursorTo(int row, int col) {
|
|
||||||
if (DEFAULT.getSupport().isAnsiEnabled()) {
|
|
||||||
System.out.print(dev.jakub.terminal.core.Ansi.cursorTo(row, col));
|
|
||||||
System.out.flush();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TerminalSupport getSupport() {
|
TerminalSupport getSupport() {
|
||||||
return support;
|
return support;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,87 +0,0 @@
|
|||||||
package dev.jakub.terminal.components;
|
|
||||||
|
|
||||||
import dev.jakub.terminal.Terminal;
|
|
||||||
import dev.jakub.terminal.core.TerminalSupport;
|
|
||||||
|
|
||||||
import java.io.PrintStream;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* CLI help / usage block. Use via {@link Terminal#help()}.
|
|
||||||
* Formats options and descriptions for a typical --help output.
|
|
||||||
*/
|
|
||||||
public final class Help {
|
|
||||||
|
|
||||||
private static final int DEFAULT_OPTION_WIDTH = 24;
|
|
||||||
|
|
||||||
private final TerminalSupport support;
|
|
||||||
private final List<String> options = new ArrayList<>();
|
|
||||||
private final List<String> descriptions = new ArrayList<>();
|
|
||||||
private String title = "Usage";
|
|
||||||
private int optionWidth = DEFAULT_OPTION_WIDTH;
|
|
||||||
private PrintStream out = System.out;
|
|
||||||
|
|
||||||
public Help(TerminalSupport support) {
|
|
||||||
this.support = support;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the title (e.g. "Usage" or "Options").
|
|
||||||
*/
|
|
||||||
public Help title(String title) {
|
|
||||||
this.title = title != null ? title : "";
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds an option with description (e.g. "-v, --verbose" and "Enable verbose output").
|
|
||||||
*/
|
|
||||||
public Help option(String option, String description) {
|
|
||||||
options.add(option != null ? option : "");
|
|
||||||
descriptions.add(description != null ? description : "");
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the width of the option column (default 24).
|
|
||||||
*/
|
|
||||||
public Help optionWidth(int width) {
|
|
||||||
this.optionWidth = Math.max(8, width);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets output stream (default: stdout).
|
|
||||||
*/
|
|
||||||
public Help output(PrintStream out) {
|
|
||||||
this.out = out != null ? out : System.out;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Prints the help block to the given stream.
|
|
||||||
*/
|
|
||||||
public void print(PrintStream stream) {
|
|
||||||
if (stream == null) stream = System.out;
|
|
||||||
if (!title.isEmpty()) {
|
|
||||||
stream.println(title);
|
|
||||||
stream.println();
|
|
||||||
}
|
|
||||||
int ow = Math.max(optionWidth, 8);
|
|
||||||
for (int i = 0; i < options.size(); i++) {
|
|
||||||
String opt = options.get(i);
|
|
||||||
String desc = i < descriptions.size() ? descriptions.get(i) : "";
|
|
||||||
String padded = opt.length() <= ow ? opt + " ".repeat(ow - opt.length()) : opt;
|
|
||||||
stream.print(" " + padded + " ");
|
|
||||||
stream.println(desc);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Prints to stdout.
|
|
||||||
*/
|
|
||||||
public void print() {
|
|
||||||
print(out);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -22,7 +22,6 @@ public final class Log {
|
|||||||
private final TerminalSupport support;
|
private final TerminalSupport support;
|
||||||
private final List<Entry> entries = new ArrayList<>();
|
private final List<Entry> entries = new ArrayList<>();
|
||||||
private boolean withTimestamp;
|
private boolean withTimestamp;
|
||||||
private Level minLevel;
|
|
||||||
|
|
||||||
public Log(TerminalSupport support) {
|
public Log(TerminalSupport support) {
|
||||||
this.support = support;
|
this.support = support;
|
||||||
@@ -69,21 +68,11 @@ public final class Log {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Only print entries at this level or higher (e.g. WARN shows WARN and ERROR).
|
* Prints all log entries to the given stream.
|
||||||
* Useful for "quiet" mode or production.
|
|
||||||
*/
|
|
||||||
public Log minLevel(Level level) {
|
|
||||||
this.minLevel = level;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Prints log entries to the given stream (respects minLevel if set).
|
|
||||||
*/
|
*/
|
||||||
public void print(PrintStream out) {
|
public void print(PrintStream out) {
|
||||||
DateTimeFormatter fmt = DateTimeFormatter.ofPattern("HH:mm:ss").withZone(ZoneId.systemDefault());
|
DateTimeFormatter fmt = DateTimeFormatter.ofPattern("HH:mm:ss").withZone(ZoneId.systemDefault());
|
||||||
for (Entry e : entries) {
|
for (Entry e : entries) {
|
||||||
if (minLevel != null && e.level.ordinal() < minLevel.ordinal()) continue;
|
|
||||||
String prefix = withTimestamp ? "[" + fmt.format(Instant.now()) + "] " : "";
|
String prefix = withTimestamp ? "[" + fmt.format(Instant.now()) + "] " : "";
|
||||||
String label = "[" + e.level.name() + "]";
|
String label = "[" + e.level.name() + "]";
|
||||||
while (label.length() < LABEL_WIDTH) label += " ";
|
while (label.length() < LABEL_WIDTH) label += " ";
|
||||||
@@ -115,14 +104,11 @@ public final class Log {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
private enum Level {
|
||||||
* Log level for filtering. Order: DEBUG < INFO < WARN < ERROR.
|
|
||||||
*/
|
|
||||||
public enum Level {
|
|
||||||
DEBUG(Ansi.FG_BRIGHT_BLACK),
|
|
||||||
INFO(Ansi.FG_CYAN),
|
INFO(Ansi.FG_CYAN),
|
||||||
WARN(Ansi.FG_YELLOW),
|
WARN(Ansi.FG_YELLOW),
|
||||||
ERROR(Ansi.FG_RED);
|
ERROR(Ansi.FG_RED),
|
||||||
|
DEBUG(Ansi.FG_BRIGHT_BLACK);
|
||||||
|
|
||||||
final String ansi;
|
final String ansi;
|
||||||
|
|
||||||
|
|||||||
@@ -47,26 +47,6 @@ public final class Table {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds many rows from a list of arrays (e.g. from CSV or a list of records).
|
|
||||||
* Each array is one row; null cells are treated as empty string.
|
|
||||||
*/
|
|
||||||
public Table rows(Iterable<String[]> dataRows) {
|
|
||||||
if (dataRows == null) return this;
|
|
||||||
for (String[] cells : dataRows) {
|
|
||||||
if (cells != null) row(cells);
|
|
||||||
}
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Builds a table from a header and a list of row arrays in one call.
|
|
||||||
*/
|
|
||||||
public Table fromRows(String[] headerRow, Iterable<String[]> dataRows) {
|
|
||||||
if (headerRow != null && headerRow.length > 0) header(headerRow);
|
|
||||||
return rows(dataRows);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Prints the table to the given stream.
|
* Prints the table to the given stream.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -61,15 +61,5 @@ public final class Ansi {
|
|||||||
/** Clear line */
|
/** Clear line */
|
||||||
public static final String ERASE_LINE = "\u001B[2K";
|
public static final String ERASE_LINE = "\u001B[2K";
|
||||||
|
|
||||||
/** Clear entire screen and move cursor to home (1,1) */
|
|
||||||
public static final String CLEAR_SCREEN = "\u001B[H\u001B[2J";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Cursor position (1-based row and column). ESC [ row ; col H
|
|
||||||
*/
|
|
||||||
public static String cursorTo(int row, int col) {
|
|
||||||
return "\u001B[" + Math.max(1, row) + ";" + Math.max(1, col) + "H";
|
|
||||||
}
|
|
||||||
|
|
||||||
private Ansi() {}
|
private Ansi() {}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,244 +0,0 @@
|
|||||||
package dev.jakub.terminal.example;
|
|
||||||
|
|
||||||
import dev.jakub.terminal.Terminal;
|
|
||||||
import dev.jakub.terminal.components.Log;
|
|
||||||
import dev.jakub.terminal.components.Notification;
|
|
||||||
import dev.jakub.terminal.components.Steps;
|
|
||||||
import dev.jakub.terminal.core.Color;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
|
|
||||||
public final class Examples {
|
|
||||||
|
|
||||||
public static void main(String[] args) {
|
|
||||||
runAll();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void runAll() {
|
|
||||||
textAndRule();
|
|
||||||
keyValueAndBox();
|
|
||||||
table();
|
|
||||||
tableFromRows();
|
|
||||||
tree();
|
|
||||||
columns();
|
|
||||||
steps();
|
|
||||||
breadcrumb();
|
|
||||||
helpBlock();
|
|
||||||
log();
|
|
||||||
logWithMinLevel();
|
|
||||||
diff();
|
|
||||||
timeline();
|
|
||||||
heatmap();
|
|
||||||
chart();
|
|
||||||
badgeAndNotify();
|
|
||||||
codeBlock();
|
|
||||||
sysInfo();
|
|
||||||
markdown();
|
|
||||||
toc();
|
|
||||||
}
|
|
||||||
|
|
||||||
static void textAndRule() {
|
|
||||||
Terminal.print("=== Text & Rule ===").color(Color.CYAN).bold().println();
|
|
||||||
Terminal.rule().character('=').print();
|
|
||||||
Terminal.print("Hello").color(Color.GREEN).println();
|
|
||||||
Terminal.rule().doubles().prefix("-- ").suffix(" --").print();
|
|
||||||
System.out.println();
|
|
||||||
}
|
|
||||||
|
|
||||||
static void keyValueAndBox() {
|
|
||||||
Terminal.print("=== KeyValue & Box ===").color(Color.CYAN).bold().println();
|
|
||||||
Terminal.keyValue()
|
|
||||||
.row("Name", "terminal-ui")
|
|
||||||
.row("Version", "1.0")
|
|
||||||
.separator(" = ")
|
|
||||||
.print(System.out);
|
|
||||||
Terminal.box()
|
|
||||||
.title("Info")
|
|
||||||
.line("First line")
|
|
||||||
.lines("Second", "Third")
|
|
||||||
.print(System.out);
|
|
||||||
System.out.println();
|
|
||||||
}
|
|
||||||
|
|
||||||
static void table() {
|
|
||||||
Terminal.print("=== Table ===").color(Color.CYAN).bold().println();
|
|
||||||
Terminal.table()
|
|
||||||
.header("Col A", "Col B", "Col C")
|
|
||||||
.row("1", "2", "3")
|
|
||||||
.row("4", "5", "6")
|
|
||||||
.print(System.out);
|
|
||||||
System.out.println();
|
|
||||||
}
|
|
||||||
|
|
||||||
static void tableFromRows() {
|
|
||||||
Terminal.print("=== Table from rows ===").color(Color.CYAN).bold().println();
|
|
||||||
List<String[]> rows = List.of(
|
|
||||||
new String[]{"Alice", "10"},
|
|
||||||
new String[]{"Bob", "20"}
|
|
||||||
);
|
|
||||||
Terminal.table()
|
|
||||||
.header("Name", "Score")
|
|
||||||
.rows(rows)
|
|
||||||
.print(System.out);
|
|
||||||
System.out.println();
|
|
||||||
}
|
|
||||||
|
|
||||||
static void tree() {
|
|
||||||
Terminal.print("=== Tree ===").color(Color.CYAN).bold().println();
|
|
||||||
Terminal.tree()
|
|
||||||
.node("root")
|
|
||||||
.child("src")
|
|
||||||
.child("main").end()
|
|
||||||
.child("test").end()
|
|
||||||
.end()
|
|
||||||
.child("docs")
|
|
||||||
.end()
|
|
||||||
.print(System.out);
|
|
||||||
System.out.println();
|
|
||||||
}
|
|
||||||
|
|
||||||
static void columns() {
|
|
||||||
Terminal.print("=== Columns ===").color(Color.CYAN).bold().println();
|
|
||||||
Terminal.columns()
|
|
||||||
.column("Left\ncolumn\ntext")
|
|
||||||
.column("Middle")
|
|
||||||
.column("Right")
|
|
||||||
.print(System.out);
|
|
||||||
System.out.println();
|
|
||||||
}
|
|
||||||
|
|
||||||
static void steps() {
|
|
||||||
Terminal.print("=== Steps ===").color(Color.CYAN).bold().println();
|
|
||||||
Terminal.steps()
|
|
||||||
.step("Setup", Steps.Status.DONE)
|
|
||||||
.step("Build", Steps.Status.RUNNING)
|
|
||||||
.step("Deploy", Steps.Status.PENDING)
|
|
||||||
.print(System.out);
|
|
||||||
System.out.println();
|
|
||||||
}
|
|
||||||
|
|
||||||
static void breadcrumb() {
|
|
||||||
Terminal.print("=== Breadcrumb ===").color(Color.CYAN).bold().println();
|
|
||||||
Terminal.breadcrumb()
|
|
||||||
.crumb("Home")
|
|
||||||
.crumb("Projects")
|
|
||||||
.crumb("terminal-ui")
|
|
||||||
.separator(" / ")
|
|
||||||
.print(System.out);
|
|
||||||
System.out.println();
|
|
||||||
}
|
|
||||||
|
|
||||||
static void helpBlock() {
|
|
||||||
Terminal.print("=== Help (CLI usage) ===").color(Color.CYAN).bold().println();
|
|
||||||
Terminal.help()
|
|
||||||
.title("Options")
|
|
||||||
.option("-v, --verbose", "Enable verbose output")
|
|
||||||
.option("-h, --help", "Show this help")
|
|
||||||
.option("--file <path>", "Input file path")
|
|
||||||
.print(System.out);
|
|
||||||
System.out.println();
|
|
||||||
}
|
|
||||||
|
|
||||||
static void log() {
|
|
||||||
Terminal.print("=== Log ===").color(Color.CYAN).bold().println();
|
|
||||||
Terminal.log()
|
|
||||||
.info("Started")
|
|
||||||
.warn("Deprecation notice")
|
|
||||||
.error("Something failed")
|
|
||||||
.withTimestamp()
|
|
||||||
.print(System.out);
|
|
||||||
System.out.println();
|
|
||||||
}
|
|
||||||
|
|
||||||
static void logWithMinLevel() {
|
|
||||||
Terminal.print("=== Log (minLevel WARN) ===").color(Color.CYAN).bold().println();
|
|
||||||
Terminal.log()
|
|
||||||
.info("Hidden")
|
|
||||||
.warn("Visible")
|
|
||||||
.error("Visible")
|
|
||||||
.minLevel(Log.Level.WARN)
|
|
||||||
.print(System.out);
|
|
||||||
System.out.println();
|
|
||||||
}
|
|
||||||
|
|
||||||
static void diff() {
|
|
||||||
Terminal.print("=== Diff ===").color(Color.CYAN).bold().println();
|
|
||||||
Terminal.diff()
|
|
||||||
.before("old line 1\nold line 2")
|
|
||||||
.after("new line 1\nnew line 2\nnew line 3")
|
|
||||||
.print(System.out);
|
|
||||||
System.out.println();
|
|
||||||
}
|
|
||||||
|
|
||||||
static void timeline() {
|
|
||||||
Terminal.print("=== Timeline ===").color(Color.CYAN).bold().println();
|
|
||||||
Terminal.timeline()
|
|
||||||
.event("2025-01-01", "First release")
|
|
||||||
.event("2025-06-01", "Added SelectList")
|
|
||||||
.event("2026-01-01", "GitHub Packages")
|
|
||||||
.print(System.out);
|
|
||||||
System.out.println();
|
|
||||||
}
|
|
||||||
|
|
||||||
static void heatmap() {
|
|
||||||
Terminal.print("=== Heatmap ===").color(Color.CYAN).bold().println();
|
|
||||||
Terminal.heatmap()
|
|
||||||
.row("Mon", 10, 20, 5, 30)
|
|
||||||
.row("Tue", 15, 25, 10, 20)
|
|
||||||
.row("Wed", 5, 15, 25, 35)
|
|
||||||
.print(System.out);
|
|
||||||
System.out.println();
|
|
||||||
}
|
|
||||||
|
|
||||||
static void chart() {
|
|
||||||
Terminal.print("=== Chart ===").color(Color.CYAN).bold().println();
|
|
||||||
Terminal.chart()
|
|
||||||
.data(1.0, 2.0, 1.5, 3.0, 2.5)
|
|
||||||
.height(5)
|
|
||||||
.print(System.out);
|
|
||||||
System.out.println();
|
|
||||||
}
|
|
||||||
|
|
||||||
static void badgeAndNotify() {
|
|
||||||
Terminal.print("=== Badge & Notify ===").color(Color.CYAN).bold().println();
|
|
||||||
Terminal.badge("OK", Color.GREEN).println();
|
|
||||||
Terminal.badge("WARN", Color.YELLOW).print(System.out);
|
|
||||||
Terminal.notify("Done!", Notification.Type.SUCCESS);
|
|
||||||
Terminal.notify("Warning", Notification.Type.WARNING);
|
|
||||||
System.out.println();
|
|
||||||
}
|
|
||||||
|
|
||||||
static void codeBlock() {
|
|
||||||
Terminal.print("=== Code block ===").color(Color.CYAN).bold().println();
|
|
||||||
Terminal.code("java")
|
|
||||||
.line("public static void main(String[] args) {")
|
|
||||||
.line(" System.out.println(\"Hello\");")
|
|
||||||
.line("}")
|
|
||||||
.lineNumbers()
|
|
||||||
.print(System.out);
|
|
||||||
System.out.println();
|
|
||||||
}
|
|
||||||
|
|
||||||
static void sysInfo() {
|
|
||||||
Terminal.print("=== SysInfo ===").color(Color.CYAN).bold().println();
|
|
||||||
Terminal.sysinfo().print(System.out);
|
|
||||||
System.out.println();
|
|
||||||
}
|
|
||||||
|
|
||||||
static void markdown() {
|
|
||||||
Terminal.print("=== Markdown ===").color(Color.CYAN).bold().println();
|
|
||||||
Terminal.markdown("# Title\n\n**Bold** and *italic*.\n\n- Item 1\n- Item 2\n\n---")
|
|
||||||
.print(System.out);
|
|
||||||
System.out.println();
|
|
||||||
}
|
|
||||||
|
|
||||||
static void toc() {
|
|
||||||
Terminal.print("=== Table of contents ===").color(Color.CYAN).bold().println();
|
|
||||||
Terminal.toc()
|
|
||||||
.section("Introduction").sub("Overview").sub("Install")
|
|
||||||
.section("API").sub("Reference")
|
|
||||||
.section("Examples")
|
|
||||||
.print(System.out);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -72,7 +72,7 @@ public final class Confirm {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Uses the given scanner for one line. Use when sharing one scanner (e.g. interactive app).
|
* Uses the given scanner for one line. Use when sharing one scanner (e.g. demo).
|
||||||
*/
|
*/
|
||||||
public boolean ask(Scanner sharedScanner) {
|
public boolean ask(Scanner sharedScanner) {
|
||||||
if (sharedScanner == null) return ask();
|
if (sharedScanner == null) return ask();
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ import dev.jakub.terminal.core.TerminalSupport;
|
|||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.PrintStream;
|
import java.io.PrintStream;
|
||||||
import java.util.Scanner;
|
import java.util.Scanner;
|
||||||
import java.util.function.Predicate;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Input prompt for reading user input. Use via {@link Terminal#prompt(String)}.
|
* Input prompt for reading user input. Use via {@link Terminal#prompt(String)}.
|
||||||
@@ -19,8 +18,6 @@ public final class Prompt {
|
|||||||
private boolean masked;
|
private boolean masked;
|
||||||
private PrintStream out = System.out;
|
private PrintStream out = System.out;
|
||||||
private InputStream in = System.in;
|
private InputStream in = System.in;
|
||||||
private Predicate<String> validator;
|
|
||||||
private String retryMessage = "Invalid, try again: ";
|
|
||||||
|
|
||||||
public Prompt(String message, TerminalSupport support) {
|
public Prompt(String message, TerminalSupport support) {
|
||||||
this.message = message != null ? message : "";
|
this.message = message != null ? message : "";
|
||||||
@@ -51,62 +48,33 @@ public final class Prompt {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Validates input: asks again until the predicate returns true. Null = no validation.
|
|
||||||
*/
|
|
||||||
public Prompt validate(Predicate<String> validator) {
|
|
||||||
this.validator = validator;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Message shown when validation fails (default: "Invalid, try again: ").
|
|
||||||
*/
|
|
||||||
public Prompt retryMessage(String retryMessage) {
|
|
||||||
this.retryMessage = retryMessage != null ? retryMessage : "Invalid, try again: ";
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Prompts and returns the entered string. Blocks until a line is read.
|
* Prompts and returns the entered string. Blocks until a line is read.
|
||||||
* If {@link #validate(Predicate)} is set, repeats until the predicate accepts the input.
|
|
||||||
*/
|
*/
|
||||||
public String ask() {
|
public String ask() {
|
||||||
|
out.print(message);
|
||||||
|
out.flush();
|
||||||
if (masked) {
|
if (masked) {
|
||||||
return readMasked();
|
return readMasked();
|
||||||
}
|
}
|
||||||
try (Scanner scan = new Scanner(in)) {
|
try (Scanner scan = new Scanner(in)) {
|
||||||
return askLoop(scan);
|
return scan.hasNextLine() ? scan.nextLine() : "";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Prompts and returns the next line from the given scanner. Use this when
|
* Prompts and returns the next line from the given scanner. Use this when
|
||||||
* sharing one scanner (e.g. in an interactive app) so input blocks correctly.
|
* sharing one scanner (e.g. in a demo) so input blocks correctly.
|
||||||
* If {@link #validate(Predicate)} is set, repeats until the predicate accepts the input.
|
|
||||||
*/
|
*/
|
||||||
public String ask(Scanner sharedScanner) {
|
public String ask(Scanner sharedScanner) {
|
||||||
if (sharedScanner == null) return ask();
|
if (sharedScanner == null) return ask();
|
||||||
|
out.print(message);
|
||||||
|
out.flush();
|
||||||
if (masked && System.console() != null) {
|
if (masked && System.console() != null) {
|
||||||
out.print(message);
|
|
||||||
out.flush();
|
|
||||||
char[] chars = System.console().readPassword();
|
char[] chars = System.console().readPassword();
|
||||||
return chars != null ? new String(chars) : "";
|
return chars != null ? new String(chars) : "";
|
||||||
}
|
}
|
||||||
return askLoop(sharedScanner);
|
return sharedScanner.hasNextLine() ? sharedScanner.nextLine() : "";
|
||||||
}
|
|
||||||
|
|
||||||
private String askLoop(Scanner scan) {
|
|
||||||
while (true) {
|
|
||||||
out.print(message);
|
|
||||||
out.flush();
|
|
||||||
if (!scan.hasNextLine()) return "";
|
|
||||||
String line = scan.nextLine();
|
|
||||||
if (line == null) line = "";
|
|
||||||
if (validator == null || validator.test(line)) return line;
|
|
||||||
out.print(retryMessage);
|
|
||||||
out.flush();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private String readMasked() {
|
private String readMasked() {
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ import dev.jakub.terminal.interactive.Prompt;
|
|||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.PrintStream;
|
import java.io.PrintStream;
|
||||||
import java.util.Scanner;
|
import java.util.Scanner;
|
||||||
import java.util.function.Predicate;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fluent builder for {@link Prompt}. Use via {@link Terminal#prompt(String)}.
|
* Fluent builder for {@link Prompt}. Use via {@link Terminal#prompt(String)}.
|
||||||
@@ -20,8 +19,6 @@ public final class PromptBuilder {
|
|||||||
private boolean masked;
|
private boolean masked;
|
||||||
private PrintStream output = System.out;
|
private PrintStream output = System.out;
|
||||||
private InputStream input = System.in;
|
private InputStream input = System.in;
|
||||||
private Predicate<String> validator;
|
|
||||||
private String retryMessage = "Invalid, try again: ";
|
|
||||||
|
|
||||||
public PromptBuilder(String message, TerminalSupport support) {
|
public PromptBuilder(String message, TerminalSupport support) {
|
||||||
this.message = message != null ? message : "";
|
this.message = message != null ? message : "";
|
||||||
@@ -52,27 +49,14 @@ public final class PromptBuilder {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Validates input: prompts again until the predicate returns true. Null = no validation.
|
|
||||||
*/
|
|
||||||
public PromptBuilder validate(Predicate<String> validator) {
|
|
||||||
this.validator = validator;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Message shown when validation fails (default: "Invalid, try again: ").
|
|
||||||
*/
|
|
||||||
public PromptBuilder retryMessage(String retryMessage) {
|
|
||||||
this.retryMessage = retryMessage != null ? retryMessage : "Invalid, try again: ";
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Prompts and returns the entered string.
|
* Prompts and returns the entered string.
|
||||||
*/
|
*/
|
||||||
public String ask() {
|
public String ask() {
|
||||||
Prompt p = buildPrompt();
|
Prompt p = new Prompt(message, support);
|
||||||
|
if (masked) p.masked();
|
||||||
|
p.output(output);
|
||||||
|
p.input(input);
|
||||||
return p.ask();
|
return p.ask();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -82,17 +66,10 @@ public final class PromptBuilder {
|
|||||||
*/
|
*/
|
||||||
public String ask(Scanner sharedScanner) {
|
public String ask(Scanner sharedScanner) {
|
||||||
if (sharedScanner == null) return ask();
|
if (sharedScanner == null) return ask();
|
||||||
Prompt p = buildPrompt();
|
|
||||||
return p.ask(sharedScanner);
|
|
||||||
}
|
|
||||||
|
|
||||||
private Prompt buildPrompt() {
|
|
||||||
Prompt p = new Prompt(message, support);
|
Prompt p = new Prompt(message, support);
|
||||||
if (masked) p.masked();
|
if (masked) p.masked();
|
||||||
p.output(output);
|
p.output(output);
|
||||||
p.input(input);
|
p.input(input);
|
||||||
if (validator != null) p.validate(validator);
|
return p.ask(sharedScanner);
|
||||||
p.retryMessage(retryMessage);
|
|
||||||
return p;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user