Anonymous avatar Anonymous committed 8d664fb

1.0

Comments (0)

Files changed (1)

+// 2010 - Mathieu Lonjaret. BSD-style licence.
+
 package main
 
 import (
 	"fmt"
 	"strings"
 	"sort"
+	"flag"
 
 	"goplan9.googlecode.com/hg/plan9/acme"
 )
 	var root string
 	var w *acme.Win
 	var INDENT string = "	"
+	var PLAN9 = os.Getenv("PLAN9")
+	
+func usage() {
+    fmt.Fprintf(os.Stderr, "usage: xplor [path] \n")
+    flag.PrintDefaults()
+    os.Exit(2)
+}
 
-//TODO: send error messages to error win, not to xplor win.	 
+//TODO: send error messages to +Errors instead of Stderr?
+ 
 func main() {
+	flag.Usage = usage
+    flag.Parse()
+    
+	args := flag.Args()
 
+	switch len(args) {
+    case 0:
+        root, _ = os.Getwd()
+    case 1:
+ 		root = args[0]
+    default:
+        usage()
+    }
+    	
 	initWindow()
 	
+	w.Write("+Errors", []byte("Hello world"))
+	
 	for word := range events() {
 		go onLook(word) 
 	}
 	var err os.Error
 	w, err = acme.New()
 	if err != nil {
-		print(err.String());
+		fmt.Fprintf(os.Stderr, err.String())
 		return 
 	}
 
-	root, _ = os.Getwd()
-	title := path.Join("/Xplor/",root)
+	title := "xplor-" + root
 	w.Name(title)
 
 	printDirContents(root, 0)
-	
-	//add an extra line to deal with out of range addresses for now
-	w.Write("body", []byte("\n"))
-	
 }
 
 func printDirContents(path string, depth int) {
 	currentDir, err := os.Open(path, os.O_RDONLY, 0644)
 	if err != nil {
-		w.Write("body", []byte(err.String()))
+		fmt.Fprintf(os.Stderr, err.String())
 		return 
 	}
 	names, err := currentDir.Readdirnames(-1)
 	if err != nil {
-		w.Write("body", []byte(err.String()))
+		fmt.Fprintf(os.Stderr, err.String())
 		return 
 	}
 	currentDir.Close();
 	for _, v := range names {	
 		w.Write("data", []byte(indents + v + "\n"))
 	}
+	
+	//lame trick for now to dodge the out of range issue, until my address-foo gets better
+	if depth == 0 {
+		w.Write("body", []byte("\n"))
+		w.Write("body", []byte("\n"))
+	}
 }
 
