diff --git a/cmd/bulb/operation.ha b/bulb/bulb.ha similarity index 59% rename from cmd/bulb/operation.ha rename to bulb/bulb.ha index 4b2286f..d24c548 100644 --- a/cmd/bulb/operation.ha +++ b/bulb/bulb.ha @@ -1,18 +1,24 @@ use fs; use fmt; use io; +use path; use os; +use strings; -type no_such_board = !void; -type error = (io::error | fs::error | no_such_board); +let bulb_path: []str = []; +@init fn bulb_path() void = bulb_path = strings::split(os::tryenv("BULBPATH", "/var/bulb"), ":"); +@fini fn bulb_path() void = free(bulb_path); -fn strerror(err: error) str = match(err) { +export type no_such_board = !void; +export type error = (io::error | fs::error | no_such_board); + +export fn strerror(err: error) str = match(err) { case no_such_board => return "No such board"; case let err: fs::error => return fs::strerror(err); case let err: io::error => return io::strerror(err); }; -fn read(board: str, number: int) (void | error) = { +export fn read(board: str, number: int) (void | error) = { let location = look_up_board(board)?; let file = os::open(location)?; defer io::close(file)!; @@ -20,7 +26,7 @@ fn read(board: str, number: int) (void | error) = { io::copy(os::stdout, file)?; }; -fn post(board: str, user_name: (str | void), message: str) (void | error) = { +export fn post(board: str, user_name: (str | void), message: str) (void | error) = { let location = look_up_board(board)?; let file = os::open(location, fs::flag::APPEND | fs::flag::WRONLY)?; defer io::close(file)!; @@ -32,6 +38,30 @@ fn post(board: str, user_name: (str | void), message: str) (void | error) = { fmt::fprintf(file, "{}: {}\n", user, message)?; }; +export fn list() (void | error) = { + for (let directory .. bulb_path) list_boards_in(directory)?; +}; + +export fn look_up_board(board: str) (str | no_such_board) = { + static let buf = path::buffer { ... }; + for (let directory .. bulb_path) { + let location = path::set(&buf, directory, board)!; + match (os::stat(location)) { + case fs::filestat => return location; + case => void; + }; + }; + return no_such_board; +}; + +fn list_boards_in(directory: str) (void | fs::error) = { + let entries = os::readdir(directory)?; + defer fs::dirents_free(entries); + for (let entry .. entries) { + fmt::println(entry.name)!; + }; +}; + fn seek_to_nth_last_line(file: io::handle, number: int) (void | io::error) = { let buffer: [256]u8 = [0...]; let end = io::seek(file, 0, io::whence::END)?; diff --git a/cmd/bulb/main.ha b/cmd/bulb/main.ha index 0ea0083..a1802e7 100644 --- a/cmd/bulb/main.ha +++ b/cmd/bulb/main.ha @@ -1,3 +1,4 @@ +use bulb; use errors; use fmt; use fs; @@ -14,10 +15,6 @@ const default_board = "general"; let name = ""; @init fn name() void = name = os::args[0]; -let bulb_path: []str = []; -@init fn bulb_path() void = bulb_path = strings::split(os::tryenv("BULBPATH", "/var/bulb"), ":"); -@fini fn bulb_path() void = free(bulb_path); - export fn main() void = { const cmd = getopt::parse( os::args, @@ -65,9 +62,9 @@ fn subcmd_post(cmd: *getopt::command) void = { let message = strings::join(" ", cmd.args...); defer free(message); - match (post(board, user_name, message)) { - case let err: error => - fmt::errorf("{}: Could not read {}: {}\n", name, board, strerror(err))!; + match (bulb::post(board, user_name, message)) { + case let err: bulb::error => + fmt::errorf("{}: Could not read {}: {}\n", name, board, bulb::strerror(err))!; case void => void; }; }; @@ -88,47 +85,21 @@ fn subcmd_read(cmd: *getopt::command) (void | errors::invalid) = { }; }; - match (read(board, number)) { - case let err: error => - fmt::errorf("{}: Could not read {}: {}\n", name, board, strerror(err))!; + match (bulb::read(board, number)) { + case let err: bulb::error => + fmt::errorf("{}: Could not read {}: {}\n", name, board, bulb::strerror(err))!; case void => void; }; }; fn subcmd_ls(cmd: *getopt::command) void = { - for (let directory .. bulb_path) { - match (list_boards_in(directory)) { - case let err: fs::error => - fmt::errorf( - "{}: Can't list boards in {}: {}\n", - name, - directory, - fs::strerror(err))!; - case void => void; - }; + match (bulb::list()) { + case let err: bulb::error => + fmt::errorf("{}: Could not list boards: {}\n", name, bulb::strerror(err))!; + case void => void; }; }; -fn list_boards_in(directory: str) (void | fs::error) = { - let entries = os::readdir(directory)?; - defer fs::dirents_free(entries); - for (let entry .. entries) { - fmt::println(entry.name)!; - }; -}; - -fn look_up_board(board: str) (str | no_such_board) = { - static let buf = path::buffer { ... }; - for (let directory .. bulb_path) { - let location = path::set(&buf, directory, board)!; - match (os::stat(location)) { - case fs::filestat => return location; - case => void; - }; - }; - return no_such_board; -}; - fn get_user_name() str = { // FIXME: could not find support for getting a username from a uid in // hare. when it is added, use that here.