Initial commit
This commit is contained in:
commit
22c5179503
27
README.md
Normal file
27
README.md
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
# bulb
|
||||||
|
|
||||||
|
A simple bulletin board for your server. Users of the system can post and read
|
||||||
|
messages using the "bulb" command. You can also set up multiple boards.
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
To list available boards:
|
||||||
|
|
||||||
|
```
|
||||||
|
bulb
|
||||||
|
```
|
||||||
|
|
||||||
|
To post a message:
|
||||||
|
|
||||||
|
```
|
||||||
|
bulb post Message text
|
||||||
|
bulb post -b <board-name> Message text
|
||||||
|
```
|
||||||
|
|
||||||
|
To read recent messages:
|
||||||
|
|
||||||
|
```
|
||||||
|
bulb read
|
||||||
|
bulb read -b <board-name>
|
||||||
|
bulb read -n <message-count>
|
||||||
|
```
|
109
cmd/bulb/main.ha
Normal file
109
cmd/bulb/main.ha
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
use errors;
|
||||||
|
use fmt;
|
||||||
|
use fs;
|
||||||
|
use getopt;
|
||||||
|
use os;
|
||||||
|
use strconv;
|
||||||
|
use strings;
|
||||||
|
use unix;
|
||||||
|
|
||||||
|
const default_board = "general";
|
||||||
|
|
||||||
|
let name = "";
|
||||||
|
@init fn name() void = name = os::args[0];
|
||||||
|
|
||||||
|
let path: []str = [];
|
||||||
|
@init fn path() void = path = strings::split(os::tryenv("BULBPATH", "/var/bulb"), ":");
|
||||||
|
@fini fn path() void = free(path);
|
||||||
|
|
||||||
|
export fn main() void = {
|
||||||
|
// parse args
|
||||||
|
const cmd = getopt::parse(
|
||||||
|
os::args,
|
||||||
|
"bulletin board",
|
||||||
|
("post", [
|
||||||
|
('a', "post anonymously"),
|
||||||
|
('b', "board", "which board to post on"),
|
||||||
|
"message...",
|
||||||
|
]): getopt::subcmd_help,
|
||||||
|
("read", [
|
||||||
|
('b', "board", "which board to read"),
|
||||||
|
('n', "number", "display N most recent messages"),
|
||||||
|
]): getopt::subcmd_help);
|
||||||
|
defer getopt::finish(&cmd);
|
||||||
|
|
||||||
|
match (cmd.subcmd) {
|
||||||
|
case let subcmd: (str, *getopt::command) =>
|
||||||
|
if (subcmd.0 == "post") {
|
||||||
|
subcmd_post(subcmd.1);
|
||||||
|
} else if (subcmd.0 == "read") {
|
||||||
|
match (subcmd_read(subcmd.1)) {
|
||||||
|
case errors::invalid =>
|
||||||
|
getopt::printhelp(cmd);
|
||||||
|
os::exit(os::status::FAILURE);
|
||||||
|
case void => void;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
case void =>
|
||||||
|
subcmd_ls(&cmd);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
fn subcmd_post(cmd: *getopt::command) void = {
|
||||||
|
let anonymous = false;
|
||||||
|
let board = default_board;
|
||||||
|
for (let opt .. cmd.opts) {
|
||||||
|
switch (opt.0) {
|
||||||
|
case 'a' => anonymous = true;
|
||||||
|
case 'b' => board = opt.1;
|
||||||
|
case => abort();
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
// TODO
|
||||||
|
};
|
||||||
|
|
||||||
|
fn subcmd_read(cmd: *getopt::command) (void | errors::invalid) = {
|
||||||
|
let board = default_board;
|
||||||
|
let number = 8;
|
||||||
|
for (let opt .. cmd.opts) {
|
||||||
|
switch (opt.0) {
|
||||||
|
case 'b' =>
|
||||||
|
board = opt.1;
|
||||||
|
case 'n' =>
|
||||||
|
match (strconv::stoi(opt.1)) {
|
||||||
|
case let num: int => number = num;
|
||||||
|
case => return errors::invalid;
|
||||||
|
};
|
||||||
|
case => abort();
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
// TODO
|
||||||
|
};
|
||||||
|
|
||||||
|
fn subcmd_ls(cmd: *getopt::command) void = {
|
||||||
|
for (let directory .. 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;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
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, path: []str) (str | void) {
|
||||||
|
// TODO
|
||||||
|
//};
|
Loading…
Reference in New Issue
Block a user