-//TODO: func isUnfolded
-
 func readLine(addr string) ([]byte, os.Error) {
-//TODO: do better about the buf of 512?
 	const NBUF = 512	
 	var b []byte = make([]byte, NBUF)
 	var err os.Error = nil
-	fmt.Fprint(os.Stdout, "readLine addr: " + addr + "\n")
-//	w.Write("body", []byte("readLine addr: " + addr + "\n"))
 	err = w.Addr("%s", addr)
 	if err != nil {
 		return b, err
 	return depth, trimedline
 }
 
+func isFolded(charaddr string) (bool, os.Error) {
+	var err os.Error = nil
+	var b []byte
+	addr := "#" + charaddr + "+1-"
+	b, err = readLine(addr)
+	if err != nil {
+		return true, err
+	}
+	depth, _ := getDepth(b)
+	addr = "#" + charaddr + "+-"
+	b, err = readLine(addr)
+	if err != nil {
+		return true, err
+	}	
+	nextdepth, _ := getDepth(b)
+	return (nextdepth <= depth), err 
+}
+
 func getParents(charaddr string, depth int, prevline int) string {
 	var addr string
 	if depth == 0 {
 	} else {
 		addr = "#" + charaddr + "-" + fmt.Sprint(prevline - 1)
 	}
-	for ;; {
+	for {
 		b, err := readLine(addr)
 		if err != nil {
 			w.Write("body", []byte(err.String()))
 			return ""
 		}
 		newdepth, line := getDepth(b)
-		fmt.Fprint(os.Stdout, fmt.Sprint(newdepth) + ", " + line + "\n")
 		if newdepth < depth {
 			fullpath := path.Join(getParents(charaddr, newdepth, prevline), "/", line)
-			fmt.Fprint(os.Stdout, fullpath + "\n")
 			return fullpath
 		}
 		prevline++
 	return ""
 }
 
-func onLook(word string) {
-	addr := "#" + word + "+1-"
+func onLook(charaddr string) {
+	// reconstruct full path and check if file or dir
+	addr := "#" + charaddr + "+1-"
 	b, err := readLine(addr)
 	if err != nil {
-		w.Write("body", []byte(err.String()))
+		fmt.Fprintf(os.Stderr, err.String())
 		return
 	}
 	depth, line := getDepth(b)
-	fmt.Fprint(os.Stdout, fmt.Sprint(depth) + ", " + line + "\n")
-	fullpath := path.Join(root, "/", getParents(word, depth, 1), "/", line)
+	fullpath := path.Join(root, "/", getParents(charaddr, depth, 1), "/", line)
 	fi, err := os.Lstat(fullpath)
 	if err != nil {
-		w.Write("body", []byte(err.String()))
+		fmt.Fprintf(os.Stderr, err.String())
 		return
 	}
+	
 	if !fi.IsDirectory() {
-//TODO: send back a Look event?
-		fmt.Fprint(os.Stdout, "Not a dir \n")
+		// send that file to B (ie open it)
+		if len(PLAN9) == 0 {
+			fmt.Fprintf(os.Stderr, "$PLAN9 not defined \n")
+			return
+		}
+		var args2 []string = make([]string, 2)
+		args2[0] = path.Join(PLAN9 + "/bin/B")
+		args2[1] = fullpath
+	    fds := []*os.File{os.Stdout, os.Stdout, os.Stderr}
+		os.ForkExec(args2[0], args2, os.Environ(), "", fds)
 		return
 	}
-	addr = "#" + word + "+2-1-#0"
-	fmt.Fprint(os.Stdout, "onLook addr: " + addr + "\n")
-	err = w.Addr("%s", addr)
+	
+	folded, err := isFolded(charaddr)
 	if err != nil {
-		w.Write("body", []byte(err.String() + addr))
-		return
-	}	
-	printDirContents(fullpath, depth + 1)
+		fmt.Fprint(os.Stderr, err.String())
+		return	
+	}
+	if folded {
+		// print dir contents
+		addr = "#" + charaddr + "+2-1-#0"
+		err = w.Addr("%s", addr)
+		if err != nil {
+			fmt.Fprintf(os.Stderr, err.String() + addr)
+			return
+		}	
+		printDirContents(fullpath, depth + 1)
+	} else {
+		// unfold, ie delete lines below dir until we hit a dir of the same depth
+		addr = "#" + charaddr + "+-"
+		nextdepth := depth + 1
+		nextline := 1
+		for nextdepth > depth {
+			err = w.Addr("%s", addr)
+			if err != nil {
+				fmt.Fprint(os.Stderr, err.String())
+				return
+			}
+			b, err = readLine(addr)
+			if err != nil {
+				fmt.Fprint(os.Stderr, err.String())
+				return
+			}
+			nextdepth, _ = getDepth(b)
+			nextline++;
+			addr = "#" + charaddr + "+" + fmt.Sprint(nextline-1)
+		}
+		nextline--
+		addr = "#" + charaddr + "+-#0,#" + charaddr + "+" + fmt.Sprint(nextline-2)
+		err = w.Addr("%s", addr)
+			if err != nil {
+				fmt.Fprint(os.Stderr, err.String())
+				return
+			}
+		w.Write("data", []byte(""))
+	}
 }
 
 func events() <-chan string {
 				w.WriteEvent(e)
 			case 'L':	// look
 				w.Ctl("clean")
-			/*
-				msg := fmt.Sprint(e.Q0) + "," + fmt.Sprint(e.Q1) + "," + fmt.Sprint(e.OrigQ0) + "," + fmt.Sprint(e.OrigQ1)
-				w.Write("body", []byte(msg))
-				continue
-			*/
-				//disallow expansions to avoid weird addresses for now
+				//ignore expansions
 				if e.OrigQ0 != e.OrigQ1 {
 					continue
 				}
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.