github.com/jmigpin/editor@v1.6.0/util/drawutil/drawer4/syntaxhighlight.go (about)

     1  package drawer4
     2  
     3  import (
     4  	"github.com/jmigpin/editor/util/drawutil"
     5  	"github.com/jmigpin/editor/util/iout/iorw"
     6  	"github.com/jmigpin/editor/util/parseutil"
     7  )
     8  
     9  func updateSyntaxHighlightOps(d *Drawer) {
    10  	if !d.Opt.SyntaxHighlight.On {
    11  		d.Opt.SyntaxHighlight.Group.Ops = nil
    12  		return
    13  	}
    14  
    15  	if d.opt.syntaxH.updated {
    16  		return
    17  	}
    18  	d.opt.syntaxH.updated = true
    19  
    20  	pad := 2500
    21  	sh := &SyntaxHighlight{d: d}
    22  	d.Opt.SyntaxHighlight.Group.Ops = sh.do(pad)
    23  }
    24  
    25  //----------
    26  
    27  type SyntaxHighlight struct {
    28  	d   *Drawer
    29  	sc  *parseutil.ScannerR
    30  	ops []*ColorizeOp
    31  }
    32  
    33  func (sh *SyntaxHighlight) do(pad int) []*ColorizeOp {
    34  	// limit reading to be able to handle big content
    35  	o, n, _, _ := sh.d.visibleLen()
    36  	min, max := o, o+n
    37  
    38  	r := iorw.NewLimitedReaderAtPad(sh.d.reader, min, max, pad)
    39  
    40  	sh.sc = parseutil.NewScannerR(r, min)
    41  
    42  	for !sh.sc.M.Eof() {
    43  		sh.normal(pad)
    44  	}
    45  	return sh.ops
    46  }
    47  func (sh *SyntaxHighlight) normal(pad int) {
    48  	pos0 := sh.sc.Pos()
    49  	opt := &sh.d.Opt.SyntaxHighlight
    50  	switch {
    51  	case sh.comments():
    52  		// ok
    53  	case sh.sc.M.StringSection("\"", '\\', true, pad, false) == nil ||
    54  		sh.sc.M.StringSection("'", '\\', true, 4, false) == nil:
    55  
    56  		// unable to support multiline quotes (Ex: Go backquotes) since the whole file is not parsed, just a section.
    57  		// Also, in the case of Go backquotes, probably only .go files should support them.
    58  
    59  		op1 := &ColorizeOp{
    60  			Offset: pos0,
    61  			Fg:     opt.String.Fg,
    62  			Bg:     opt.String.Bg,
    63  		}
    64  		op2 := &ColorizeOp{Offset: sh.sc.Pos()}
    65  		sh.ops = append(sh.ops, op1, op2)
    66  	default:
    67  		_, _ = sh.sc.ReadRune()
    68  	}
    69  }
    70  
    71  func (sh *SyntaxHighlight) comments() bool {
    72  	opt := &sh.d.Opt.SyntaxHighlight
    73  	for _, c := range opt.Comment.Defs {
    74  		if sh.comment(c) {
    75  			return true
    76  		}
    77  	}
    78  	return false
    79  }
    80  func (sh *SyntaxHighlight) comment(c *drawutil.SyntaxHighlightComment) bool {
    81  	pos0 := sh.sc.Pos()
    82  
    83  	// must match sequence start (line or multiline)
    84  	if err := sh.sc.M.Sequence(c.S); err != nil {
    85  		return false
    86  	}
    87  
    88  	opt := &sh.d.Opt.SyntaxHighlight
    89  	fg := opt.Comment.Fg
    90  	bg := opt.Comment.Bg
    91  
    92  	// single line comment
    93  	if c.IsLine {
    94  		op1 := &ColorizeOp{Offset: pos0, Fg: fg, Bg: bg}
    95  		_ = sh.sc.M.ToNLExcludeOrEnd('\\')
    96  		op2 := &ColorizeOp{Offset: sh.sc.Pos()}
    97  		sh.ops = append(sh.ops, op1, op2)
    98  		return true
    99  	}
   100  
   101  	// multiline comment
   102  	// start
   103  	op := &ColorizeOp{Offset: pos0, Fg: fg, Bg: bg}
   104  	sh.ops = append(sh.ops, op)
   105  	// loop until it finds ending sequence
   106  	for !sh.sc.M.Eof() {
   107  		if err := sh.sc.M.Sequence(c.E); err == nil {
   108  			// end
   109  			op = &ColorizeOp{Offset: sh.sc.Pos()}
   110  			sh.ops = append(sh.ops, op)
   111  			break
   112  		}
   113  		_, _ = sh.sc.ReadRune()
   114  	}
   115  	return true
   116  }