|  |  |  | @ -4,6 +4,7 @@ package wikilink | 
		
	
		
			
				|  |  |  |  | import ( | 
		
	
		
			
				|  |  |  |  | 	"fmt" | 
		
	
		
			
				|  |  |  |  | 	"strings" | 
		
	
		
			
				|  |  |  |  | 	"sync" | 
		
	
		
			
				|  |  |  |  | 	// "unicode"
 | 
		
	
		
			
				|  |  |  |  | 	"unicode/utf8" | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
	
		
			
				
					|  |  |  | @ -67,19 +68,20 @@ func (l *Lexer) NextItem() Item { | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | func (l *Lexer) ignore() { | 
		
	
		
			
				|  |  |  |  | 	l.start = l.pos | 
		
	
		
			
				|  |  |  |  | 	l.SetStart(l.pos) | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | func (l *Lexer) backup() { | 
		
	
		
			
				|  |  |  |  | 	l.pos -= l.width | 
		
	
		
			
				|  |  |  |  | 	l.SetPos(l.GetPos() - l.GetWidth()) | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | type Lexer struct { | 
		
	
		
			
				|  |  |  |  | 	L                 *zap.SugaredLogger | 
		
	
		
			
				|  |  |  |  | 	name, input       string | 
		
	
		
			
				|  |  |  |  | 	start, pos, width int | 
		
	
		
			
				|  |  |  |  | 	state             stateFn | 
		
	
		
			
				|  |  |  |  | 	items             chan Item | 
		
	
		
			
				|  |  |  |  | 	L                                           *zap.SugaredLogger | 
		
	
		
			
				|  |  |  |  | 	name, input                                 string | 
		
	
		
			
				|  |  |  |  | 	start, pos, width                           int | 
		
	
		
			
				|  |  |  |  | 	state                                       stateFn | 
		
	
		
			
				|  |  |  |  | 	items                                       chan Item | 
		
	
		
			
				|  |  |  |  | 	widthMutex, startMutex, posMutex, chanMutex sync.Mutex | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | func (l *Lexer) peek() rune { | 
		
	
	
		
			
				
					|  |  |  | @ -106,17 +108,19 @@ func (l *Lexer) acceptRun(valid string) { | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | func (l *Lexer) emit(t ItemType) { | 
		
	
		
			
				|  |  |  |  | 	i := Item{t, l.input[l.start:l.pos]} | 
		
	
		
			
				|  |  |  |  | 	defer l.chanMutex.Unlock() | 
		
	
		
			
				|  |  |  |  | 	l.chanMutex.Lock() | 
		
	
		
			
				|  |  |  |  | 	i := Item{t, l.input[l.GetStart():l.GetPos()]} | 
		
	
		
			
				|  |  |  |  | 	L := l.L.With( | 
		
	
		
			
				|  |  |  |  | 		zap.Int("pos", l.pos), | 
		
	
		
			
				|  |  |  |  | 		zap.Int("width", l.width), | 
		
	
		
			
				|  |  |  |  | 		zap.Int("pos", l.GetPos()), | 
		
	
		
			
				|  |  |  |  | 		zap.Int("width", l.GetWidth()), | 
		
	
		
			
				|  |  |  |  | 	).Named("emit") | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 	L.Debugw("emitting item", | 
		
	
		
			
				|  |  |  |  | 		zap.String("item", i.String()), | 
		
	
		
			
				|  |  |  |  | 	) | 
		
	
		
			
				|  |  |  |  | 	l.items <- i | 
		
	
		
			
				|  |  |  |  | 	l.start = l.pos | 
		
	
		
			
				|  |  |  |  | 	l.SetStart(l.GetPos()) | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | func (l *Lexer) errorf(format string, args ...interface{}) stateFn { | 
		
	
	
		
			
				
					|  |  |  | @ -135,12 +139,13 @@ func (l *Lexer) errorf(format string, args ...interface{}) stateFn { | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | func (l *Lexer) next() rune { | 
		
	
		
			
				|  |  |  |  | 	var r rune | 
		
	
		
			
				|  |  |  |  | 	if l.pos >= len(l.input) { | 
		
	
		
			
				|  |  |  |  | 		l.width = 0 | 
		
	
		
			
				|  |  |  |  | 	if l.GetPos() >= len(l.input) { | 
		
	
		
			
				|  |  |  |  | 		l.SetWidth(0) | 
		
	
		
			
				|  |  |  |  | 		return EOF | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  | 	r, l.width = utf8.DecodeRuneInString(l.input[l.pos:]) | 
		
	
		
			
				|  |  |  |  | 	l.pos += l.width | 
		
	
		
			
				|  |  |  |  | 	r, width := utf8.DecodeRuneInString(l.input[l.GetPos():]) | 
		
	
		
			
				|  |  |  |  | 	l.SetWidth(width) | 
		
	
		
			
				|  |  |  |  | 	l.SetPos(l.GetPos() + l.GetWidth()) | 
		
	
		
			
				|  |  |  |  | 	return r | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
	
		
			
				
					|  |  |  | @ -148,9 +153,46 @@ func (l *Lexer) run() { | 
		
	
		
			
				|  |  |  |  | 	for state := lexText; state != nil; { | 
		
	
		
			
				|  |  |  |  | 		state = state(l) | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  | 	l.chanMutex.Lock() | 
		
	
		
			
				|  |  |  |  | 	close(l.items) | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | func (l *Lexer) GetPos() int { | 
		
	
		
			
				|  |  |  |  | 	defer l.posMutex.Unlock() | 
		
	
		
			
				|  |  |  |  | 	l.posMutex.Lock() | 
		
	
		
			
				|  |  |  |  | 	return l.pos | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | func (l *Lexer) SetPos(pos int) { | 
		
	
		
			
				|  |  |  |  | 	defer l.posMutex.Unlock() | 
		
	
		
			
				|  |  |  |  | 	l.posMutex.Lock() | 
		
	
		
			
				|  |  |  |  | 	l.pos = pos | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | func (l *Lexer) GetWidth() int { | 
		
	
		
			
				|  |  |  |  | 	defer l.widthMutex.Unlock() | 
		
	
		
			
				|  |  |  |  | 	l.widthMutex.Lock() | 
		
	
		
			
				|  |  |  |  | 	return l.width | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | func (l *Lexer) SetWidth(width int) { | 
		
	
		
			
				|  |  |  |  | 	defer l.widthMutex.Unlock() | 
		
	
		
			
				|  |  |  |  | 	l.widthMutex.Lock() | 
		
	
		
			
				|  |  |  |  | 	l.width = width | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | func (l *Lexer) GetStart() int { | 
		
	
		
			
				|  |  |  |  | 	defer l.startMutex.Unlock() | 
		
	
		
			
				|  |  |  |  | 	l.startMutex.Lock() | 
		
	
		
			
				|  |  |  |  | 	return l.start | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | func (l *Lexer) SetStart(start int) { | 
		
	
		
			
				|  |  |  |  | 	defer l.startMutex.Unlock() | 
		
	
		
			
				|  |  |  |  | 	l.startMutex.Lock() | 
		
	
		
			
				|  |  |  |  | 	l.start = start | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | type stateFn func(*Lexer) stateFn | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | type ItemType int | 
		
	
	
		
			
				
					|  |  |  | 
 |