Skip to content

Commit 9331a6f

Browse files
committed
feat: added colors module for color handling
1 parent f056fee commit 9331a6f

8 files changed

Lines changed: 1302 additions & 0 deletions

File tree

README.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ And then we have utility modules:
1010
- **[`ansiparser`](ansiparser/README.md)** — compact ANSI escape sequence parser
1111
- **[`mousetrack`](mousetrack/README.md)** — terminal mouse-tracking helpers and event parser
1212
- **[`termcap`](termcap/README.md)** — terminal capability detection
13+
- **[`colors`](colors/README.md)** — terminal colour palette querying and setting
1314

1415
**Philosophy** : this project has been expressly created to be as minimal as possible, it only offers the most essential functionality that is missing from Java to be able to use the features of a modern Terminal. Several other projects exist that do this as well, but they normally come with a whole bunch of other things that you might not need. `miniterm` on the other hand *only* does the work that you can't do with standard Java APIs. Everything else can be built on top.
1516

@@ -95,6 +96,16 @@ if (caps.colors() >= 256) {
9596
}
9697
```
9798

99+
### Query colors
100+
101+
```java
102+
Color bg = TermColors.queryBackground(terminal, () -> terminal.read(500));
103+
if (bg != null) {
104+
// luminance check for dark/light theme detection
105+
boolean dark = (0.299 * bg.r8() + 0.587 * bg.g8() + 0.114 * bg.b8()) < 128;
106+
}
107+
```
108+
98109
## Modules
99110

100111
Three artifacts are published independently:
@@ -106,6 +117,7 @@ Three artifacts are published independently:
106117
| [`ansiparser`](ansiparser/README.md) | Compact ANSI escape sequence parser, Java 8+ |
107118
| [`mousetrack`](mousetrack/README.md) | Terminal mouse-tracking helpers and event parser, Java 8+ |
108119
| [`termcap`](termcap/README.md) | Terminal capability detection, Java 8+ |
120+
| [`colors`](colors/README.md) | Terminal colour palette querying and setting via OSC sequences, Java 8+ |
109121

110122
For dependency coordinates (Maven, Gradle, JBang) and module-specific usage details, see the individual module READMEs linked above.
111123

colors/README.md

Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
# colors
2+
3+
`colors` is a small Java 8+ library for querying and setting terminal colour palettes via OSC escape sequences, part of the [java-miniterm](../README.md) project.
4+
5+
It supports reading the full 256-entry palette in a single burst, querying the foreground/background/cursor colours, redefining palette entries, and resetting them to the profile defaults.
6+
7+
## Usage
8+
9+
### Query foreground and background
10+
11+
```java
12+
Color fg = TermColors.queryForeground(terminal, in);
13+
Color bg = TermColors.queryBackground(terminal, in);
14+
Color cursor = TermColors.queryCursor(terminal, in);
15+
16+
if (bg != null) {
17+
// luminance check for dark/light theme detection
18+
boolean dark = (0.299 * bg.r8() + 0.587 * bg.g8() + 0.114 * bg.b8()) < 128;
19+
}
20+
```
21+
22+
Returns `null` if the terminal does not respond within the timeout.
23+
24+
### Query a single palette entry
25+
26+
```java
27+
Color color1 = TermColors.queryColor(terminal, in, 1); // ANSI red
28+
```
29+
30+
### Query the full 256-entry palette (burst)
31+
32+
All 256 queries are sent at once; responses are collected until a read timeout indicates the terminal has no more data:
33+
34+
```java
35+
Color[] palette = TermColors.queryPalette(terminal, in);
36+
// palette[n] is null if the terminal did not respond for that index
37+
```
38+
39+
Query a specific subset:
40+
41+
```java
42+
// Query only the 16 ANSI colours
43+
int[] ansi16 = new int[16];
44+
for (int i = 0; i < 16; i++) ansi16[i] = i;
45+
Color[] result = TermColors.queryPalette(terminal, in, ansi16);
46+
```
47+
48+
### Set colours
49+
50+
```java
51+
TermColors.setForeground(terminal, Color.ofRgb8(220, 220, 220));
52+
TermColors.setBackground(terminal, Color.ofRgb8(30, 30, 30));
53+
TermColors.setCursor(terminal, Color.ofRgb8(255, 165, 0));
54+
55+
TermColors.setColor(terminal, 1, Color.ofRgb8(204, 0, 0)); // redefine ANSI red
56+
```
57+
58+
Set the full palette from an array (null entries are skipped):
59+
60+
```java
61+
Color[] palette = buildThemePalette(); // Color[256]
62+
TermColors.setPalette(terminal, palette);
63+
```
64+
65+
### Reset to profile defaults
66+
67+
```java
68+
TermColors.resetForeground(terminal); // OSC 110
69+
TermColors.resetBackground(terminal); // OSC 111
70+
TermColors.resetCursor(terminal); // OSC 112
71+
72+
TermColors.resetColor(terminal, 1); // reset single palette entry (OSC 104)
73+
TermColors.resetPalette(terminal); // reset all 256 entries (OSC 104)
74+
```
75+
76+
## Concepts
77+
78+
### `TermColors`
79+
80+
All methods are static. Query methods require the terminal in **raw mode** and an `IntReader` that returns negative values on timeout or EOF:
81+
82+
```java
83+
terminal.enableRawMode();
84+
IntReader in = () -> terminal.read(500); // 500 ms timeout per read
85+
```
86+
87+
### `Color`
88+
89+
An immutable 16-bit-per-channel RGB colour, matching the precision used in the X11 `rgb:` colour specification that terminals return in OSC responses.
90+
91+
```java
92+
Color red = Color.of(0xFFFF, 0x0000, 0x0000); // 16-bit channels
93+
Color green = Color.ofRgb8(0, 255, 0); // 8-bit, expanded
94+
Color blue = Color.parse("rgb:0000/0000/FFFF"); // from OSC string
95+
```
96+
97+
Conversion helpers:
98+
99+
```java
100+
color.r8() // red channel downsampled to 8 bits (0-255)
101+
color.toRgb8() // packed 0xRRGGBB int
102+
color.toString() // "rgb:RRRR/GGGG/BBBB" — ready for use in OSC sequences
103+
```
104+
105+
## OSC sequence reference
106+
107+
| Operation | Sequence |
108+
|---|---|
109+
| Query foreground | `OSC 10 ; ? BEL` |
110+
| Query background | `OSC 11 ; ? BEL` |
111+
| Query cursor colour | `OSC 12 ; ? BEL` |
112+
| Query palette entry *n* | `OSC 4 ; n ; ? BEL` |
113+
| Set foreground | `OSC 10 ; rgb:RRRR/GGGG/BBBB BEL` |
114+
| Set background | `OSC 11 ; rgb:RRRR/GGGG/BBBB BEL` |
115+
| Set cursor colour | `OSC 12 ; rgb:RRRR/GGGG/BBBB BEL` |
116+
| Set palette entry *n* | `OSC 4 ; n ; rgb:RRRR/GGGG/BBBB BEL` |
117+
| Reset foreground | `OSC 110 BEL` |
118+
| Reset background | `OSC 111 BEL` |
119+
| Reset cursor colour | `OSC 112 BEL` |
120+
| Reset palette entry *n* | `OSC 104 ; n BEL` |
121+
| Reset all palette entries | `OSC 104 BEL` |
122+
123+
## Dependency
124+
125+
### JBang
126+
127+
```java
128+
//DEPS org.codejive.miniterm:colors:0.1.1
129+
```
130+
131+
### Maven
132+
133+
```xml
134+
<dependency>
135+
<groupId>org.codejive.miniterm</groupId>
136+
<artifactId>colors</artifactId>
137+
<version>0.1.1</version>
138+
</dependency>
139+
```
140+
141+
### Gradle
142+
143+
```kotlin
144+
implementation("org.codejive.miniterm:colors:0.1.1")
145+
```
146+
147+
`colors` requires `ansiparser` (included transitively) for parsing OSC responses.

colors/pom.xml

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project xmlns="http://maven.apache.org/POM/4.0.0"
3+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
5+
<modelVersion>4.0.0</modelVersion>
6+
7+
<parent>
8+
<groupId>org.codejive.miniterm</groupId>
9+
<artifactId>miniterm-parent</artifactId>
10+
<version>0.1.2-SNAPSHOT</version>
11+
</parent>
12+
13+
<artifactId>colors</artifactId>
14+
<name>colors</name>
15+
<description>Terminal colour palette querying and setting via OSC sequences</description>
16+
<url>https://github.com/codejive/miniterm</url>
17+
18+
<properties>
19+
<maven.compiler.release>8</maven.compiler.release>
20+
<javaModuleName>org.codejive.miniterm.colors</javaModuleName>
21+
</properties>
22+
23+
<dependencies>
24+
<dependency>
25+
<groupId>org.codejive.miniterm</groupId>
26+
<artifactId>ansiparser</artifactId>
27+
<version>${project.version}</version>
28+
</dependency>
29+
30+
<dependency>
31+
<groupId>org.junit.jupiter</groupId>
32+
<artifactId>junit-jupiter</artifactId>
33+
<scope>test</scope>
34+
</dependency>
35+
<dependency>
36+
<groupId>org.assertj</groupId>
37+
<artifactId>assertj-core</artifactId>
38+
<version>${version.assertj}</version>
39+
<scope>test</scope>
40+
</dependency>
41+
</dependencies>
42+
43+
<build>
44+
<plugins>
45+
<plugin>
46+
<groupId>org.apache.maven.plugins</groupId>
47+
<artifactId>maven-compiler-plugin</artifactId>
48+
<configuration>
49+
<release>8</release>
50+
</configuration>
51+
</plugin>
52+
<plugin>
53+
<groupId>org.apache.maven.plugins</groupId>
54+
<artifactId>maven-jar-plugin</artifactId>
55+
<configuration>
56+
<archive>
57+
<manifestEntries>
58+
<Automatic-Module-Name>${javaModuleName}</Automatic-Module-Name>
59+
</manifestEntries>
60+
<addMavenDescriptor>false</addMavenDescriptor>
61+
<index>false</index>
62+
</archive>
63+
</configuration>
64+
</plugin>
65+
<plugin>
66+
<groupId>com.diffplug.spotless</groupId>
67+
<artifactId>spotless-maven-plugin</artifactId>
68+
<configuration>
69+
<formats>
70+
<format>
71+
<includes>
72+
<include>**/*.md</include>
73+
<include>**/*.txt</include>
74+
<include>.gitignore</include>
75+
<include>.gitattributes</include>
76+
</includes>
77+
<excludes>
78+
<exclude>**/target/**</exclude>
79+
</excludes>
80+
<lineEndings>UNIX</lineEndings>
81+
<trimTrailingWhitespace />
82+
<endWithNewline />
83+
<indent>
84+
<spaces>true</spaces>
85+
<spacesPerTab>4</spacesPerTab>
86+
</indent>
87+
</format>
88+
</formats>
89+
<java>
90+
<includes>
91+
<include>src/main/java/**/*.java</include>
92+
<include>src/test/java/**/*.java</include>
93+
</includes>
94+
<googleJavaFormat>
95+
<version>${version.google-java-format}</version>
96+
<style>AOSP</style>
97+
</googleJavaFormat>
98+
<toggleOffOn />
99+
</java>
100+
</configuration>
101+
<executions>
102+
<execution>
103+
<phase>verify</phase>
104+
<goals>
105+
<goal>check</goal>
106+
</goals>
107+
</execution>
108+
</executions>
109+
</plugin>
110+
</plugins>
111+
</build>
112+
</project>

0 commit comments

Comments
 (0)