From a2b296d73e7e11fbaee014797e7f21648e45d9bc Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Thu, 30 May 2024 10:11:19 +0530 Subject: [PATCH] Setting of index features now basically works --- kittens/choose_fonts/face.go | 34 +++++-- kittens/choose_fonts/index_feature.go | 129 ++++++++++++++++++++++++++ kittens/choose_fonts/ui.go | 3 +- 3 files changed, 159 insertions(+), 7 deletions(-) create mode 100644 kittens/choose_fonts/index_feature.go diff --git a/kittens/choose_fonts/face.go b/kittens/choose_fonts/face.go index 6dbc97042..3854e633b 100644 --- a/kittens/choose_fonts/face.go +++ b/kittens/choose_fonts/face.go @@ -150,7 +150,11 @@ func (self *face_panel) draw_font_features(_ loop.ScreenSize, start_y int, previ formatted = append(formatted, tui.InternalHyperlink(text, "feature:"+feat_tag)) } utils.SortWithKey(formatted, func(a string) string { - return strings.ToLower(wcswidth.StripEscapeCodes(a)) + ans := strings.ToLower(wcswidth.StripEscapeCodes(a)) + if ans[0] == '-' || ans[0] == '+' { + ans = ans[1:] + } + return ans }) line := lp.SprintStyled(control_name_style, `Features`) + ": " + strings.Join(formatted, ", ") y = self.render_lines(start_y, ``, line) @@ -315,15 +319,34 @@ func (self *face_panel) remove_feature_in_setting(tag string) error { return nil } +func (self *face_panel) change_feature_value(tag string, val uint, remove bool) error { + if remove { + return self.remove_feature_in_setting(tag) + } + pff := ParsedFontFeature{tag: tag, val: val} + return self.update_feature_in_setting(pff) +} + func (self *face_panel) handle_click_on_feature(feat_tag string) error { d := self.current_preview.Features[feat_tag] if d.Is_index { + var current_val uint + for q, serialized := range self.current_preview.Applied_features { + if q == feat_tag && serialized != "" { + if _, num, found := strings.Cut(serialized, "="); found { + if v, err := strconv.ParseUint(num, 10, 0); err == nil { + current_val = uint(v) + } + } else { + current_val = utils.IfElse(serialized[0] == '-', uint(0), uint(1)) + } + return self.handler.if_pane.on_enter(self.family, self.which, self.settings, feat_tag, d, current_val) + } + } + return self.handler.if_pane.on_enter(self.family, self.which, self.settings, feat_tag, d, current_val) } else { for q, serialized := range self.current_preview.Applied_features { - if q == feat_tag { - if serialized == "" { - continue - } + if q == feat_tag && serialized != "" { if serialized[0] == '-' { return self.remove_feature_in_setting(feat_tag) } @@ -332,7 +355,6 @@ func (self *face_panel) handle_click_on_feature(feat_tag string) error { } return self.update_feature_in_setting(ParsedFontFeature{tag: feat_tag, is_bool: true, val: 1}) } - return nil } func (self *face_panel) on_click(id string) (err error) { diff --git a/kittens/choose_fonts/index_feature.go b/kittens/choose_fonts/index_feature.go new file mode 100644 index 000000000..fa30f112e --- /dev/null +++ b/kittens/choose_fonts/index_feature.go @@ -0,0 +1,129 @@ +package choose_fonts + +import ( + "fmt" + "strconv" + "strings" + + "kitty/tools/tui/loop" + "kitty/tools/tui/readline" + "kitty/tools/utils" +) + +var _ = fmt.Print + +type if_panel struct { + handler *handler + rl *readline.Readline + + family, which, feat_tag string + settings faces_settings + feature_data FeatureData + current_val uint +} + +func (self *if_panel) render_lines(start_y int, lines ...string) (y int) { + sz, _ := self.handler.lp.ScreenSize() + _, y, str := self.handler.render_lines.InRectangle(lines, 0, start_y, int(sz.WidthCells), int(sz.HeightCells)-y, &self.handler.mouse_state, self.on_click) + self.handler.lp.QueueWriteString(str) + return +} + +func (self *if_panel) draw_screen() (err error) { + lp := self.handler.lp + feat_name := utils.IfElse(self.feature_data.Name == "", self.feat_tag, self.feature_data.Name) + lp.QueueWriteString(self.handler.format_title("Edit "+feat_name, 0)) + lines := []string{ + fmt.Sprintf("Enter a value for the '%s' feature of the %s font. Values are non-negative integers. Leaving it blank will cause the feature value to be not set, i.e. take its default value.", feat_name, self.family), + } + if self.feature_data.Tooltip != "" { + lines = append(lines, "") + lines = append(lines, self.feature_data.Tooltip) + } + if len(self.feature_data.Params) > 0 { + lines = append(lines, "") + lines = append(lines, "You can also click on any of the feature names below to choose the corresponding value.") + } else { + lines = append(lines, "") + lines = append(lines, "Consult the documentation for this font to find out what values are valid for this feature.") + } + lines = append(lines, "") + cursor_y := self.render_lines(2, lines...) + lp.MoveCursorTo(1, cursor_y+1) + lp.ClearToEndOfLine() + self.rl.RedrawNonAtomic() + lp.SetCursorVisible(true) + return +} + +func (self *if_panel) initialize(h *handler) (err error) { + self.handler = h + self.rl = readline.New(h.lp, readline.RlInit{DontMarkPrompts: true, Prompt: "Value: "}) + return +} + +func (self *if_panel) on_wakeup() error { + return self.handler.draw_screen() +} + +func (self *if_panel) on_click(id string) (err error) { + return +} + +func (self *if_panel) on_key_event(event *loop.KeyEvent) (err error) { + if event.MatchesPressOrRepeat("esc") { + event.Handled = true + self.handler.current_pane = &self.handler.face_pane + return self.handler.draw_screen() + } + if event.MatchesPressOrRepeat("enter") { + event.Handled = true + text := strings.TrimSpace(self.rl.AllText()) + remove := false + var val uint64 + if text == "" { + remove = true + } else { + val, err = strconv.ParseUint(text, 10, 0) + } + if err != nil { + self.rl.ResetText() + self.handler.lp.Beep() + } else { + if err = self.handler.face_pane.change_feature_value(self.feat_tag, uint(val), remove); err != nil { + return err + } + self.handler.current_pane = &self.handler.face_pane + } + return self.handler.draw_screen() + } + if err = self.rl.OnKeyEvent(event); err != nil { + if err == readline.ErrAcceptInput { + return nil + } + return err + } + return self.draw_screen() +} + +func (self *if_panel) on_text(text string, from_key_event bool, in_bracketed_paste bool) (err error) { + if err = self.rl.OnText(text, from_key_event, in_bracketed_paste); err != nil { + return err + } + return self.draw_screen() +} + +func (self *if_panel) on_enter(family, which string, settings faces_settings, feat_tag string, fd FeatureData, current_val uint) error { + self.family = family + self.feat_tag = feat_tag + self.settings = settings + self.which = which + self.handler.current_pane = self + self.feature_data = fd + self.current_val = current_val + self.rl.ResetText() + if self.current_val > 0 { + self.rl.SetText(strconv.Itoa(int(self.current_val))) + } + return self.handler.draw_screen() +} diff --git a/kittens/choose_fonts/ui.go b/kittens/choose_fonts/ui.go index 4cc6a36e6..1523d8c3e 100644 --- a/kittens/choose_fonts/ui.go +++ b/kittens/choose_fonts/ui.go @@ -55,6 +55,7 @@ type handler struct { listing FontList faces faces face_pane face_panel + if_pane if_panel final_pane final_pane panes []pane @@ -78,7 +79,7 @@ func (h *handler) initialize() (err error) { h.lp.SetCursorVisible(false) h.lp.OnQueryResponse = h.on_query_response h.lp.QueryTerminal("font_size", "dpi_x", "dpi_y", "foreground", "background") - h.panes = []pane{&h.listing, &h.faces, &h.face_pane, &h.final_pane} + h.panes = []pane{&h.listing, &h.faces, &h.face_pane, &h.if_pane, &h.final_pane} for _, pane := range h.panes { if err = pane.initialize(h); err != nil { return err