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  }