Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 11 additions & 4 deletions build.zig
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,26 @@ const std = @import("std");
pub fn build(b: *std.Build) void {
const target = b.standardTargetOptions(.{});
const optimize = b.standardOptimizeOption(.{});
const exe = b.addExecutable(.{
.name = "ziglets",
const exe_root_module = b.createModule(.{
.root_source_file = b.path("src/main.zig"),
.target = target,
.optimize = optimize,
});
const exe = b.addExecutable(.{
.name = "ziglets",
.root_module = exe_root_module,
.version = std.SemanticVersion.parse("0.1.0") catch null,
});
b.installArtifact(exe); // Add test support
const exe_unit_tests = b.addTest(.{
b.installArtifact(exe);

const test_root_module = b.createModule(.{
.root_source_file = b.path("src/tests.zig"),
.target = target,
.optimize = optimize,
});
const exe_unit_tests = b.addTest(.{
.root_module = test_root_module,
});

const run_exe_unit_tests = b.addRunArtifact(exe_unit_tests);

Expand Down
29 changes: 14 additions & 15 deletions src/main.zig
Original file line number Diff line number Diff line change
Expand Up @@ -47,43 +47,42 @@ pub const commands = [_]Command{
};

fn helpHandler(_: std.mem.Allocator, _: []const []const u8) !void {
const stdout = std.io.getStdOut().writer();
try stdout.print(
const io = std.Io.Threaded.global_single_threaded.io();
var stdout_buffer: [0]u8 = undefined;
var stdout = std.Io.File.stdout().writer(io, &stdout_buffer);
try stdout.interface.print(
\\ziglets <command>
\\
\\Available commands:
\\
, .{});
for (commands) |cmd| {
// Print the command name, padded to 10 chars, and its description
try stdout.print(" {s: <12} {s}\n", .{ cmd.name, cmd.description });
try stdout.interface.print(" {s: <12} {s}\n", .{ cmd.name, cmd.description });
}
try stdout.print("\n", .{});
try stdout.interface.print("\n", .{});
}

pub fn main() !void {
pub fn main(init: std.process.Init.Minimal) !void {
var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
defer arena.deinit();

var args_iter = try std.process.argsWithAllocator(arena.allocator());
var args = std.ArrayList([]const u8).init(arena.allocator());

while (true) {
const arg = args_iter.next();
if (arg == null) break;
try args.append(arg.?);
const raw_args = try std.process.Args.toSlice(init.args, arena.allocator());
const args = try arena.allocator().alloc([]const u8, raw_args.len);
for (raw_args, 0..) |arg, i| {
args[i] = arg;
}

if (args.items.len < 2) {
if (args.len < 2) {
std.debug.print("Usage: ziglets <command>\n", .{});
std.debug.print("Try 'ziglets help' for more information.\n", .{});
return error.InvalidArguments;
}

const command = args.items[1];
const command = args[1];
for (commands) |cmd| {
if (std.mem.eql(u8, command, cmd.name)) {
try cmd.handler(arena.allocator(), args.items[2..]);
try cmd.handler(arena.allocator(), args[2..]);
return;
}
}
Expand Down
64 changes: 30 additions & 34 deletions src/ziglets/calculator.zig
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ const State = struct {
};

// Print the calculator display
fn printDisplay(state: *State, writer: anytype) !void {
fn printDisplay(state: *State, writer: *std.Io.Writer) !void {
if (state.entering_operand) {
try writer.print("\r{d:.8} ", .{state.operand});
} else {
Expand Down Expand Up @@ -67,16 +67,6 @@ const RawMode = if (builtin.os.tag == .windows) struct {
const posix = std.posix;

// Definizione manuale dei flag POSIX se non presenti in std.posix
const ICANON: u32 = 0x0002; // 0b0000000000000010
const ECHO: u32 = 0x0008; // 0b0000000000001000
const ISIG: u32 = 0x0001; // 0b0000000000000001
const IEXTEN: u32 = 0x8000; // 0b1000000000000000
const IXON: u32 = 0x0400; // 0b0000010000000000
const ICRNL: u32 = 0x0100; // 0b0000000100000000
const BRKINT: u32 = 0x0002; // 0b0000000000000010
const INPCK: u32 = 0x0010; // 0b0000000001000000
const ISTRIP: u32 = 0x0020; // 0b0000000010000000
const OPOST: u32 = 0x0001; // 0b0000000000000001
const VMIN: u32 = 6; // 0b0000000000010110
const VTIME: u32 = 5; // 0b0000000000010101

Expand All @@ -88,9 +78,16 @@ const RawMode = if (builtin.os.tag == .windows) struct {
var raw = original_termios;

// Disabilita echo, modalità canonica e segnali
raw.lflag = @bitCast(@as(u32, @bitCast(raw.lflag)) & ~@as(u32, ICANON | ECHO | ISIG | IEXTEN));
raw.iflag = @bitCast(@as(u32, @bitCast(raw.iflag)) & ~@as(u32, IXON | ICRNL | BRKINT | INPCK | ISTRIP));
raw.oflag = @bitCast(@as(u32, @bitCast(raw.oflag)) & ~@as(u32, OPOST));
raw.lflag.ICANON = false;
raw.lflag.ECHO = false;
raw.lflag.ISIG = false;
raw.lflag.IEXTEN = false;
raw.iflag.IXON = false;
raw.iflag.ICRNL = false;
raw.iflag.BRKINT = false;
raw.iflag.INPCK = false;
raw.iflag.ISTRIP = false;
raw.oflag.OPOST = false;
raw.cc[VMIN] = 1;
raw.cc[VTIME] = 0;

Expand All @@ -103,35 +100,34 @@ const RawMode = if (builtin.os.tag == .windows) struct {
};

pub fn run(_: std.mem.Allocator, _: []const []const u8) !void {
const io = std.Io.Threaded.global_single_threaded.io();
var state = State{};
var stdin = std.io.getStdIn().reader();
var stdout = std.io.getStdOut().writer();
var stdin_buffer: [128]u8 = undefined;
var stdout_buffer: [0]u8 = undefined;
var stdin = std.Io.File.stdin().reader(io, &stdin_buffer);
var stdout = std.Io.File.stdout().writer(io, &stdout_buffer);

// Abilita la modalità raw per l'input istantaneo
try RawMode.enable();
defer {
RawMode.disable() catch {};
}

try stdout.print("Calculator (press Q to exit)\n", .{});
try printDisplay(&state, stdout);
try stdout.interface.print("Calculator (press Q to exit)\n", .{});
try printDisplay(&state, &stdout.interface);

while (true) {
var buf: [1]u8 = undefined;

// Leggiamo un singolo carattere (ora senza bisogno di premere Enter)
const bytes_read = stdin.read(&buf) catch |err| {
try stdout.print("\nError durante la lettura: {s}\n", .{@errorName(err)});
return err;
const c = stdin.interface.takeByte() catch |err| switch (err) {
error.EndOfStream => return,
error.ReadFailed => {
try stdout.interface.print("\nError durante la lettura: {s}\n", .{@errorName(stdin.err.?)});
return stdin.err.?;
Comment on lines 120 to +125
},
};

// Se non abbiamo letto nulla, continuiamo
if (bytes_read == 0) continue;

const c = buf[0];

if (c == 'q' or c == 'Q') { // Q key
try stdout.print("\nBye!\n", .{});
try stdout.interface.print("\nBye!\n", .{});
return;
}

Expand All @@ -156,7 +152,7 @@ pub fn run(_: std.mem.Allocator, _: []const []const u8) !void {
else => digit = 0, // Should not happen due to the check above
}
state.operand = state.operand * 10 + digit;
try printDisplay(&state, stdout);
try printDisplay(&state, &stdout.interface);
} else if (c == '.' or c == ',') {
// Decimal point not implemented for simplicity
} else if (c == '+' or c == '-' or c == '*' or c == '/') {
Expand All @@ -170,23 +166,23 @@ pub fn run(_: std.mem.Allocator, _: []const []const u8) !void {
state.operand = 0;
}
state.op = c;
try printDisplay(&state, stdout);
try printDisplay(&state, &stdout.interface);
} else if (c == '=' or c == '\r' or c == '\n') {
if (state.op != null and state.entering_operand) {
applyOp(&state);
state.op = null;
state.entering_operand = false;
state.operand = 0;
try printDisplay(&state, stdout);
try printDisplay(&state, &stdout.interface);
}
} else if (c == 8 or c == 127) { // Backspace
if (state.entering_operand) {
state.operand = @floor(state.operand / 10);
try printDisplay(&state, stdout);
try printDisplay(&state, &stdout.interface);
}
} else if (c == 'c' or c == 'C') { // Clear
state = State{};
try printDisplay(&state, stdout);
try printDisplay(&state, &stdout.interface);
}
}
}
19 changes: 12 additions & 7 deletions src/ziglets/clock.zig
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,21 @@ pub fn run(allocator: std.mem.Allocator, args: []const []const u8) !void {
_ = allocator; // allocator not used in this implementation
_ = args; // args not used in this implementation

const stdout = std.io.getStdOut().writer();
const io = std.Io.Threaded.global_single_threaded.io();
var stdout_buffer: [0]u8 = undefined;
var stdout = std.Io.File.stdout().writer(io, &stdout_buffer);

// Print initial message
try stdout.print("Terminal Clock - Press Ctrl+C to exit\n\n", .{});
try stdout.interface.print("Terminal Clock - Press Ctrl+C to exit\n\n", .{});

// Simple implementation that works on all platforms
while (true) {
// Clear the current line and move cursor to beginning
try stdout.print("\r", .{});
try stdout.interface.print("\r", .{});

// Get current time
const timestamp = std.time.timestamp();
const epoch_seconds = @as(u64, @intCast(timestamp));
const timestamp = std.Io.Clock.real.now(io);
const epoch_seconds = @as(u64, @intCast(timestamp.toSeconds()));

// Convert to broken down time (UTC)
const epoch_day = epoch_seconds / std.time.s_per_day;
Expand All @@ -36,10 +38,13 @@ pub fn run(allocator: std.mem.Allocator, args: []const []const u8) !void {
const month_day = calculateMonthDay(day_of_year, isLeapYear(year));

// Display formatted time and date with emojis
try stdout.print("{d:0>4}-{d:0>2}-{d:0>2} {d:0>2}:{d:0>2}:{d:0>2} UTC", .{ year, month_day.month, month_day.day, hours, minutes, seconds });
try stdout.interface.print("{d:0>4}-{d:0>2}-{d:0>2} {d:0>2}:{d:0>2}:{d:0>2} UTC", .{ year, month_day.month, month_day.day, hours, minutes, seconds });

// Sleep for 1 second
std.time.sleep(1 * std.time.ns_per_s);
try std.Io.Clock.Duration.sleep(.{
.clock = .boot,
.raw = .fromSeconds(1),
}, io);
}
}

Expand Down
Loading
Loading