github.com/aretext/aretext@v1.3.0/display/palette.go (about)

     1  package display
     2  
     3  import (
     4  	"log"
     5  
     6  	"github.com/gdamore/tcell/v2"
     7  
     8  	"github.com/aretext/aretext/config"
     9  	"github.com/aretext/aretext/state"
    10  	"github.com/aretext/aretext/syntax/parser"
    11  )
    12  
    13  // Palette controls the style of displayed text.
    14  type Palette struct {
    15  	lineNumStyle              tcell.Style
    16  	selectionStyle            tcell.Style
    17  	searchMatchStyle          tcell.Style
    18  	searchCursorStyle         tcell.Style
    19  	statusMsgSuccessStyle     tcell.Style
    20  	statusMsgErrorStyle       tcell.Style
    21  	statusInputModeStyle      tcell.Style
    22  	statusInputBufferStyle    tcell.Style
    23  	statusRecordingMacroStyle tcell.Style
    24  	statusFilePathStyle       tcell.Style
    25  	menuBorderStyle           tcell.Style
    26  	menuIconStyle             tcell.Style
    27  	menuPromptStyle           tcell.Style
    28  	menuQueryStyle            tcell.Style
    29  	menuCursorStyle           tcell.Style
    30  	menuItemSelectedStyle     tcell.Style
    31  	menuItemUnselectedStyle   tcell.Style
    32  	textFieldPromptStyle      tcell.Style
    33  	textFieldInputTextStyle   tcell.Style
    34  	textFieldBorderStyle      tcell.Style
    35  	searchPrefixStyle         tcell.Style
    36  	searchQueryStyle          tcell.Style
    37  	tokenRoleStyle            map[parser.TokenRole]tcell.Style
    38  }
    39  
    40  func NewPalette() *Palette {
    41  	s := tcell.StyleDefault
    42  	return &Palette{
    43  		lineNumStyle:              s.Foreground(tcell.ColorOlive),
    44  		selectionStyle:            s.Reverse(true).Dim(true),
    45  		searchMatchStyle:          s.Reverse(true),
    46  		searchCursorStyle:         s.Reverse(true).Dim(true),
    47  		statusMsgSuccessStyle:     s.Foreground(tcell.ColorGreen).Bold(true),
    48  		statusMsgErrorStyle:       s.Background(tcell.ColorMaroon).Foreground(tcell.ColorWhite).Bold(true),
    49  		statusInputModeStyle:      s.Bold(true),
    50  		statusInputBufferStyle:    s.Bold(true),
    51  		statusRecordingMacroStyle: s.Bold(true),
    52  		statusFilePathStyle:       s.Bold(true),
    53  		menuBorderStyle:           s.Dim(true),
    54  		menuIconStyle:             s,
    55  		menuPromptStyle:           s.Dim(true),
    56  		menuQueryStyle:            s,
    57  		menuCursorStyle:           s.Bold(true),
    58  		menuItemSelectedStyle:     s.Underline(true),
    59  		menuItemUnselectedStyle:   s,
    60  		textFieldPromptStyle:      s.Dim(true),
    61  		textFieldInputTextStyle:   s,
    62  		textFieldBorderStyle:      s,
    63  		searchPrefixStyle:         s,
    64  		searchQueryStyle:          s,
    65  		tokenRoleStyle: map[parser.TokenRole]tcell.Style{
    66  			parser.TokenRoleOperator: s.Foreground(tcell.ColorPurple),
    67  			parser.TokenRoleKeyword:  s.Foreground(tcell.ColorOlive),
    68  			parser.TokenRoleNumber:   s.Foreground(tcell.ColorGreen),
    69  			parser.TokenRoleString:   s.Foreground(tcell.ColorMaroon),
    70  			parser.TokenRoleComment:  s.Foreground(tcell.ColorNavy),
    71  			parser.TokenRoleCustom1:  s.Foreground(tcell.ColorTeal),
    72  			parser.TokenRoleCustom2:  s.Foreground(tcell.ColorDarkBlue),
    73  			parser.TokenRoleCustom3:  s.Foreground(tcell.ColorRed),
    74  			parser.TokenRoleCustom4:  s.Foreground(tcell.ColorLime),
    75  			parser.TokenRoleCustom5:  s.Foreground(tcell.ColorFuchsia),
    76  			parser.TokenRoleCustom6:  s.Foreground(tcell.ColorAqua),
    77  			parser.TokenRoleCustom7:  s.Foreground(tcell.ColorDarkGreen),
    78  			parser.TokenRoleCustom8:  s.Foreground(tcell.ColorDarkCyan),
    79  			parser.TokenRoleCustom9:  s.Foreground(tcell.ColorTeal),
    80  			parser.TokenRoleCustom10: s.Foreground(tcell.ColorDarkBlue),
    81  			parser.TokenRoleCustom11: s.Foreground(tcell.ColorRed),
    82  			parser.TokenRoleCustom12: s.Foreground(tcell.ColorLime),
    83  			parser.TokenRoleCustom13: s.Foreground(tcell.ColorFuchsia),
    84  			parser.TokenRoleCustom14: s.Foreground(tcell.ColorAqua),
    85  			parser.TokenRoleCustom15: s.Foreground(tcell.ColorDarkGreen),
    86  			parser.TokenRoleCustom16: s.Foreground(tcell.ColorDarkCyan),
    87  		},
    88  	}
    89  }
    90  
    91  func NewPaletteFromConfigStyles(styles map[string]config.StyleConfig) *Palette {
    92  	p := NewPalette()
    93  	for k, v := range styles {
    94  		s := styleFromConfig(v)
    95  		switch k {
    96  		case config.StyleLineNum:
    97  			p.lineNumStyle = s
    98  		case config.StyleTokenOperator:
    99  			p.tokenRoleStyle[parser.TokenRoleOperator] = s
   100  		case config.StyleTokenKeyword:
   101  			p.tokenRoleStyle[parser.TokenRoleKeyword] = s
   102  		case config.StyleTokenNumber:
   103  			p.tokenRoleStyle[parser.TokenRoleNumber] = s
   104  		case config.StyleTokenString:
   105  			p.tokenRoleStyle[parser.TokenRoleString] = s
   106  		case config.StyleTokenComment:
   107  			p.tokenRoleStyle[parser.TokenRoleComment] = s
   108  		case config.StyleTokenCustom1:
   109  			p.tokenRoleStyle[parser.TokenRoleCustom1] = s
   110  		case config.StyleTokenCustom2:
   111  			p.tokenRoleStyle[parser.TokenRoleCustom2] = s
   112  		case config.StyleTokenCustom3:
   113  			p.tokenRoleStyle[parser.TokenRoleCustom3] = s
   114  		case config.StyleTokenCustom4:
   115  			p.tokenRoleStyle[parser.TokenRoleCustom4] = s
   116  		case config.StyleTokenCustom5:
   117  			p.tokenRoleStyle[parser.TokenRoleCustom5] = s
   118  		case config.StyleTokenCustom6:
   119  			p.tokenRoleStyle[parser.TokenRoleCustom6] = s
   120  		case config.StyleTokenCustom7:
   121  			p.tokenRoleStyle[parser.TokenRoleCustom7] = s
   122  		case config.StyleTokenCustom8:
   123  			p.tokenRoleStyle[parser.TokenRoleCustom8] = s
   124  		case config.StyleTokenCustom9:
   125  			p.tokenRoleStyle[parser.TokenRoleCustom9] = s
   126  		case config.StyleTokenCustom10:
   127  			p.tokenRoleStyle[parser.TokenRoleCustom10] = s
   128  		case config.StyleTokenCustom11:
   129  			p.tokenRoleStyle[parser.TokenRoleCustom11] = s
   130  		case config.StyleTokenCustom12:
   131  			p.tokenRoleStyle[parser.TokenRoleCustom12] = s
   132  		case config.StyleTokenCustom13:
   133  			p.tokenRoleStyle[parser.TokenRoleCustom13] = s
   134  		case config.StyleTokenCustom14:
   135  			p.tokenRoleStyle[parser.TokenRoleCustom14] = s
   136  		case config.StyleTokenCustom15:
   137  			p.tokenRoleStyle[parser.TokenRoleCustom15] = s
   138  		case config.StyleTokenCustom16:
   139  			p.tokenRoleStyle[parser.TokenRoleCustom16] = s
   140  		default:
   141  			log.Printf("Unrecognized style key: %s\n", k)
   142  		}
   143  	}
   144  	return p
   145  }
   146  
   147  func (p *Palette) StyleForLineNum() tcell.Style {
   148  	return p.lineNumStyle
   149  }
   150  
   151  func (p *Palette) StyleForSelection() tcell.Style {
   152  	return p.selectionStyle
   153  }
   154  
   155  func (p *Palette) StyleForSearchMatch() tcell.Style {
   156  	return p.searchMatchStyle
   157  }
   158  
   159  func (p *Palette) StyleForSearchCursor() tcell.Style {
   160  	return p.searchCursorStyle
   161  }
   162  
   163  func (p *Palette) StyleForStatusInputMode() tcell.Style {
   164  	return p.statusInputModeStyle
   165  }
   166  
   167  func (p *Palette) StyleForStatusInputBuffer() tcell.Style {
   168  	return p.statusInputBufferStyle
   169  }
   170  
   171  func (p *Palette) StyleForStatusRecordingMacro() tcell.Style {
   172  	return p.statusRecordingMacroStyle
   173  }
   174  
   175  func (p *Palette) StyleForStatusFilePath() tcell.Style {
   176  	return p.statusFilePathStyle
   177  }
   178  
   179  func (p *Palette) StyleForStatusMsg(statusMsgStyle state.StatusMsgStyle) tcell.Style {
   180  	switch statusMsgStyle {
   181  	case state.StatusMsgStyleSuccess:
   182  		return p.statusMsgSuccessStyle
   183  	case state.StatusMsgStyleError:
   184  		return p.statusMsgErrorStyle
   185  	default:
   186  		return tcell.StyleDefault
   187  	}
   188  }
   189  
   190  func (p *Palette) StyleForMenuBorder() tcell.Style {
   191  	return p.menuBorderStyle
   192  }
   193  
   194  func (p *Palette) StyleForMenuIcon() tcell.Style {
   195  	return p.menuIconStyle
   196  }
   197  
   198  func (p *Palette) StyleForMenuPrompt() tcell.Style {
   199  	return p.menuPromptStyle
   200  }
   201  
   202  func (p *Palette) StyleForMenuQuery() tcell.Style {
   203  	return p.menuQueryStyle
   204  }
   205  
   206  func (p *Palette) StyleForMenuCursor() tcell.Style {
   207  	return p.menuCursorStyle
   208  }
   209  
   210  func (p *Palette) StyleForMenuItem(selected bool) tcell.Style {
   211  	if selected {
   212  		return p.menuItemSelectedStyle
   213  	} else {
   214  		return p.menuItemUnselectedStyle
   215  	}
   216  }
   217  
   218  func (p *Palette) StyleForTextFieldPrompt() tcell.Style {
   219  	return p.textFieldPromptStyle
   220  }
   221  
   222  func (p *Palette) StyleForTextFieldInputText() tcell.Style {
   223  	return p.textFieldInputTextStyle
   224  }
   225  
   226  func (p *Palette) StyleForTextFieldBorder() tcell.Style {
   227  	return p.textFieldBorderStyle
   228  }
   229  
   230  func (p *Palette) StyleForSearchPrefix() tcell.Style {
   231  	return p.searchPrefixStyle
   232  }
   233  
   234  func (p *Palette) StyleForSearchQuery() tcell.Style {
   235  	return p.searchQueryStyle
   236  }
   237  
   238  func (p *Palette) StyleForTokenRole(tokenRole parser.TokenRole) tcell.Style {
   239  	// If key is not set, returns tcell.StyleDefault (the zero value).
   240  	return p.tokenRoleStyle[tokenRole]
   241  }
   242  
   243  func styleFromConfig(s config.StyleConfig) tcell.Style {
   244  	c := tcell.GetColor(s.Color)
   245  	style := tcell.StyleDefault.Foreground(c)
   246  
   247  	if s.BackgroundColor != "" {
   248  		bg := tcell.GetColor(s.BackgroundColor)
   249  		style = style.Background(bg)
   250  	}
   251  
   252  	if s.Bold {
   253  		style = style.Bold(true)
   254  	}
   255  
   256  	if s.Italic {
   257  		style = style.Italic(true)
   258  	}
   259  
   260  	if s.Underline {
   261  		style = style.Underline(true)
   262  	}
   263  
   264  	if s.StrikeThrough {
   265  		style = style.StrikeThrough(true)
   266  	}
   267  
   268  	return style
   269  }