Skip to content

Commit 609793b

Browse files
authored
Merge pull request #22 from maxgmr/dev
0.1.0-beta.4
2 parents 9e049ae + 56b5edc commit 609793b

32 files changed

+4314
-218
lines changed

CHANGELOG.md

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,25 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1717
- Abstract away Tlenix program boilerplate (proc macro?)
1818
- Add `--help` display to all Tlenix programs
1919
- `man` pages!
20+
- `hexe`: Format input bytes as hex
21+
- `rcv`: Convert radices
22+
- `reset`: Reset terminal
23+
24+
## [0.1.0-beta.4] - 2025-08-04
25+
26+
### Added
27+
28+
- `ted`: A basic Vim-style text editor.
29+
- `codebreaker`: A simple code-guessing game inspired by the "Mastermind" board game.
30+
- Random number generation.
31+
- A collection of common ANSI console control sequences.
32+
- Time measurement.
33+
- The Tlenix source code is now included in the installation within `/usr/src/tlenix`.
34+
- Cursor shape switching.
35+
36+
### Changed
37+
38+
- Bumped memory allocator to 256 MiB.
2039

2140
## [0.1.0-beta.3] - 2025-06-12
2241

Cargo.toml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "tlenix"
3-
version = "0.1.0-beta.3"
3+
version = "0.1.0-beta.4"
44
authors = ["Max Gilmour <mgilmour@maxgmr.ca>"]
55
edition = "2024"
66
description = "Custom OS built upon the Linux kernel"
@@ -27,7 +27,8 @@ bitflags = "2.1"
2727
getargs = { version = "0.5", default-features = false }
2828
lazy_static = { version = "1.5", features = ["spin_no_std"] }
2929
num_enum = { version = ">=0.4, <=0.7", default-features = false }
30-
spin = { version = "0.10.0", default-features = false, features = [
30+
pastey = "0.1.0"
31+
spin = { version = "0.9.8", default-features = false, features = [
3132
"mutex",
3233
"spin_mutex",
3334
"lock_api",

build.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
fn main() {
2+
println!("cargo::rustc-check-cfg=cfg(qemu)");
3+
}

config/grub.cfg

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
menuentry "tlenix" {
2-
linux /EFI/BOOT/bzImage root=/dev/sda2 rw loglevel=3 fbcon=font:TER16x32
2+
linux /EFI/BOOT/bzImage root=/dev/sda2 rw console=tty1 loglevel=3 fbcon=font:TER16x32
33
initrd /EFI/BOOT/root.cpio.gz
44
}

os_files/root/.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
*
2+
!.gitignore

src/allocator.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use core::ptr;
55
use talc::{ClaimOnOom, Span, Talc, Talck};
66

77
// Size (in bytes) of global memory allocator arena.
8-
const ARENA_SIZE: usize = 1 << 16; // 64 KiB
8+
const ARENA_SIZE: usize = 1 << 28; // 256 MiB
99

1010
// Talc global memory allocator
1111
static mut ARENA: [u8; ARENA_SIZE] = [0; ARENA_SIZE];

src/ansi.rs

Lines changed: 306 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,306 @@
1+
//! A collection of ANSI escape sequences used for terminal control.
2+
//!
3+
//! See [`console_codes(4)`](https://www.man7.org/linux/man-pages/man4/console_codes.4.html) for a
4+
//! reference of supported codes.
5+
6+
extern crate alloc;
7+
8+
use alloc::string::{String, ToString};
9+
10+
macro_rules! define_ecma_single_consts {
11+
[$(
12+
$(#[$doc:meta])+
13+
$name:ident = $num:literal;
14+
)*] => {
15+
$(
16+
$(#[$doc])+
17+
pub const $name: &str = concat!("\u{001b}[", $num, "m");
18+
)*
19+
}
20+
}
21+
define_ecma_single_consts![
22+
/// Reset all graphic attributes to their defaults.
23+
ANSI_RESET_GRAPHIC = "";
24+
/// Set bold text.
25+
ANSI_BOLD = "1";
26+
/// Set half-bright text.
27+
ANSI_HALF_BRIGHT = "2";
28+
/// Set italic text.
29+
ANSI_ITALIC = "3";
30+
/// Set blinking text.
31+
ANSI_BLINK = "5";
32+
/// Invert text colours.
33+
ANSI_INVERT = "7";
34+
/// Set underline.
35+
ANSI_UNDERLINE = "21";
36+
/// Set normal intensity.
37+
ANSI_NORMAL_INTENSITY = "22";
38+
/// Turn off italics.
39+
ANSI_ITALIC_OFF = "23";
40+
/// Turn off underline.
41+
ANSI_UNDERLINE_OFF = "24";
42+
/// Turn off blinking.
43+
ANSI_BLINK_OFF = "25";
44+
/// Turn off inverted text colours.
45+
ANSI_INVERT_OFF = "27";
46+
/// Set the foreground colour to black.
47+
ANSI_FG_BLACK = "30";
48+
/// Set the foreground colour to red.
49+
ANSI_FG_RED = "31";
50+
/// Set the foreground colour to green.
51+
ANSI_FG_GREEN = "32";
52+
/// Set the foreground colour to yellow.
53+
ANSI_FG_YELLOW = "33";
54+
/// Set the foreground colour to blue.
55+
ANSI_FG_BLUE = "34";
56+
/// Set the foreground colour to magenta.
57+
ANSI_FG_MAGENTA = "35";
58+
/// Set the foreground colour to cyan.
59+
ANSI_FG_CYAN = "36";
60+
/// Set the foreground colour to white.
61+
ANSI_FG_WHITE = "37";
62+
/// Set the default foreground colour.
63+
ANSI_FG_DEFAULT = "39";
64+
/// Set the background colour to black.
65+
ANSI_BG_BLACK = "40";
66+
/// Set the background colour to red.
67+
ANSI_BG_RED = "41";
68+
/// Set the background colour to green.
69+
ANSI_BG_GREEN = "42";
70+
/// Set the background colour to yellow.
71+
ANSI_BG_YELLOW = "43";
72+
/// Set the background colour to blue.
73+
ANSI_BG_BLUE = "44";
74+
/// Set the background colour to magenta.
75+
ANSI_BG_MAGENTA = "45";
76+
/// Set the background colour to cyan.
77+
ANSI_BG_CYAN = "46";
78+
/// Set the background colour to white.
79+
ANSI_BG_WHITE = "47";
80+
/// Set the default background colour.
81+
ANSI_BG_DEFAULT = "49";
82+
/// Set the foreground colour to bright black.
83+
ANSI_FG_B_BLACK = "90";
84+
/// Set the foreground colour to bright red.
85+
ANSI_FG_B_RED = "91";
86+
/// Set the foreground colour to bright green.
87+
ANSI_FG_B_GREEN = "92";
88+
/// Set the foreground colour to bright yellow.
89+
ANSI_FG_B_YELLOW = "93";
90+
/// Set the foreground colour to bright blue.
91+
ANSI_FG_B_BLUE = "94";
92+
/// Set the foreground colour to bright magenta.
93+
ANSI_FG_B_MAGENTA = "95";
94+
/// Set the foreground colour to bright cyan.
95+
ANSI_FG_B_CYAN = "96";
96+
/// Set the foreground colour to bright white.
97+
ANSI_FG_B_WHITE = "97";
98+
];
99+
100+
macro_rules! define_cursor_appearance {
101+
[$(
102+
$(#[$doc:meta])+
103+
$name:ident($num:expr);
104+
)*] => {$(
105+
$(#[$doc])+
106+
pub const $name: &str = concat!("\u{001b}[?", stringify!($num), "c");
107+
)*}
108+
}
109+
110+
define_cursor_appearance![
111+
/// Set the cursor to its default blinking appearance.
112+
ANSI_CURSOR_B_DEFAULT(0);
113+
/// Make the cursor invisible.
114+
ANSI_CURSOR_INVIS(1);
115+
/// Make the cursor a blinking underline.
116+
ANSI_CURSOR_B_UNDER(2);
117+
/// Make the cursor a blinking block.
118+
ANSI_CURSOR_B_BLOCK(8);
119+
/// Set the cursor to its default steady appearance.
120+
ANSI_CURSOR_DEFAULT(112);
121+
/// Set the cursor to a steady underline.
122+
ANSI_CURSOR_UNDER(114);
123+
/// Set the cursor to a steady block.
124+
ANSI_CURSOR_BLOCK(120);
125+
];
126+
127+
macro_rules! define_ansi_cursors {
128+
[$(
129+
$(#[$doc:meta])+
130+
$name:ident = $suffix:literal;
131+
)*] => {
132+
$(
133+
$(#[$doc])+
134+
#[macro_export]
135+
macro_rules! $name {
136+
() => {
137+
concat!("\u{001b}[", $suffix)
138+
};
139+
($n:literal) => {
140+
concat!("\u{001b}[", $n, $suffix)
141+
}
142+
}
143+
)*
144+
};
145+
}
146+
147+
define_ansi_cursors![
148+
/// Move the cursor up the given number of lines.
149+
ansi_cursor_up = "A";
150+
/// Move the cursor down the given number of lines.
151+
ansi_cursor_down = "B";
152+
/// Move the cursor right the given number of lines.
153+
ansi_cursor_right = "C";
154+
/// Move the cursor left the given number of lines.
155+
ansi_cursor_left = "D";
156+
/// Move the cursor down the given number of rows, to column 1.
157+
ansi_cursor_down_col1 = "E";
158+
/// Move the cursor up the given number of rows, to column 1.
159+
ansi_cursor_up_col1 = "F";
160+
/// Move the cursor to the given column in the current row.
161+
ansi_cursor_to_col = "G";
162+
/// Move the cursor to the given row in the current column.
163+
ansi_cursor_to_row = "d";
164+
];
165+
166+
/// Move the cursor to a specified row and column.
167+
#[macro_export]
168+
macro_rules! ansi_cursor_to_pos {
169+
($row:literal, $col:literal) => {
170+
concat!("\u{001b}[", $row, ";", $col, "H")
171+
};
172+
}
173+
174+
/// Move the cursor to the top left of the display.
175+
pub const ANSI_CURSOR_TOP_LEFT: &str = "\u{001b}[H";
176+
177+
/// Hide the cursor.
178+
pub const ANSI_HIDE_CURSOR: &str = "\u{001b}[?25l";
179+
/// Show the cursor.
180+
pub const ANSI_SHOW_CURSOR: &str = "\u{001b}[?25h";
181+
182+
/// Get the cursor position.
183+
pub const ANSI_GET_CURSOR_POS: &str = "\u{001b}[6n";
184+
185+
/// Erase from the cursor to the end of the display.
186+
pub const ANSI_ERASE_CURSOR_TO_END: &str = "\u{001b}[J";
187+
/// Erase from the start of the display to the cursor.
188+
pub const ANSI_ERASE_START_TO_CURSOR: &str = "\u{001b}[1J";
189+
/// Erase the whole display.
190+
pub const ANSI_ERASE_DISPLAY: &str = "\u{001b}[2J";
191+
/// Erase the whole display, along with the scroll-back buffer.
192+
pub const ANSI_ERASE_DISPLAY_SCROLLBACK: &str = "\u{001b}[3J";
193+
194+
/// Erase from the cursor to the end of the line.
195+
pub const ANSI_ERASE_REMAINING_LINE: &str = "\u{001b}[K";
196+
/// Erase from the start of the line to the cursor.
197+
pub const ANSI_ERASE_LINE_TO_CURSOR: &str = "\u{001b}[1K";
198+
/// Erase the entire line.
199+
pub const ANSI_ERASE_LINE: &str = "\u{001b}[2K";
200+
201+
/// Clear all keyboard LEDs.
202+
pub const ANSI_CLEAR_KB_LEDS: &str = "\u{001b}[0q";
203+
/// Set the scroll lock keyboard LED.
204+
pub const ANSI_SCROLL_LOCK_LED: &str = "\u{001b}[1q";
205+
/// Set the num lock keyboard LED.
206+
pub const ANSI_NUM_LOCK_LED: &str = "\u{001b}[2q";
207+
/// Set the caps lock keyboard LED.
208+
pub const ANSI_CAPS_LOCK_LED: &str = "\u{001b}[3q";
209+
210+
/// Save the current cursor location.
211+
pub const ANSI_SAVE_CURSOR: &str = "\u{001b}[s";
212+
/// Restore the saved cursor location.
213+
pub const ANSI_RESTORE_CURSOR: &str = "\u{001b}[u";
214+
215+
/// An ECMA-48 display attribute.
216+
#[allow(missing_docs)]
217+
#[repr(usize)]
218+
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
219+
pub enum DisplayAttr {
220+
Reset = 0,
221+
Bold = 1,
222+
HalfBright = 2,
223+
Italic = 3,
224+
Underscore = 4,
225+
Blink = 5,
226+
Inverted = 7,
227+
Underline = 21,
228+
NormalIntensity = 22,
229+
ItalicOff = 23,
230+
UnderlineOff = 24,
231+
BlinkOff = 25,
232+
InvertedOff = 27,
233+
BlackFg = 30,
234+
RedFg = 31,
235+
GreenFg = 32,
236+
YellowFg = 33,
237+
BlueFg = 34,
238+
MagentaFg = 35,
239+
CyanFg = 36,
240+
WhiteFg = 37,
241+
DefaultFg = 39,
242+
BlackBg = 40,
243+
RedBg = 41,
244+
GreenBg = 42,
245+
YellowBg = 43,
246+
BlueBg = 44,
247+
MagentaBg = 45,
248+
CyanBg = 46,
249+
WhiteBg = 47,
250+
DefaultBg = 49,
251+
BrightBlackFg = 90,
252+
BrightRedFg = 91,
253+
BrightGreenFg = 92,
254+
BrightYellowFg = 93,
255+
BrightBlueFg = 94,
256+
BrightMagentaFg = 95,
257+
BrightCyanFg = 96,
258+
BrightWhiteFg = 97,
259+
BrightBlackBg = 100,
260+
BrightRedBg = 101,
261+
BrightGreenBg = 102,
262+
BrightYellowBg = 103,
263+
BrightBlueBg = 104,
264+
BrightMagentaBg = 105,
265+
BrightCyanBg = 106,
266+
BrightWhiteBg = 107,
267+
}
268+
269+
/// Creates an ECMA-48 sequence capable of setting the given [`DisplayAttr`]s.
270+
#[must_use]
271+
pub fn display_seq(display_attrs: &[DisplayAttr]) -> String {
272+
let mut seq = String::with_capacity((display_attrs.len() * 4) + 3);
273+
seq.push_str("\u{001b}[");
274+
for (i, &display_attr) in display_attrs.iter().enumerate() {
275+
seq.push_str((display_attr as usize).to_string().as_str());
276+
if i < (display_attrs.len() - 1) {
277+
seq.push(';');
278+
}
279+
}
280+
seq.push('m');
281+
seq
282+
}
283+
284+
#[cfg(test)]
285+
mod tests {
286+
use super::*;
287+
288+
#[test_case]
289+
fn empty_ecma_display_seq() {
290+
assert_eq!(display_seq(&[]).as_str(), "\u{001b}[m");
291+
}
292+
293+
#[test_case]
294+
fn ecma_display_seq() {
295+
assert_eq!(
296+
display_seq(&[
297+
DisplayAttr::Bold,
298+
DisplayAttr::BlueBg,
299+
DisplayAttr::RedFg,
300+
DisplayAttr::BlinkOff
301+
])
302+
.as_str(),
303+
"\u{001b}[1;44;31;25m"
304+
);
305+
}
306+
}

0 commit comments

Comments
 (0)