Skip to content

Commit

Permalink
refactor to a multiple project configuration
Browse files Browse the repository at this point in the history
remove onions' ColorScheme dependency from scurses
update readme
  • Loading branch information
Tenchi2xh committed Nov 12, 2015
1 parent 53f0932 commit 9642077
Show file tree
Hide file tree
Showing 39 changed files with 86 additions and 41 deletions.
30 changes: 24 additions & 6 deletions build.sbt
@@ -1,11 +1,29 @@
name := "Scurses"
import sbt.Keys._
import sbt._

version := "1.0"

scalaVersion := "2.11.7"
lazy val commonSettings: Seq[Setting[_]] = Seq(
version := "1.0",
scalaVersion := "2.11.7",
scalacOptions ++= Seq("-feature", "-unchecked")
)

scalacOptions ++= Seq("-feature", "-unchecked")
lazy val root = (project in file("."))
.settings(commonSettings: _*)
.aggregate(scurses, onions)

libraryDependencies += "com.lihaoyi" %% "fastparse" % "0.2.1"
lazy val scurses = (project in file("scurses"))
.settings(commonSettings: _*)
.settings(
name := "Scurses",
libraryDependencies += "com.lihaoyi" %% "fastparse" % "0.2.1",
mainClass in (Compile, run) := Some("net.team2xh.scurses.examples.GameOfLife")
)

mainClass in (Compile, run) := Some("net.team2xh.scurses.examples.StressTest")
lazy val onions = (project in file("onions"))
.settings(commonSettings: _*)
.dependsOn(scurses)
.settings(
name := "Onions",
mainClass in (Compile, run) := Some("net.team2xh.onions.examples.ExampleUI")
)
Expand Up @@ -351,9 +351,9 @@ case class FramePanel(parent: Component)
else " " + ts

if (title != "") {
screen.put(2, 0, r"[[$title$tabText]", theme)
screen.putRichText(2, 0, r"[[$title$tabText]", theme.foreground, theme.background)
} else if (tabText != "") {
screen.put(2, 0, r"[[$tabText]", theme)
screen.putRichText(2, 0, r"[[$tabText]", theme.foreground, theme.background)
}
}

Expand Down
Expand Up @@ -14,7 +14,7 @@ case class RichLabel(parent: FramePanel, text: Varying[RichText])
override def redraw(focus: Boolean, theme: ColorScheme): Unit = {
lines = TextWrap.wrapText(text.value, innerWidth - 1)
for ((line, i) <- lines.zipWithIndex) {
screen.put(1, i, lines(i), theme)
screen.putRichText(1, i, lines(i), theme.foreground, theme.background)
}
}

Expand Down
Expand Up @@ -84,7 +84,7 @@ object ExampleUI extends App {
big.color := color
}
colB.addTab()
BitMap(colB, "/src/main/scala/net/team2xh/onions/examples/logo.png", relative = true)
BitMap(colB, "/onions/src/main/scala/net/team2xh/onions/examples/logo.png", relative = true)
Separator(colB)
Label(colB, "Heat maps blur radius:")
val slider = Slider(colB, 1, 10)(3)
Expand Down
78 changes: 53 additions & 25 deletions readme.md
Expand Up @@ -8,22 +8,21 @@ Terminal drawing API for Scala

- Hello World:

```R
$ sbt
> run net.team2xh.scurses.examples.HelloWorld
```
```R
$ sbt "scurses/run-main net.team2xh.scurses.examples.HelloWorld"
```

- Game of life:

```R
$ sbt
> run net.teamx2h.scurses.examples.GameOfLife
```
```R
$ sbt scurses/run
```

- Stress test:

```R
$ sbt
> run net.teamx2h.scurses.examples.StressTest
```
```R
$ sbt "scurses/run-main net.team2xh.scurses.examples.StressTest"
```

### How to use

Expand Down Expand Up @@ -62,32 +61,61 @@ Scurses framework for easy terminal UI
What's been done so far:

```R
$ sbt
> run net.teamx2h.onions.examples.ExampleUI
$ sbt onions/run
```

Goal is to provide an API full of widgets to make it really easy for users to quickly set up a dashboard to monitor their services in the terminal (graphs, histograms, logs, etc.)

