sys

A set of unix utils in hare!
Log | Files | Refs | README

main.ha (2066B)


      1 use fmt;
      2 use io;
      3 use bufio;
      4 use strings;
      5 use fs;
      6 use os;
      7 use ascii;
      8 use strconv;
      9 
     10 use util;
     11 
     12 type command = struct {
     13 	c: rune,
     14 	range: (size, size),
     15 	args: []str
     16 };
     17 
     18 let file: nullable *lines = null;
     19 let pos: size = 0;
     20 
     21 fn loadfile(h: io::handle) nullable *lines = {
     22 	let ls: nullable *lines = null;
     23 	let sc = bufio::newscanner(h);
     24 	defer bufio::finish(&sc);
     25 
     26 	for (true) {
     27 		match (bufio::scan_line(&sc)) {
     28 		case let s: str =>
     29 			match (ls) {
     30 			case let ls: *lines =>
     31 				ls.next = newline(strings::dup(s)!);
     32 				(ls.next as *lines).prev = ls;
     33 			case null => ls = newline(strings::dup(s)!);
     34 			};
     35 		case io::EOF => break;
     36 		case => abort();
     37 		};
     38 	};
     39 
     40 	return ls;
     41 };
     42 
     43 fn openfile(name: str) nullable *lines = {
     44 	let h = match(os::open(name)) {
     45 	case let h: io::file => yield h;
     46 	case let e: fs::error => util::die(fs::strerror(e));
     47 	};
     48 	defer io::close(h)!;
     49 
     50 	return loadfile(h);
     51 };
     52 
     53 fn parsenum(runes: []rune) (size, []rune) = {
     54 	let digits: []rune = [];
     55 	defer free(digits);
     56 
     57 	let i = 0z;
     58 
     59 	for (ascii::isdigit(runes[i])) {
     60 		append(digits, runes[i])!;
     61 		i += 1;
     62 	};
     63 
     64 	let num = strings::fromrunes(digits)!;
     65 	defer free(num);
     66 
     67 	return (strconv::stoz(num)!, runes[i..]);
     68 };
     69 
     70 fn parsecmd(s: str) command = {
     71 	let c: command = command{c = ' ', range = (-1, -1), args = []};
     72 
     73 	let runes = strings::torunes(s)!;
     74 	let sav = runes;
     75 	defer free(sav);
     76 
     77 	if (ascii::isdigit(runes[0])) {
     78 		let res = parsenum(runes);
     79 		c.range.0 = res.0; runes = res.1;
     80 		if (runes[0] == ',') {
     81 			res = parsenum(runes[1..]);
     82 			c.range.0 = res.0; runes = res.1;
     83 		} else c.range.1 = -1;
     84 	} else c.range = (-1, -1);
     85 
     86 	c.c = runes[0];
     87 
     88 	return c;
     89 };
     90 
     91 fn runcmd() void = {
     92 	let sc = bufio::newscanner(os::stdin);
     93 	defer bufio::finish(&sc);
     94 
     95 	let in = parsecmd(bufio::scan_line(&sc) as str);
     96 
     97 	for (let c .. cmds) {
     98 		if (c.cmd == in.c) {
     99 			c.f(&(file as *lines), &pos, in.range, in.args);
    100 			break;
    101 		};
    102 	};
    103 };
    104 
    105 export fn main() void = {
    106 	if (len(os::args) < 2) {
    107 		util::die("", "needs a file!");
    108 	};
    109 	let f = os::open(os::args[1])!;
    110 	file = loadfile(f);
    111 
    112 	for (true) {
    113 		runcmd();
    114 	};
    115 };