Open directories of files

You can pass files / dirs as arguments an they will be opened. The
directories will be searched for text files (as identified by libmagic)
and those text files will be displayed too.
This commit is contained in:
Nathan McRae 2023-06-20 22:32:04 -07:00
parent 0da13751d5
commit 32c0b9bb5c
2 changed files with 330 additions and 280 deletions

View File

@ -7,6 +7,7 @@ pub fn build(b: *Builder) void {
exe.setBuildMode(mode);
exe.linkSystemLibrary("SDL2");
exe.linkSystemLibrary("SDL2_TTF");
exe.linkSystemLibrary("magic");
exe.linkSystemLibrary("c");
b.default_step.dependOn(&exe.step);

View File

@ -1,280 +1,329 @@
const std = @import("std");
const c = @cImport({
@cInclude("SDL.h");
@cInclude("SDL_ttf.h");
});
const assert = @import("std").debug.assert;
const DrawnText = struct {
surface: [*c]c.SDL_Surface,
texture: ?*c.SDL_Texture,
rect: c.SDL_Rect,
};
const FileDocMap = struct {
title_text: DrawnText,
contents: []u8,
};
pub fn main() !void {
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
defer {
if(gpa.deinit()) {
std.debug.print("Allocator leak\n", .{});
}
}
const allocator = gpa.allocator();
const window_width = 300;
const window_height = 500;
const column_width = 100;
if (c.SDL_Init(c.SDL_INIT_VIDEO) != 0) {
c.SDL_Log("Unable to initialize SDL: %s", c.SDL_GetError());
return error.SDLInitializationFailed;
}
defer c.SDL_Quit();
const screen = c.SDL_CreateWindow("Document Map Viewer", c.SDL_WINDOWPOS_UNDEFINED, c.SDL_WINDOWPOS_UNDEFINED, window_width, window_height, c.SDL_WINDOW_OPENGL) orelse
{
c.SDL_Log("Unable to create window: %s", c.SDL_GetError());
return error.SDLInitializationFailed;
};
defer c.SDL_DestroyWindow(screen);
const renderer = c.SDL_CreateRenderer(screen, -1, 0) orelse {
c.SDL_Log("Unable to create renderer: %s", c.SDL_GetError());
return error.SDLInitializationFailed;
};
defer c.SDL_DestroyRenderer(renderer);
// Turn on anti-aliasing
// :( doesn't seem to work
const aa_result = c.SDL_SetHint(c.SDL_HINT_RENDER_SCALE_QUALITY, "1");
if (aa_result != c.SDL_TRUE) {
c.SDL_Log("Unable to set anti-aliasing: %d", c.SDL_GetError());
return error.SDLInitializationFailed;
}
// https://github.com/cirosantilli/cpp-cheat/blob/e52ed4b838e2697d8f44ab5bef3e7a170705d48e/sdl/ttf.c
const ttf_init_result: c_int = c.TTF_Init();
if (ttf_init_result != 0) {
c.SDL_Log("Unable to init TTF: %d", ttf_init_result);
return error.TTFInitializationFailed;
}
defer c.TTF_Quit();
const text_color: c.SDL_Color = c.SDL_Color {
.r = 0,
.g = 0,
.b = 0,
.a = 255
};
// TODO: can we embed this file?
const font: ?*c.TTF_Font = c.TTF_OpenFont("FreeSans.ttf", 12);
if (font == null) {
const err = c.TTF_GetError();
c.SDL_Log("Unable to load font: %s", err);
return error.TTFFontLoadFailed;
}
var file_paths = std.ArrayList([]const u8).init(allocator);
defer file_paths.deinit();
try file_paths.append("src/main.zig");
try file_paths.append("GapProbeScan.cs");
var file_docmaps = std.ArrayList(FileDocMap).init(allocator);
defer file_docmaps.deinit();
for (file_paths.items) |path| {
const surface: [*c]c.SDL_Surface = c.TTF_RenderText_Solid(font, @ptrCast([*c]const u8, path), text_color);
if (surface == null) {
c.SDL_Log("Unable to render text");
return error.RenderTextFailed;
}
const texture: ?*c.SDL_Texture = c.SDL_CreateTextureFromSurface(renderer, surface);
if (texture == null) {
c.SDL_Log("Unable to create texture from surface");
return error.CreateTextureFailed;
}
var rect = c.SDL_Rect {
.x = 0,
.y = 0,
.w = surface.*.w,
.h = surface.*.h,
};
const file = try std.fs.cwd().openFile(path, .{ });
defer file.close();
const stat = try file.stat();
var buffer = try allocator.alloc(u8, stat.size);
const bytes_read = try file.readAll(buffer);
if (bytes_read != stat.size) {
std.debug.print("bytes_read: {any}, stat.size: {any}\n", .{
bytes_read,
stat.size,
});
return error.FileReadError;
}
var docmap = FileDocMap {
.title_text = DrawnText {
.surface = surface,
.texture = texture,
.rect = rect,
},
.contents = buffer,
};
try file_docmaps.append(docmap);
}
defer {
for (file_docmaps.items) |docmap| {
c.SDL_FreeSurface(docmap.title_text.surface);
c.SDL_DestroyTexture(docmap.title_text.texture);
allocator.free(docmap.contents);
}
}
const color_result: c_int = c.SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
if (color_result != 0) {
c.SDL_Log("Unable to set draw color: %d", color_result);
return error.SDLInitializationFailed;
}
// const surface = c.SDL_GetWindowSurface(screen);
var quit = false;
while (!quit) {
var event: c.SDL_Event = undefined;
while (c.SDL_PollEvent(&event) != 0) {
switch (event.@"type") {
c.SDL_QUIT => {
quit = true;
},
else => {},
}
}
const initial_color_result = c.SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
if (initial_color_result != 0) {
c.SDL_Log("Unable to set draw color: %d", initial_color_result);
return error.SDLInitializationFailed;
}
// Draw white background
var x: c_int = 0;
while (x < window_width) : (x += 1) {
var y: c_int = 0;
while (y < window_height) : (y += 1) {
const draw_result = c.SDL_RenderDrawPoint(renderer, x, y);
if (draw_result != 0) {
c.SDL_Log("Unable to draw point: %d", draw_result);
return error.SDLDrawingFailed;
}
}
}
var i: usize = 0;
var column: c_int = 0;
x = 0;
var y: c_int = 0;
for (file_docmaps.items) |docmap| {
i = 0;
var rect = c.SDL_Rect {
.x = x,
.y = y,
.w = docmap.title_text.surface.*.w,
.h = docmap.title_text.surface.*.h,
};
// Display text
if (c.SDL_RenderCopy(renderer, docmap.title_text.texture, null, &rect) != 0) {
c.SDL_Log("Unable to render copy");
}
y += docmap.title_text.rect.h;
// white: false, black: true
var color: bool = false;
while (i < docmap.contents.len) : (i += 1) {
if (docmap.contents[i] == 10) {
y += 1;
if (y > window_height) {
y = 0;
column += 1;
// std.debug.print("Column: {any}, x: {any}\n", .{column, column*column_width});
}
x = column * column_width;
continue;
}
if (docmap.contents[i] == 32 and color) {
color = false;
const white_color_result = c.SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
if (white_color_result != 0) {
c.SDL_Log("Unable to set draw color: %d", white_color_result);
return error.SDLInitializationFailed;
}
} else if (docmap.contents[i] != 32 and !color) {
color = true;
const black_color_result = c.SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
if (black_color_result != 0) {
c.SDL_Log("Unable to set draw color: %d", black_color_result);
return error.SDLInitializationFailed;
}
}
if (x < (column + 1) * column_width) {
const draw_result = c.SDL_RenderDrawPoint(renderer, x, y);
if (draw_result != 0) {
c.SDL_Log("Unable to draw point: %d", draw_result);
return error.SDLDrawingFailed;
}
} else {
const red_color_result = c.SDL_SetRenderDrawColor(renderer, 255, 0, 0, 255);
if (red_color_result != 0) {
c.SDL_Log("Unable to set draw color: %d", red_color_result);
return error.SDLInitializationFailed;
}
const draw_result = c.SDL_RenderDrawPoint(renderer, (column + 1) * column_width - 1, y);
if (draw_result != 0) {
c.SDL_Log("Unable to draw point: %d", draw_result);
return error.SDLDrawingFailed;
}
if (!color) {
const white_color_result = c.SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
if (white_color_result != 0) {
c.SDL_Log("Unable to set draw color: %d", white_color_result);
return error.SDLInitializationFailed;
}
} else {
const black_color_result = c.SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
if (black_color_result != 0) {
c.SDL_Log("Unable to set draw color: %d", black_color_result);
return error.SDLInitializationFailed;
}
}
}
x += 1;
}
}
c.SDL_RenderPresent(renderer);
c.SDL_Delay(17);
}
}
const std = @import("std");
const c = @cImport({
@cInclude("SDL.h");
@cInclude("SDL_ttf.h");
});
const m = @cImport({
@cInclude("magic.h");
});
const assert = @import("std").debug.assert;
const DrawnText = struct {
surface: [*c]c.SDL_Surface,
texture: ?*c.SDL_Texture,
rect: c.SDL_Rect,
};
const FileDocMap = struct {
title_text: DrawnText,
contents: []u8,
};
pub fn main() !void {
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
defer {
if (gpa.deinit()) {
std.debug.print("Allocator leak\n", .{});
}
}
var magic = m.magic_open(m.MAGIC_MIME | m.MAGIC_CHECK);
const load_result = m.magic_load(magic, null);
if (load_result != 0) {
std.debug.print("Unable to initialize magic: {d}", .{load_result});
return error.MagicInitializationFailed;
}
const allocator = gpa.allocator();
const args = try std.process.argsAlloc(allocator);
defer std.process.argsFree(allocator, args);
const window_width = 700;
const window_height = 500;
const column_width = 100;
if (c.SDL_Init(c.SDL_INIT_VIDEO) != 0) {
c.SDL_Log("Unable to initialize SDL: %s", c.SDL_GetError());
return error.SDLInitializationFailed;
}
defer c.SDL_Quit();
const screen = c.SDL_CreateWindow("Document Map Viewer", c.SDL_WINDOWPOS_UNDEFINED, c.SDL_WINDOWPOS_UNDEFINED, window_width, window_height, c.SDL_WINDOW_OPENGL) orelse
{
c.SDL_Log("Unable to create window: %s", c.SDL_GetError());
return error.SDLInitializationFailed;
};
defer c.SDL_DestroyWindow(screen);
const renderer = c.SDL_CreateRenderer(screen, -1, 0) orelse {
c.SDL_Log("Unable to create renderer: %s", c.SDL_GetError());
return error.SDLInitializationFailed;
};
defer c.SDL_DestroyRenderer(renderer);
// Turn on anti-aliasing
// :( doesn't seem to work
const aa_result = c.SDL_SetHint(c.SDL_HINT_RENDER_SCALE_QUALITY, "1");
if (aa_result != c.SDL_TRUE) {
c.SDL_Log("Unable to set anti-aliasing: %d", c.SDL_GetError());
return error.SDLInitializationFailed;
}
// https://github.com/cirosantilli/cpp-cheat/blob/e52ed4b838e2697d8f44ab5bef3e7a170705d48e/sdl/ttf.c
const ttf_init_result: c_int = c.TTF_Init();
if (ttf_init_result != 0) {
c.SDL_Log("Unable to init TTF: %d", ttf_init_result);
return error.TTFInitializationFailed;
}
defer c.TTF_Quit();
const text_color: c.SDL_Color = c.SDL_Color{ .r = 0, .g = 0, .b = 0, .a = 255 };
// TODO: can we embed this file?
const font: ?*c.TTF_Font = c.TTF_OpenFont("FreeSans.ttf", 12);
if (font == null) {
const err = c.TTF_GetError();
c.SDL_Log("Unable to load font: %s", err);
return error.TTFFontLoadFailed;
}
var file_paths = std.ArrayList([]const u8).init(allocator);
defer file_paths.deinit();
defer {
for (file_paths.items) |item| {
allocator.free(item);
}
}
var args_i: usize = 1;
while (args_i < args.len) : (args_i += 1) {
const arg = args[args_i];
if (std.fs.cwd().openIterableDir(arg, .{})) |iter_dir| {
std.debug.print("searching dir for files: '{s}'\n", .{arg});
var iter = iter_dir.iterate();
while (try iter.next()) |entry| {
if (entry.kind == .File) {
const entry_path = try std.fmt.allocPrint(allocator, "{s}{c}{s}\x00", .{
arg,
std.fs.path.sep,
entry.name,
});
const magic_result = m.magic_file(magic, @ptrCast([*c]const u8, entry_path));
std.debug.print("'{s}': {s}\n", .{ entry.name, magic_result });
if (std.mem.eql(u8, magic_result[0..5], "text/")) {
try file_paths.append(entry_path[0..(entry_path.len - 1)]);
} else {
allocator.free(entry_path);
}
}
}
} else |_| {
if (std.fs.cwd().openFile(arg, .{})) |file| {
file.close();
std.debug.print("Will do docmap for: '{s}'\n", .{arg});
var path = try allocator.alloc(u8, arg.len);
std.mem.copy(u8, path, arg);
try file_paths.append(path);
} else |_| {
std.debug.print("Arg not file: '{s}'\n", .{arg});
}
}
}
var file_docmaps = std.ArrayList(FileDocMap).init(allocator);
defer file_docmaps.deinit();
for (file_paths.items) |path| {
const surface: [*c]c.SDL_Surface = c.TTF_RenderText_Solid(font, @ptrCast([*c]const u8, path), text_color);
if (surface == null) {
c.SDL_Log("Unable to render text");
return error.RenderTextFailed;
}
const texture: ?*c.SDL_Texture = c.SDL_CreateTextureFromSurface(renderer, surface);
if (texture == null) {
c.SDL_Log("Unable to create texture from surface");
return error.CreateTextureFailed;
}
var rect = c.SDL_Rect{
.x = 0,
.y = 0,
.w = surface.*.w,
.h = surface.*.h,
};
std.debug.print("open file: {s}\n", .{path});
const file = try std.fs.cwd().openFile(path, .{});
defer file.close();
const stat = try file.stat();
var buffer = try allocator.alloc(u8, stat.size);
const bytes_read = try file.readAll(buffer);
if (bytes_read != stat.size) {
std.debug.print("bytes_read: {any}, stat.size: {any}\n", .{
bytes_read,
stat.size,
});
return error.FileReadError;
}
var docmap = FileDocMap{
.title_text = DrawnText{
.surface = surface,
.texture = texture,
.rect = rect,
},
.contents = buffer,
};
try file_docmaps.append(docmap);
}
defer {
for (file_docmaps.items) |docmap| {
c.SDL_FreeSurface(docmap.title_text.surface);
c.SDL_DestroyTexture(docmap.title_text.texture);
allocator.free(docmap.contents);
}
}
const color_result: c_int = c.SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
if (color_result != 0) {
c.SDL_Log("Unable to set draw color: %d", color_result);
return error.SDLInitializationFailed;
}
// const surface = c.SDL_GetWindowSurface(screen);
var quit = false;
while (!quit) {
var event: c.SDL_Event = undefined;
while (c.SDL_PollEvent(&event) != 0) {
switch (event.@"type") {
c.SDL_QUIT => {
quit = true;
},
else => {},
}
}
const initial_color_result = c.SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
if (initial_color_result != 0) {
c.SDL_Log("Unable to set draw color: %d", initial_color_result);
return error.SDLInitializationFailed;
}
// Draw white background
var x: c_int = 0;
while (x < window_width) : (x += 1) {
var y: c_int = 0;
while (y < window_height) : (y += 1) {
const draw_result = c.SDL_RenderDrawPoint(renderer, x, y);
if (draw_result != 0) {
c.SDL_Log("Unable to draw point: %d", draw_result);
return error.SDLDrawingFailed;
}
}
}
var i: usize = 0;
var column: c_int = 0;
x = 0;
var y: c_int = 0;
for (file_docmaps.items) |docmap| {
i = 0;
var rect = c.SDL_Rect{
.x = x,
.y = y,
.w = docmap.title_text.surface.*.w,
.h = docmap.title_text.surface.*.h,
};
// Display text
if (c.SDL_RenderCopy(renderer, docmap.title_text.texture, null, &rect) != 0) {
c.SDL_Log("Unable to render copy");
}
y += docmap.title_text.rect.h;
// white: false, black: true
var color: bool = false;
while (i < docmap.contents.len) : (i += 1) {
if (docmap.contents[i] == 10) {
y += 1;
if (y > window_height) {
y = 0;
column += 1;
// std.debug.print("Column: {any}, x: {any}\n", .{column, column*column_width});
}
x = column * column_width;
continue;
}
if (docmap.contents[i] == 32 and color) {
color = false;
const white_color_result = c.SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
if (white_color_result != 0) {
c.SDL_Log("Unable to set draw color: %d", white_color_result);
return error.SDLInitializationFailed;
}
} else if (docmap.contents[i] != 32 and !color) {
color = true;
const black_color_result = c.SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
if (black_color_result != 0) {
c.SDL_Log("Unable to set draw color: %d", black_color_result);
return error.SDLInitializationFailed;
}
}
if (x < (column + 1) * column_width) {
const draw_result = c.SDL_RenderDrawPoint(renderer, x, y);
if (draw_result != 0) {
c.SDL_Log("Unable to draw point: %d", draw_result);
return error.SDLDrawingFailed;
}
} else {
const red_color_result = c.SDL_SetRenderDrawColor(renderer, 255, 0, 0, 255);
if (red_color_result != 0) {
c.SDL_Log("Unable to set draw color: %d", red_color_result);
return error.SDLInitializationFailed;
}
const draw_result = c.SDL_RenderDrawPoint(renderer, (column + 1) * column_width - 1, y);
if (draw_result != 0) {
c.SDL_Log("Unable to draw point: %d", draw_result);
return error.SDLDrawingFailed;
}
if (!color) {
const white_color_result = c.SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
if (white_color_result != 0) {
c.SDL_Log("Unable to set draw color: %d", white_color_result);
return error.SDLInitializationFailed;
}
} else {
const black_color_result = c.SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
if (black_color_result != 0) {
c.SDL_Log("Unable to set draw color: %d", black_color_result);
return error.SDLInitializationFailed;
}
}
}
x += 1;
}
}
c.SDL_RenderPresent(renderer);
c.SDL_Delay(17);
}
}