| 146 | } |
| 147 | |
| 148 | func readExpr() <-chan expr { |
| 149 | ch := make(chan expr) |
| 150 | |
| 151 | go func() { |
| 152 | duration := 100 * time.Millisecond |
| 153 | |
| 154 | c, err := net.Dial("unix", gSocketPath) |
| 155 | for err != nil { |
| 156 | log.Printf("connecting server: %s", err) |
| 157 | time.Sleep(duration) |
| 158 | duration *= 2 |
| 159 | c, err = net.Dial("unix", gSocketPath) |
| 160 | } |
| 161 | |
| 162 | if _, err := fmt.Fprintf(c, "conn %d\n", gClientID); err != nil { |
| 163 | log.Printf("registering with server: %s", err) |
| 164 | return |
| 165 | } |
| 166 | |
| 167 | ch <- &callExpr{"sync", nil, 1} |
| 168 | ch <- &callExpr{"on-init", nil, 1} |
| 169 | |
| 170 | s := bufio.NewScanner(c) |
| 171 | for s.Scan() { |
| 172 | log.Printf("recv: %s", s.Text()) |
| 173 | |
| 174 | // `query` has to be handled outside of the main thread, which is |
| 175 | // blocked when running a synchronous shell command ("$" or "!"). |
| 176 | // This is important since `query` is often the result of the user |
| 177 | // running `$lf -remote "query $id <something>"`. |
| 178 | if word, rest := splitWord(s.Text()); word == "query" { |
| 179 | gState.mutex.Lock() |
| 180 | state := gState.data[rest] |
| 181 | gState.mutex.Unlock() |
| 182 | if _, err := fmt.Fprintln(c, state); err != nil { |
| 183 | log.Printf("sending response to server: %s", err) |
| 184 | return |
| 185 | } |
| 186 | } else { |
| 187 | p := newParser(strings.NewReader(s.Text())) |
| 188 | if p.parse() { |
| 189 | ch <- p.expr |
| 190 | } |
| 191 | } |
| 192 | } |
| 193 | |
| 194 | if err := s.Err(); err != nil { |
| 195 | log.Printf("reading from server: %s", err) |
| 196 | } |
| 197 | |
| 198 | c.Close() |
| 199 | }() |
| 200 | |
| 201 | return ch |
| 202 | } |
| 203 | |
| 204 | func remote(req string) (string, error) { |
| 205 | c, err := net.Dial("unix", gSocketPath) |