github.com/lmorg/murex@v0.0.0-20240217211045-e081c89cd4ef/utils/virtualterm/write.go (about)

     1  package virtualterm
     2  
     3  const (
     4  	charEsc           = 27
     5  	charBackspaceIso  = 8
     6  	charBackspaceAnsi = 127
     7  )
     8  
     9  func (term *Term) writeCell(r rune) {
    10  	term.cell().char = r
    11  	term.cell().sgr = term.sgr
    12  	term.wrapCursorForwards()
    13  }
    14  
    15  // Write multiple characters to the virtual terminal
    16  func (term *Term) Write(text []rune) {
    17  	var (
    18  		escape bool
    19  	)
    20  
    21  	term.mutex.Lock()
    22  
    23  	for i := 0; i < len(text); i++ {
    24  		switch text[i] {
    25  		case charBackspaceIso, charBackspaceAnsi:
    26  			panic("TODO: backspace")
    27  
    28  		case charEsc:
    29  			escape = true
    30  
    31  		case '[':
    32  			if escape {
    33  				i += parseSgr(term, text[i-1:])
    34  				continue
    35  			}
    36  			term.writeCell(text[i])
    37  
    38  		case '\r':
    39  			//if grid.LfIncCr {
    40  			//	continue
    41  			//}
    42  			term.curPos.X = 0
    43  
    44  		case '\n':
    45  			if term.state.LfIncCr {
    46  				term.curPos.X = 0
    47  			}
    48  			if term.moveCursorDownwards(1) > 0 {
    49  				term.moveContentsUp()
    50  				term.moveCursorDownwards(1)
    51  			}
    52  
    53  		default:
    54  			term.writeCell(text[i])
    55  
    56  		}
    57  	}
    58  
    59  	term.mutex.Unlock()
    60  }
    61  
    62  func parseSgr(term *Term, text []rune) int {
    63  	i := 2
    64  
    65  	var n rune
    66  
    67  	for ; i < len(text); i++ {
    68  		switch {
    69  		case text[i] >= '0' && '9' >= text[i]:
    70  			n = (n * 10) + (text[i] - 48)
    71  
    72  		case text[i] == 'm': // SGR
    73  			lookupSgr(term, n)
    74  			return i - 1
    75  
    76  		case text[i] == 'A': // moveCursorUp
    77  			term.moveCursorUpwards(int(n))
    78  			return i - 1
    79  
    80  		case text[i] == 'B': // moveCursorDown
    81  			term.moveCursorDownwards(int(n))
    82  			return i - 1
    83  
    84  		case text[i] == 'C': // moveCursorForwards
    85  			term.moveCursorForwards(int(n))
    86  			return i - 1
    87  
    88  		case text[i] == 'D': // moveCursorBackwards
    89  			term.moveCursorBackwards(int(n))
    90  			return i - 1
    91  
    92  		case text[i] == 'J': // eraseDisplay...
    93  			if n == 0 {
    94  				term.eraseDisplayAfter()
    95  			}
    96  
    97  		default:
    98  			return i - 1
    99  		}
   100  	}
   101  	return i
   102  }
   103  
   104  func lookupSgr(term *Term, n rune) {
   105  	switch n {
   106  	case 0: // reset / normal
   107  		term.sgrReset()
   108  
   109  	case 1: // bold
   110  		term.sgrEffect(sgrBold)
   111  
   112  	case 4: // underscore
   113  		term.sgrEffect(sgrUnderscore)
   114  
   115  	case 5: // blink
   116  		term.sgrEffect(sgrBlink)
   117  
   118  		//
   119  		// 4bit foreground colour:
   120  		//
   121  
   122  	case 30: // fg black
   123  		term.sgrEffect(sgrFgColour4)
   124  		term.sgr.fg.Red = sgrColour4Black
   125  
   126  	case 31: // fg red
   127  		term.sgrEffect(sgrFgColour4)
   128  		term.sgr.fg.Red = sgrColour4Red
   129  
   130  	case 32: // fg green
   131  		term.sgrEffect(sgrFgColour4)
   132  		term.sgr.fg.Red = sgrColour4Green
   133  
   134  	case 33: // fg yellow
   135  		term.sgrEffect(sgrFgColour4)
   136  		term.sgr.fg.Red = sgrColour4Yellow
   137  
   138  	case 34: // fg blue
   139  		term.sgrEffect(sgrFgColour4)
   140  		term.sgr.fg.Red = sgrColour4Blue
   141  
   142  	case 35: // fg magenta
   143  		term.sgrEffect(sgrFgColour4)
   144  		term.sgr.fg.Red = sgrColour4Magenta
   145  
   146  	case 36: // fg cyan
   147  		term.sgrEffect(sgrFgColour4)
   148  		term.sgr.fg.Red = sgrColour4Cyan
   149  
   150  	case 37: // fg white
   151  		term.sgrEffect(sgrFgColour4)
   152  		term.sgr.fg.Red = sgrColour4White
   153  	}
   154  }