Currently taking "raw" input from keyboard with JLine, need to find something more powerful to grab inputs like ESC and key combinations, and also detect terminal resize.

### How to use

```scala
Scurses { implicit screen =>
val frame = Frame("Example UI")
// Three columns
val p1 = frame.panel
val p2 = p1.splitRight
val p3 = p2.splitRight
// Split second column in three rows (p2 will point to first row of second column)
val p22 = p2.splitDown
val p23 = p22.splitDown
// Split third row of second column into two columns (p23 will point to the first column of the two)
val p232 = p23.splitRight
val colA = frame.panel
val colB = colA.splitRight
val colC = colB.splitRight
// Split second column in three rows
val colB2 = colB.splitDown
val colB3 = colB2.splitDown
// Split third row of second column into two columns
val colB3B = colB3.splitRight
val colB3B2 = colB3B.splitDown
// Split last column into two rows
val p32 = p3.splitDown
val colC2 = colC.splitDown

// Add a label in the first column
Label(colA, Lorem.Ipsum, TextWrap.JUSTIFY)

val r = Random
val points = (1 to 50) map (i => {
val x = r.nextInt(40)
val y = 50 - x + (r.nextGaussian() * 5).toInt - 2
(x, y max 0)
})

// Add a scatter plot in the first row of third column
ScatterPlot(colC, points, "Time", "Sales")

// Show a heat map of the same values in the second row
HeatMap(colC2, points, "Time", "Sales")

// Display and launch event loop
frame.show()
}
```

For examples about all widgets, see `ExampleUI.scala`

### Keyboard controls

Keys | Action
:---:|:------
<kbd>↑</kbd> / <kbd>↓</kbd> | Focus next widget in direction / Focus next panel in direction
<kbd>←</kbd> / <kbd>→</kbd> | Focus next panel in direction
<kbd>⇥</kbd> / <kbd>⇧</kbd>+<kbd>⇥</kbd> | Focus next / previous panel
<kbd>CTRL</kbd>+<kbd>SPACE</kbd> | Switch to next tab (if panel has multiple tabs)
<kbd>SPACE</kbd> / <kbd>↵</kbd> | Activate label action, check radio or checkbox
<kbd>&lt;</kbd> / <kbd>&gt;</kbd> | Move slider left / right (also with <kbd>SPACE</kbd> / <kbd>↵</kbd>)
<kbd>ESC</kbd> / <kbd>CTRL</kbd>+<kbd>C</kbd> | Exit

Expand Up @@ -3,7 +3,6 @@ package net.team2xh.scurses
import java.io.BufferedOutputStream
import java.util.{TimerTask, Timer}

import net.team2xh.onions.Themes.ColorScheme
import net.team2xh.scurses.RichText._
import sun.misc.{SignalHandler, Signal}

Expand Down Expand Up @@ -74,12 +73,12 @@ class Scurses {
ec.stopBackground()
}

def put(x: Int, y: Int, richText: RichText, theme: ColorScheme): Unit = {
def putRichText(x: Int, y: Int, richText: RichText, foreground: Int = -1, background: Int = -1): Unit = {
if (outOfBounds(x, y))
return
ec.move(x + offsetX, y + offsetY)
if (theme.foreground >= 0) ec.setForeground(theme.foreground)
if (theme.background >= 0) ec.setBackground(theme.background)
if (foreground >= 0) ec.setForeground(foreground)
if (background >= 0) ec.setBackground(background)
for (instruction <- richText.instructions) {
instruction match {
case Text(text) => out.write(text.getBytes)
Expand All @@ -106,8 +105,8 @@ class Scurses {
case Underline => ec.stopUnderline()
case Blink => ec.stopBlink()
case Reverse => ec.stopReverse()
case Foreground => if (theme.foreground >= 0) ec.setForeground(theme.foreground)
case Background => if (theme.background >= 0) ec.setBackground(theme.background)
case Foreground => if (foreground >= 0) ec.setForeground(foreground)
case Background => if (background >= 0) ec.setBackground(background)
case _ =>
}
case ResetAttributes => ec.resetColors()
Expand Down

0 comments on commit 9642077

Please sign in to comment.