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 }