...

Source file src/github.com/c-bata/go-prompt/output_vt100.go

Documentation: github.com/c-bata/go-prompt

     1  package prompt
     2  
     3  import (
     4  	"bytes"
     5  	"strconv"
     6  )
     7  
     8  // VT100Writer generates VT100 escape sequences.
     9  type VT100Writer struct {
    10  	buffer []byte
    11  }
    12  
    13  // WriteRaw to write raw byte array
    14  func (w *VT100Writer) WriteRaw(data []byte) {
    15  	w.buffer = append(w.buffer, data...)
    16  }
    17  
    18  // Write to write safety byte array by removing control sequences.
    19  func (w *VT100Writer) Write(data []byte) {
    20  	w.WriteRaw(bytes.Replace(data, []byte{0x1b}, []byte{'?'}, -1))
    21  }
    22  
    23  // WriteRawStr to write raw string
    24  func (w *VT100Writer) WriteRawStr(data string) {
    25  	w.WriteRaw([]byte(data))
    26  }
    27  
    28  // WriteStr to write safety string by removing control sequences.
    29  func (w *VT100Writer) WriteStr(data string) {
    30  	w.Write([]byte(data))
    31  }
    32  
    33  /* Erase */
    34  
    35  // EraseScreen erases the screen with the background colour and moves the cursor to home.
    36  func (w *VT100Writer) EraseScreen() {
    37  	w.WriteRaw([]byte{0x1b, '[', '2', 'J'})
    38  }
    39  
    40  // EraseUp erases the screen from the current line up to the top of the screen.
    41  func (w *VT100Writer) EraseUp() {
    42  	w.WriteRaw([]byte{0x1b, '[', '1', 'J'})
    43  }
    44  
    45  // EraseDown erases the screen from the current line down to the bottom of the screen.
    46  func (w *VT100Writer) EraseDown() {
    47  	w.WriteRaw([]byte{0x1b, '[', 'J'})
    48  }
    49  
    50  // EraseStartOfLine erases from the current cursor position to the start of the current line.
    51  func (w *VT100Writer) EraseStartOfLine() {
    52  	w.WriteRaw([]byte{0x1b, '[', '1', 'K'})
    53  }
    54  
    55  // EraseEndOfLine erases from the current cursor position to the end of the current line.
    56  func (w *VT100Writer) EraseEndOfLine() {
    57  	w.WriteRaw([]byte{0x1b, '[', 'K'})
    58  }
    59  
    60  // EraseLine erases the entire current line.
    61  func (w *VT100Writer) EraseLine() {
    62  	w.WriteRaw([]byte{0x1b, '[', '2', 'K'})
    63  }
    64  
    65  /* Cursor */
    66  
    67  // ShowCursor stops blinking cursor and show.
    68  func (w *VT100Writer) ShowCursor() {
    69  	w.WriteRaw([]byte{0x1b, '[', '?', '1', '2', 'l', 0x1b, '[', '?', '2', '5', 'h'})
    70  }
    71  
    72  // HideCursor hides cursor.
    73  func (w *VT100Writer) HideCursor() {
    74  	w.WriteRaw([]byte{0x1b, '[', '?', '2', '5', 'l'})
    75  }
    76  
    77  // CursorGoTo sets the cursor position where subsequent text will begin.
    78  func (w *VT100Writer) CursorGoTo(row, col int) {
    79  	if row == 0 && col == 0 {
    80  		// If no row/column parameters are provided (ie. <ESC>[H), the cursor will move to the home position.
    81  		w.WriteRaw([]byte{0x1b, '[', 'H'})
    82  		return
    83  	}
    84  	r := strconv.Itoa(row)
    85  	c := strconv.Itoa(col)
    86  	w.WriteRaw([]byte{0x1b, '['})
    87  	w.WriteRaw([]byte(r))
    88  	w.WriteRaw([]byte{';'})
    89  	w.WriteRaw([]byte(c))
    90  	w.WriteRaw([]byte{'H'})
    91  }
    92  
    93  // CursorUp moves the cursor up by 'n' rows; the default count is 1.
    94  func (w *VT100Writer) CursorUp(n int) {
    95  	if n == 0 {
    96  		return
    97  	} else if n < 0 {
    98  		w.CursorDown(-n)
    99  		return
   100  	}
   101  	s := strconv.Itoa(n)
   102  	w.WriteRaw([]byte{0x1b, '['})
   103  	w.WriteRaw([]byte(s))
   104  	w.WriteRaw([]byte{'A'})
   105  }
   106  
   107  // CursorDown moves the cursor down by 'n' rows; the default count is 1.
   108  func (w *VT100Writer) CursorDown(n int) {
   109  	if n == 0 {
   110  		return
   111  	} else if n < 0 {
   112  		w.CursorUp(-n)
   113  		return
   114  	}
   115  	s := strconv.Itoa(n)
   116  	w.WriteRaw([]byte{0x1b, '['})
   117  	w.WriteRaw([]byte(s))
   118  	w.WriteRaw([]byte{'B'})
   119  }
   120  
   121  // CursorForward moves the cursor forward by 'n' columns; the default count is 1.
   122  func (w *VT100Writer) CursorForward(n int) {
   123  	if n == 0 {
   124  		return
   125  	} else if n < 0 {
   126  		w.CursorBackward(-n)
   127  		return
   128  	}
   129  	s := strconv.Itoa(n)
   130  	w.WriteRaw([]byte{0x1b, '['})
   131  	w.WriteRaw([]byte(s))
   132  	w.WriteRaw([]byte{'C'})
   133  }
   134  
   135  // CursorBackward moves the cursor backward by 'n' columns; the default count is 1.
   136  func (w *VT100Writer) CursorBackward(n int) {
   137  	if n == 0 {
   138  		return
   139  	} else if n < 0 {
   140  		w.CursorForward(-n)
   141  		return
   142  	}
   143  	s := strconv.Itoa(n)
   144  	w.WriteRaw([]byte{0x1b, '['})
   145  	w.WriteRaw([]byte(s))
   146  	w.WriteRaw([]byte{'D'})
   147  }
   148  
   149  // AskForCPR asks for a cursor position report (CPR).
   150  func (w *VT100Writer) AskForCPR() {
   151  	// CPR: Cursor Position Request.
   152  	w.WriteRaw([]byte{0x1b, '[', '6', 'n'})
   153  }
   154  
   155  // SaveCursor saves current cursor position.
   156  func (w *VT100Writer) SaveCursor() {
   157  	w.WriteRaw([]byte{0x1b, '[', 's'})
   158  }
   159  
   160  // UnSaveCursor restores cursor position after a Save Cursor.
   161  func (w *VT100Writer) UnSaveCursor() {
   162  	w.WriteRaw([]byte{0x1b, '[', 'u'})
   163  }
   164  
   165  /* Scrolling */
   166  
   167  // ScrollDown scrolls display down one line.
   168  func (w *VT100Writer) ScrollDown() {
   169  	w.WriteRaw([]byte{0x1b, 'D'})
   170  }
   171  
   172  // ScrollUp scroll display up one line.
   173  func (w *VT100Writer) ScrollUp() {
   174  	w.WriteRaw([]byte{0x1b, 'M'})
   175  }
   176  
   177  /* Title */
   178  
   179  // SetTitle sets a title of terminal window.
   180  func (w *VT100Writer) SetTitle(title string) {
   181  	titleBytes := []byte(title)
   182  	patterns := []struct {
   183  		from []byte
   184  		to   []byte
   185  	}{
   186  		{
   187  			from: []byte{0x13},
   188  			to:   []byte{},
   189  		},
   190  		{
   191  			from: []byte{0x07},
   192  			to:   []byte{},
   193  		},
   194  	}
   195  	for i := range patterns {
   196  		titleBytes = bytes.Replace(titleBytes, patterns[i].from, patterns[i].to, -1)
   197  	}
   198  
   199  	w.WriteRaw([]byte{0x1b, ']', '2', ';'})
   200  	w.WriteRaw(titleBytes)
   201  	w.WriteRaw([]byte{0x07})
   202  }
   203  
   204  // ClearTitle clears a title of terminal window.
   205  func (w *VT100Writer) ClearTitle() {
   206  	w.WriteRaw([]byte{0x1b, ']', '2', ';', 0x07})
   207  }
   208  
   209  /* Font */
   210  
   211  // SetColor sets text and background colors. and specify whether text is bold.
   212  func (w *VT100Writer) SetColor(fg, bg Color, bold bool) {
   213  	if bold {
   214  		w.SetDisplayAttributes(fg, bg, DisplayBold)
   215  	} else {
   216  		// If using `DisplayDefualt`, it will be broken in some environment.
   217  		// Details are https://github.com/c-bata/go-prompt/pull/85
   218  		w.SetDisplayAttributes(fg, bg, DisplayReset)
   219  	}
   220  }
   221  
   222  // SetDisplayAttributes to set VT100 display attributes.
   223  func (w *VT100Writer) SetDisplayAttributes(fg, bg Color, attrs ...DisplayAttribute) {
   224  	w.WriteRaw([]byte{0x1b, '['}) // control sequence introducer
   225  	defer w.WriteRaw([]byte{'m'}) // final character
   226  
   227  	var separator byte = ';'
   228  	for i := range attrs {
   229  		p, ok := displayAttributeParameters[attrs[i]]
   230  		if !ok {
   231  			continue
   232  		}
   233  		w.WriteRaw(p)
   234  		w.WriteRaw([]byte{separator})
   235  	}
   236  
   237  	f, ok := foregroundANSIColors[fg]
   238  	if !ok {
   239  		f = foregroundANSIColors[DefaultColor]
   240  	}
   241  	w.WriteRaw(f)
   242  	w.WriteRaw([]byte{separator})
   243  	b, ok := backgroundANSIColors[bg]
   244  	if !ok {
   245  		b = backgroundANSIColors[DefaultColor]
   246  	}
   247  	w.WriteRaw(b)
   248  }
   249  
   250  var displayAttributeParameters = map[DisplayAttribute][]byte{
   251  	DisplayReset:        {'0'},
   252  	DisplayBold:         {'1'},
   253  	DisplayLowIntensity: {'2'},
   254  	DisplayItalic:       {'3'},
   255  	DisplayUnderline:    {'4'},
   256  	DisplayBlink:        {'5'},
   257  	DisplayRapidBlink:   {'6'},
   258  	DisplayReverse:      {'7'},
   259  	DisplayInvisible:    {'8'},
   260  	DisplayCrossedOut:   {'9'},
   261  	DisplayDefaultFont:  {'1', '0'},
   262  }
   263  
   264  var foregroundANSIColors = map[Color][]byte{
   265  	DefaultColor: {'3', '9'},
   266  
   267  	// Low intensity.
   268  	Black:     {'3', '0'},
   269  	DarkRed:   {'3', '1'},
   270  	DarkGreen: {'3', '2'},
   271  	Brown:     {'3', '3'},
   272  	DarkBlue:  {'3', '4'},
   273  	Purple:    {'3', '5'},
   274  	Cyan:      {'3', '6'},
   275  	LightGray: {'3', '7'},
   276  
   277  	// High intensity.
   278  	DarkGray:  {'9', '0'},
   279  	Red:       {'9', '1'},
   280  	Green:     {'9', '2'},
   281  	Yellow:    {'9', '3'},
   282  	Blue:      {'9', '4'},
   283  	Fuchsia:   {'9', '5'},
   284  	Turquoise: {'9', '6'},
   285  	White:     {'9', '7'},
   286  }
   287  
   288  var backgroundANSIColors = map[Color][]byte{
   289  	DefaultColor: {'4', '9'},
   290  
   291  	// Low intensity.
   292  	Black:     {'4', '0'},
   293  	DarkRed:   {'4', '1'},
   294  	DarkGreen: {'4', '2'},
   295  	Brown:     {'4', '3'},
   296  	DarkBlue:  {'4', '4'},
   297  	Purple:    {'4', '5'},
   298  	Cyan:      {'4', '6'},
   299  	LightGray: {'4', '7'},
   300  
   301  	// High intensity
   302  	DarkGray:  {'1', '0', '0'},
   303  	Red:       {'1', '0', '1'},
   304  	Green:     {'1', '0', '2'},
   305  	Yellow:    {'1', '0', '3'},
   306  	Blue:      {'1', '0', '4'},
   307  	Fuchsia:   {'1', '0', '5'},
   308  	Turquoise: {'1', '0', '6'},
   309  	White:     {'1', '0', '7'},
   310  }
   311  

View as plain text