9fans.net/go@v0.0.7/cmd/acme/look1.go (about) 1 // #include <u.h> 2 // #include <libc.h> 3 // #include <draw.h> 4 // #include <thread.h> 5 // #include <cursor.h> 6 // #include <mouse.h> 7 // #include <keyboard.h> 8 // #include <frame.h> 9 // #include <fcall.h> 10 // #include <regexp.h> 11 // #include <9pclient.h> 12 // #include <plumb.h> 13 // #include <libsec.h> 14 // #include "dat.h" 15 // #include "fns.h" 16 17 package main 18 19 import ( 20 "bufio" 21 "fmt" 22 "time" 23 24 "9fans.net/go/cmd/acme/internal/adraw" 25 "9fans.net/go/cmd/acme/internal/alog" 26 "9fans.net/go/cmd/acme/internal/bufs" 27 "9fans.net/go/cmd/acme/internal/runes" 28 "9fans.net/go/cmd/acme/internal/ui" 29 "9fans.net/go/cmd/acme/internal/wind" 30 "9fans.net/go/plan9" 31 "9fans.net/go/plan9/client" 32 "9fans.net/go/plumb" 33 ) 34 35 var plumbeditfid *client.Fid 36 37 var nuntitled int 38 39 func plumbthread() { 40 /* 41 * Loop so that if plumber is restarted, acme need not be. 42 */ 43 for { 44 /* 45 * Connect to plumber. 46 */ 47 // TODO(rsc): plumbunmount() 48 var fid *client.Fid 49 for { 50 var err error 51 fid, err = plumb.Open("edit", plan9.OREAD|plan9.OCEXEC) 52 if err == nil { 53 break 54 } 55 time.Sleep(2 * time.Second) 56 } 57 big.Lock() // TODO still racy 58 plumbeditfid = fid 59 ui.Plumbsendfid, _ = plumb.Open("send", plan9.OWRITE|plan9.OCEXEC) 60 big.Unlock() 61 62 /* 63 * Relay messages. 64 */ 65 bedit := bufio.NewReader(fid) 66 for { 67 m := new(plumb.Message) 68 err := m.Recv(bedit) 69 if err != nil { 70 break 71 } 72 cplumb <- m 73 } 74 75 /* 76 * Lost connection. 77 */ 78 big.Lock() // TODO still racy 79 fid = ui.Plumbsendfid 80 ui.Plumbsendfid = nil 81 big.Unlock() 82 fid.Close() 83 84 big.Lock() // TODO still racy 85 fid = plumbeditfid 86 plumbeditfid = nil 87 big.Unlock() 88 fid.Close() 89 } 90 } 91 92 func startplumbing() { 93 go plumbthread() 94 } 95 96 func plumbgetc(a interface{}, n int) rune { 97 r := a.([]rune) 98 if n > len(r) { 99 return 0 100 } 101 return r[n] 102 } 103 104 func plumblook(m *plumb.Message) { 105 if len(m.Data) >= bufs.Len { 106 alog.Printf("insanely long file name (%d bytes) in plumb message (%.32s...)\n", len(m.Data), m.Data) 107 return 108 } 109 var e ui.Expand 110 e.Q0 = 0 111 e.Q1 = 0 112 if len(m.Data) == 0 { 113 return 114 } 115 e.Arg = nil 116 e.Bname = string(m.Data) 117 e.Name = []rune(e.Bname) 118 e.Jump = true 119 e.A0 = 0 120 e.A1 = 0 121 addr := m.LookupAttr("addr") 122 if addr != "" { 123 r := []rune(addr) 124 e.A1 = len(r) 125 e.Arg = r 126 e.Agetc = plumbgetc 127 } 128 adraw.Display.Top() 129 ui.Openfile(nil, &e) 130 } 131 132 func plumbshow(m *plumb.Message) { 133 adraw.Display.Top() 134 w := ui.Makenewwindow(nil) 135 ui.Winmousebut(w) 136 name := m.LookupAttr("filename") 137 if name == "" { 138 nuntitled++ 139 name = fmt.Sprintf("Untitled-%d", nuntitled) 140 } 141 if name[0] != '/' && m.Dir != "" { 142 name = fmt.Sprintf("%s/%s", m.Dir, name) 143 } 144 var rb [256]rune 145 _, nr, _ := runes.Convert([]byte(name), rb[:], true) 146 rs := runes.CleanPath(rb[:nr]) 147 wind.Winsetname(w, rs) 148 r := make([]rune, len(m.Data)) 149 _, nr, _ = runes.Convert(m.Data, r, true) 150 wind.Textinsert(&w.Body, 0, r[:nr], true) 151 w.Body.File.SetMod(false) 152 w.Dirty = false 153 wind.Winsettag(w) 154 wind.Textscrdraw(&w.Body) 155 wind.Textsetselect(&w.Tag, w.Tag.Len(), w.Tag.Len()) 156 ui.OnNewWindow(w) 157 }