func testText() *wax.Part { t := `- write a ws pg that knows how to display multiple parts with drag and drop and resizes. Play embedding just a chunk of html and later play with embedding something from a different url - write a canvas ctl - port the old canvas text frame using the canvas ctl - write an terminal variant that simply honors In,Out,Err chans on a text frame. - use local storage to save the layout editing state for errors and to recover those if desired - make sure we can share an inner part with controls multiple times (ie not just repeating controls, but parts with controls, although for this we should probably use iframes) - use tls for conns to the registry and peers - put in place some kind of auth - make the registry a hierarchy, so that we can have registry islands and they sync to each other make it use broadcast to discover other machines nearby and propagate island information ` if err := tTxt.Ins([]rune(t), 0); err != nil { dbg.Fatal("txt ins: %s", err) } p, err := wax.New("$txt$") if err != nil { dbg.Fatal("new part: %s", err) } p.SetEnv(map[string]interface{}{"txt": tTxt}) return p }
func usage(err error) { opts.Usage(os.Stderr) fmt.Fprintf(os.Stderr, "\tspec = name | name!file | name!file!flags \n") fmt.Fprintf(os.Stderr, "\tspec flags = ro | rw | ncro | ncrw \n") if err == nil { dbg.Fatal("usage") } dbg.Fatal(err) }
func bexit(c cmd.Ctx) error { args := c.Args xprintf("exiting...\n") if len(args) <= 1 || args[1] == "" { dbg.Fatal("") } else { dbg.Fatal(args[1]) } return nil }
func main() { defer dbg.Exits("") os.Args[0] = "zxdump" dfltdump := zx.Path(dbg.Home, "dump") opts.NewFlag("s", "don't dump right now, wait until next at 5am", &Skip) opts.NewFlag("1", "dump once and exit", &Once) opts.NewFlag("v", "verbose", &Verbose) opts.NewFlag("D", "debug", &Debug) opts.NewFlag("x", "expr: files excluded (.*, tmp.* if none given); tmp always excluded.", &Xcludes) Dump = dfltdump opts.NewFlag("d", "dir: where to keep the dump, or empty if none", &Dump) args, err := opts.Parse(os.Args) if err != nil { dbg.Warn("%s", err) opts.Usage() dbg.Exits(err) } if len(Xcludes) == 0 { Xcludes = []string{".*", "tmp.*", "*.tmp"} } Xcludes = append(Xcludes, "tmp") if len(args) == 0 { dbg.Warn("arguments missing") opts.Usage() dbg.Exits("usage") } if Skip && Once { dbg.Fatal("can't skip the current dump and dump once now") } nt := 0 ec := make(chan bool) for i := 0; i < len(args); i++ { al := strings.SplitN(args[i], "!", 2) if len(al) == 1 { al = append(al, al[0]) al[0] = path.Base(al[0]) } t, err := lfs.New(al[0], al[1], lfs.RO) if err != nil { dbg.Warn("%s: %s", al[0], err) continue } t.ReadAttrs(true) nt++ go dump(Dump, t, ec) } if nt == 0 { dbg.Fatal("no trees to dump") } for nt > 0 { <-ec nt-- } }
func main() { defer dbg.Exits("") os.Args[0] = "zxfs" quiet := false opts.NewFlag("q", "don't print errors to stderr", &quiet) opts.NewFlag("D", "debug and zxfs calls", &zxfs.Debug) opts.NewFlag("r", "read only", &rflag) opts.NewFlag("s", "statistics", &sflag) opts.NewFlag("n", "don't use caching (otherwise write-through cache)", &nocaching) opts.NewFlag("d", "use delayed writes cache", &delayed) opts.NewFlag("Z", "debug zx requests", &zdebug) opts.NewFlag("V", "verbose debug and fuse requests", &fs.Debug) opts.NewFlag("x", "addr: re-export locally the cached tree to this address, if any", &xaddr) opts.NewFlag("m", "use mfs caching", &mfscfs) opts.NewFlag("l", "dir: use lfs caching at dir", &lfsdir) args, err := opts.Parse(os.Args) if err != nil { opts.Usage(os.Stderr) dbg.Fatal(err) } zxfs.Debug = zxfs.Debug || fs.Debug zxfs.Verb = !quiet || zxfs.Debug if fs.Debug { fuse.Debug = func(m interface{}) { fmt.Fprintf(os.Stderr, "fuse: %v\n", m) } } switch len(args) { case 2: addr = args[0] mntdir = args[1] case 1: addr = args[0] default: opts.Usage(os.Stderr) dbg.Fatal("usage") } dprintf("debug on\n") xfs, fn, err := mkfs(addr) if err != nil { dbg.Fatal("%s", err) } defer fn() if nocaching || !delayed { err = ncmount(xfs) } else { dbg.Fatal("delayed write mount is gone") } if err != nil { dbg.Fatal("%s", err) } dbg.Warn("unmounted: exiting") }
func ExampleNew() { // create a tree using the local directory /tmp/cache for the cache dfs, err := lfs.New("cache", "/tmp/cache", lfs.RW) if err != nil { dbg.Fatal("lfs: %s", err) } fs, err := New("example mdfs", dfs) if err != nil { dbg.Fatal("mfds: %s", err) } dbg.Warn("fs %s ready", fs) // Now use it... }
func (m *Msg) Pack() []byte { buf := make([]byte, 0, 100) var n [8]byte if m.Op<Tmin || m.Op>=Tend { dbg.Fatal("unknown msg type %d", m.Op) } buf = append(buf, byte(m.Op)) buf = nchan.PutString(buf, m.Rid) if m.Op==Tget || m.Op==Tput { binary.LittleEndian.PutUint64(n[0:], uint64(m.Off)) buf = append(buf, n[:8]...) } if m.Op == Tget { binary.LittleEndian.PutUint64(n[0:], uint64(m.Count)) buf = append(buf, n[:8]...) } if m.Op==Tput || m.Op==Tmkdir || m.Op==Twstat { buf = append(buf, m.D.Pack()...) } if m.Op == Tmove { buf = nchan.PutString(buf, m.To) } if m.Op==Tfind || m.Op==Tget || m.Op==Tput || m.Op==Tfindget { buf = nchan.PutString(buf, m.Pred) } if m.Op==Tfind || m.Op==Tfindget { buf = nchan.PutString(buf, m.Spref) buf = nchan.PutString(buf, m.Dpref) binary.LittleEndian.PutUint64(n[0:], uint64(m.Depth)) buf = append(buf, n[:8]...) } return buf }
func testfn(t *testing.T, fn func(t fstest.Fataler, fss ...zx.Tree)) { fstest.Repeats = 1 fs, err := mfs.New("example mfs") if err != nil { dbg.Fatal("lfs: %s", err) } xfs, _ := fs.AuthFor(&auth.Info{Uid: dbg.Usr, SpeaksFor: dbg.Usr, Ok: true}) tr := New(xfs) tc := make(chan string) dc := make(chan bool) go func() { for x := range tc { printf("%s\n", x) } dc <- true }() fstest.MkZXTree(t, tr) fs.Dbg = testing.Verbose() if fs.Dbg { defer fs.Dump(os.Stdout) } tr.C = tc if fn != nil { fn(t, tr) } tr.Close(nil) close(tc) <-dc }
func testFor() *wax.Part { forpg := ` Trees: <ul> $for t in repl.Trees do$ <li> Name: $t.Name$; Path: $t.Path$; Kind: $t.Sync$ <ul> $for p in t.Peers do$ <li> $p$ $end$ </ul> $end$ </ul> ` p, err := wax.New(forpg) if err != nil { dbg.Fatal("new part: %s", err) } tenv := map[string]interface{}{"repl": tRepl} p.SetEnv(tenv) return p }
// both for Ninblk and Nhereblk func (nd *Nd) xInBlk() ([]string, error) { xprintf("x %s\n", nd) if len(nd.Child) == 0 { return []string{}, nil } if len(nd.Child)>1 || nd.Child[0].Kind!=Npipe { dbg.Fatal("inblk child bug; it assumes a single pipe in block") return []string{}, dbg.ErrBug } c := nd.Child[0] fd, w, _ := os.Pipe() c.mkExec(nd.Stdin, w, nd.Stderr, nd.args...) c.extraFds(nd) c.closefds = append(c.closefds, w) c.Args = nil // don't & it c.xPipe() var b bytes.Buffer io.Copy(&b, fd) fd.Close() xprintf("x %s done\n", nd) if nd.Kind == Nhereblk { return []string{b.String()}, nil } words := strings.Fields(b.String()) return words, nil }
func ctx() *Ctx { c := AppCtx() if c == nil { dbg.Fatal("no context for %d", runtime.AppId()) } return c }
func testAdt() *wax.Part { p, err := wax.New(`$repl$`) if err != nil { dbg.Fatal("new part: %s", err) } p.SetEnv(map[string]interface{}{"repl": tRepl}) return p }
func testCanvas() *wax.Part { p, err := wax.New("$tc$") if err != nil { dbg.Fatal("new part: %s", err) } p.SetEnv(map[string]interface{}{"tc": tCanvas}) return p }
// Define a new flag with the given name and usage. // valuep must be a pointer to the argument type and will be set to // the command line flag value if the flag is found. // Known types are bool, int, Counter, Octal, Hexa, int64, uint64, string, // float64, time.Duration, time.Time, and []string. // []string is a string option that may be repeated. // The time formats understood are // "01/02" // "01/02/06" // "01/02/2006" // "2006/0102" // "15:04:05" // "15:04" // "3pm" // "3:04pm" // "01/02 15:04" // "01/02/06 15:04" // "01/02/2006 15:04" // "2006/0102 15:04 " // // If the name is "+..." or "-..." and vp is *int, then it is understood as // a request to accept +number or -number as an argument. // // The help string should just describe the flag for flags with no // argument, and should be something like "dir: do this with dir" // if the flag accepts a "dir" argument. This convention is used to generate // a good usage diagnostic. func (f *Flags) NewFlag(name, help string, vp interface{}) { if vp == nil { dbg.Fatal("flag %s: nil value", name) } if len(name) == 0 { dbg.Fatal("empty flag name") } if f.defs[name] != nil { dbg.Fatal("flag %s redefined", name) } aname := "" if i := strings.Index(help, ":"); i > 0 { aname = help[:i] } switch vp.(type) { case *bool: case *int: if aname == "" { aname = "num" } if name[0] == '+' { if f.plus != nil { dbg.Fatal("flag +number redefined") } f.plus = &def{name: name, help: help, valp: vp, argname: aname} return } if name[0] == '-' { if f.minus != nil { dbg.Fatal("flag -number redefined") } f.minus = &def{name: name, help: help, valp: vp, argname: aname} return } case *Counter: case *Octal, *Hexa, *int64, *uint64, *float64: if aname == "" { aname = "num" } case *string, *[]string: if aname == "" { aname = "str" } case *time.Duration: if aname == "" { aname = "ival" } case *time.Time: if aname == "" { aname = "time" } default: dbg.Fatal("flag %s: unknown flag type", name) } if name[0]=='+' || name[0]=='-' { dbg.Fatal("name '±...' is only for *int") } f.defs[name] = &def{name: name, help: help, valp: vp, argname: aname} }
func ExampleNewDir() { fi, err := os.Stat("/a/file") if err != nil { dbg.Fatal(err) } d := NewDir(fi, 0) printf("%s\n", d) // could print `path"/a/file", name:"file" type:"d" mode:"0755" size:"3" mtime:"5000000000"` }
func ExampleNew() { // create a tree fs, err := New("example mfs") if err != nil { dbg.Fatal("lfs: %s", err) } dbg.Warn("fs %s ready", fs) // Now use it... }
func ExampleLfs_Get() { // let's use a tree rooted at / in RO mode fs, err := New("example lfs", "/", RO) if err != nil { dbg.Fatal("lfs: %s", err) } // Now do a "cat" of /etc/hosts dc := fs.Get("/etc/hosts", 0, zx.All, "") // if had an early error, it's reported by the close of dc // and we won't receive any data. for data := range dc { os.Stdout.Write(data) } if cerror(dc) != nil { dbg.Fatal("get: %s", cerror(dc)) } }
func ExampleNew() { // create a tree rooted at /bin in RO mode fs, err := New("example lfs", "/bin", RO) if err != nil { dbg.Fatal("lfs: %s", err) } dbg.Warn("fs %s ready", fs) // Now use it... }
func ExampleLfs_Stat() { var fs *Lfs // = New("tag", path, RO|RW) dirc := fs.Stat("/ls") dir := <-dirc if dir == nil { dbg.Fatal("stat: %s", cerror(dirc)) } dbg.Warn("stat was %s", dir) }
func TestPart(t *testing.T) { r := repl{ Debug: true, Trees: []*tree{ { Name: "t1<p ?''", Path: "p1", Peers: []string{"t2", "t4"}, }, { Name: "t2", Path: "p2", Peers: []string{"t2"}, }, { Name: "t3", }, }, } vars1 := map[string]interface{}{ "t": r.Trees[1], } p1, err := New(tpg) if err != nil { dbg.Fatal("new part: %s", err) } p1.SetEnv(vars1) var buf1 bytes.Buffer if err := p1.apply(&buf1); err != nil { t.Fatalf("apply part: %s", err) } printf("p1: {%s}\n", buf1.String()) if buf1.String() != p1out { t.Fatalf("wrong p1 output") } u := ui{"another ui", p1} vars := map[string]interface{}{ "debug": &r.Debug, "port": 3333, "repl": r, "p1": p1, "u": u, } var buf2 bytes.Buffer if err := applyNew(&buf2, pg, vars); err != nil { t.Fatalf("new part: %s", err) } printf("p2: {%s}\n", buf2.String()) if buf2.String() != p2out { fmt.Printf("wrong? p2 output: was [%s]", buf2.String()) } }
func (l *lex) unget() { if l.eofmet { if !Interactive { l.eofmet = false } return } if err := l.in[0].UnreadRune(); err != nil { dbg.Fatal("lex: bug: unreadrune: %s", err) } l.val = l.val[0 : len(l.val)-1] }
func cfgPath(nm string) string { if _, err := os.Stat(nm); err == nil { return nm } if strings.ContainsRune(nm, '/') { return nm } if nm == "." || nm == ".." { dbg.Fatal("Can't use . or .. as the cfg name") } return fmt.Sprintf("%s/lib/%s", dbg.Home, nm) }
func (t *Flags) add(name string, vp interface{}, ro bool) { if t.usr == nil { t.usr = make(map[string]interface{}) t.ro = make(map[string]bool) } if vp == nil { dbg.Fatal("flag %s: nil value", name) } switch t := vp.(type) { case *bool: case *int: case *string: case func(...string)error: default: dbg.Fatal("unknown flag type %T", t) } if t.usr == nil { t.usr = make(map[string]interface{}) } t.usr[name] = vp t.ro[name] = ro }
func (nd *Nd) xCmds() error { xprintf("x %s\n", nd) if err := nd.redirs(); err != nil { xprintf("x %s done\n", nd) nd.closeAll() nd.waitc <- err return err } go func() { var err error for _, c := range nd.Child { if nd.interrupted() { err = errors.New("interrupted") break } switch c.Kind { case Nnone, Nnop: continue case Npipe: c.mkExec(nd.Stdin, nd.Stdout, nd.Stderr, nd.args...) c.extraFds(nd) c.xPipe() err = nil if nd.async() { bg.Add(c) go func() { err := c.wait() bg.Del(c, err) }() } else { err = c.wait() } setsts(err) case Nset: c.mkExec(nd.Stdin, nd.Stdout, nd.Stderr, nd.args...) c.extraFds(nd) c.xSet() err = c.wait() setsts(err) default: dbg.Fatal("xcmds: child bug") } } xprintf("x %s done\n", nd) nd.closeAll() nd.waitc <- err }() return nil }
func main() { os.Args[0] = "wax" flag.Usage = usage flag.BoolVar(&test, "t", false, "create some test parts") flag.BoolVar(&wax.Verbose, "v", false, "verbose") flag.StringVar(&port, "p", "9191", "port") flag.Parse() wax.Verbose = true ctl.Debug = true wax.ServeLogin("/", "/index") index.ServeAt("/index", testParts()) if err := wax.Serve(":" + port); err != nil { dbg.Fatal("serve: %s", err) } }
func ExampleRfs() { xfs, err := Import("tcp!whatever!rfs") if err != nil { dbg.Fatal("import: %s", err) } fs := xfs.(*Rfs) // perhaps enable IO stats fs.IOstats = &zx.IOstats{} defer func() { fs.IOstats.Averages() fmt.Printf("iostats:\n%s\n", fs.IOstats) }() // use it, eg. to do a stat dc := fs.Stat("/a/file") d := <-dc if d == nil { dbg.Fatal("stat: %s", cerror(dc)) } dbg.Warn("got dir %s", dc) // stop rfs when done. fs.Close(nil) }
func (nd *Nd) mkExec(i io.Reader, o, e io.Writer, args ...string) { intrlk.Lock() nd.NdExec = &NdExec{ NdIO: NdIO{i, o, e}, waitc: make(chan error, 1), intrc: intrc, } intrlk.Unlock() if (nd.Kind==Npipe || nd.Kind==Npipeblk) && len(nd.Args)>0 && len(nd.Args[0])>0 { fd, err := os.Open(os.DevNull) if err != nil { dbg.Fatal("can't open /dev/null: %s", err) } nd.Stdin = fd nd.closefds = append(nd.closefds, fd) } nd.args = args }
func testTb() *wax.Part { tbpg := ` <p> Single entry<br> $entry$ <p> A tool bar:<br> $tb$ ` p, err := wax.New(tbpg) if err != nil { dbg.Fatal("new part: %s", err) } tenv := map[string]interface{}{ "entry": tEntry, "tb": tTb, } p.SetEnv(tenv) return p }
func (nd *Nd) xIf() error { xprintf("x %s\n", nd) if len(nd.Child)<2 || len(nd.Child)%2!=0 { dbg.Fatal("if bug") } if err := nd.redirs(); err != nil { xprintf("x %s done\n", nd) nd.closeAll() nd.waitc <- err return err } go func() { var err error for i := 0; i < len(nd.Child)-1; i += 2 { if nd.interrupted() { err = errors.New("interrupted") break } cond, body := nd.Child[i], nd.Child[i+1] if cond != nil { cond.mkExec(nd.Stdin, nd.Stdout, nd.Stderr, nd.args...) cond.extraFds(nd) err = cond.xPipe() if err == nil { err = cond.wait() } if err != nil { continue } } body.mkExec(nd.Stdin, nd.Stdout, nd.Stderr, nd.args...) body.extraFds(nd) err = body.xCmds() if err == nil { err = body.wait() } break } nd.closeAll() nd.waitc <- err }() return nil }
func (nd *Nd) xFor() error { xprintf("x %s\n", nd) if len(nd.Child) != 2 { dbg.Fatal("for bug") } if err := nd.redirs(); err != nil { xprintf("x %s done\n", nd) nd.closeAll() nd.waitc <- err return err } go func() { iter, body := nd.Child[0], nd.Child[1] nd.Child = iter.Child args := nd.names() nd.Child = []*Nd{iter, body} if len(args) < 2 { xprintf("x %s done\n", nd) nd.closeAll() nd.waitc <- nil return } vname := args[0] var err error for args = args[1:]; len(args) > 0; args = args[1:] { if nd.interrupted() { err = errors.New("interrupted") break } body.mkExec(nd.Stdin, nd.Stdout, nd.Stderr, nd.args...) body.extraFds(nd) os.Setenv(vname, args[0]) err = body.xCmds() if err == nil { err = body.wait() } } nd.closeAll() xprintf("x %s done\n", nd) nd.waitc <- err }() return nil }