added ctrl-l keybind for arbitrary species+calltype labels

quietlight
May 19, 2026, 10:19 PM
GUCJEGHSHOTGO333BQSUX44S5YIVIVEPMLLFIRFXD4KD6APBMOYQC

Dependencies

  • [2] 4L2IWSLS moved TUI-adjacent code from calls_classify.go to dedicated files within the same package
  • [3] YVFPP5VJ refactor of tui/ first iteration

Change contents

  • edit in tui/view.go at line 39
    [3.692]
    [3.692]
    // Label dialog (when active)
    if m.labelMode {
    m.renderLabelDialog(&b)
    return tea.NewView(b.String())
    }
  • edit in tui/view.go at line 121
    [3.3038]
    [3.3038]
    }
    // renderLabelDialog renders the label input dialog
    func (m Model) renderLabelDialog(b *strings.Builder) {
    before := m.labelText[:m.labelCursor]
    after := m.labelText[m.labelCursor:]
    inputLine := before + "█" + after
    charCount := fmt.Sprintf("%d/%d", len(m.labelText), maxLabelLength)
    content := fmt.Sprintf("Label (Species+CallType):\n%s\n%s\n%s", inputLine, charCount, labelHelpText)
    b.WriteString(commentBoxStyle.Render(content))
  • edit in tui/update.go at line 45
    [3.4802]
    [3.4802]
    }
    if m.labelMode {
    return m.handleLabelKey(msg)
  • edit in tui/update.go at line 122
    [3.6660]
    [3.6660]
    if msg.String() == "ctrl+l" {
    m.labelText = m.state.GetCurrentSpeciesCallType()
    m.labelCursor = len(m.labelText)
    m.labelMode = true
    return true, m, nil
    }
  • edit in tui/update.go at line 353
    [3.12044]
    [3.12044]
    }
    // handleLabelKey handles key presses in label mode
    func (m Model) handleLabelKey(msg tea.KeyPressMsg) (tea.Model, tea.Cmd) {
    key := msg.Key()
    // Enter: save label
    if key.Code == tea.KeyEnter {
    return m.handleLabelEnter()
    }
    // Escape: cancel
    if key.Code == tea.KeyEscape || key.Code == tea.KeyEsc {
    m.labelMode = false
    return m, nil
    }
    // Navigation and editing keys
    if handled := m.handleLabelKeyCode(key); handled {
    return m, nil
    }
    // Ctrl combos
    if handled := m.handleLabelCtrl(msg.String()); handled {
    return m, nil
    }
    // Printable ASCII character (space handled via KeySpace below)
    s := msg.String()
    if len(s) == 1 && s[0] >= 33 && s[0] <= 126 {
    if len(m.labelText) < maxLabelLength {
    m.labelText = m.labelText[:m.labelCursor] + s + m.labelText[m.labelCursor:]
    m.labelCursor++
    }
    }
    return m, nil
  • edit in tui/update.go at line 390
    [3.12046]
    [3.12046]
    // handleLabelEnter handles Enter key in label mode.
    func (m Model) handleLabelEnter() (tea.Model, tea.Cmd) {
    m.labelMode = false
    if m.labelText == "" {
    return m, nil
    }
  • edit in tui/update.go at line 398
    [3.12047]
    [3.12047]
    species, callType := datafile.ParseSpeciesCallType(m.labelText)
    if species == "" {
    return m, nil
    }
    m.stopPlayer()
    m.state.ApplyBinding(&calls.BindingResult{Species: species, CallType: callType})
    if err := m.state.Save(); err != nil {
    m.err = err.Error()
    }
    return m.advanceOrQuit()
    }
    // handleLabelKeyCode handles navigation and editing keys in label mode.
    // Returns true if the key was consumed.
    func (m *Model) handleLabelKeyCode(key tea.Key) bool {
    switch key.Code {
    case tea.KeyLeft:
    if m.labelCursor > 0 {
    m.labelCursor--
    }
    return true
    case tea.KeyRight:
    if m.labelCursor < len(m.labelText) {
    m.labelCursor++
    }
    return true
    case tea.KeySpace:
    if len(m.labelText) < maxLabelLength {
    m.labelText = m.labelText[:m.labelCursor] + " " + m.labelText[m.labelCursor:]
    m.labelCursor++
    }
    return true
    case tea.KeyBackspace:
    if m.labelCursor > 0 {
    m.labelText = m.labelText[:m.labelCursor-1] + m.labelText[m.labelCursor:]
    m.labelCursor--
    }
    return true
    case tea.KeyDelete:
    if m.labelCursor < len(m.labelText) {
    m.labelText = m.labelText[:m.labelCursor] + m.labelText[m.labelCursor+1:]
    }
    return true
    }
    return false
    }
    // handleLabelCtrl handles ctrl-key combos in label mode.
    // Returns true if the key was consumed.
    func (m *Model) handleLabelCtrl(s string) bool {
    switch s {
    case "ctrl+u":
    m.labelText = ""
    m.labelCursor = 0
    return true
    case "ctrl+a":
    m.labelCursor = 0
    return true
    case "ctrl+e":
    m.labelCursor = len(m.labelText)
    return true
    }
    return false
    }
  • edit in tui/model.go at line 56
    [3.17451]
    [3.17451]
    // Label dialog state
    labelMode bool // true when label dialog is open
    labelText string // current input text
    labelCursor int // cursor position in label text
  • replacement in tui/keymap.go at line 4
    [3.20646][3.20646:20815]()
    const keyHelpText = "[esc]quit [,]prev [.]next [0]confirm [space]comment [ctrl+s]clip [ctrl+d]bookmark [ctrl+,]prev-bk [ctrl+.]next-bk [enter]play [shift+enter]½speed"
    [3.20646]
    [3.20815]
    const keyHelpText = "[esc]quit [,]prev [.]next [0]confirm [space]comment [ctrl+l]label [ctrl+s]clip [ctrl+d]bookmark [ctrl+,]prev-bk [ctrl+.]next-bk [enter]play [shift+enter]½speed"
  • replacement in tui/keymap.go at line 12
    [3.21029][3.21029:21053]()
    // Comment text limits.
    [3.21029]
    [3.21053]
    // Label dialog help text.
    const labelHelpText = "[enter]save [esc]cancel [←→]move [ctrl+u]clear [ctrl+a]start [ctrl+e]end"
    // Input text limits.
  • edit in tui/keymap.go at line 19
    [3.21114]
    [3.21114]
    maxLabelLength = 64
  • edit in tools/calls/classify_labels.go at line 58
    [2.1268]
    [2.1268]
    }
    // GetCurrentSpeciesCallType returns the species+calltype string for the current
    // segment's first filter label, using the Species+CallType format.
    // Returns "" if no matching label exists.
    func (s *ClassifyState) GetCurrentSpeciesCallType() string {
    seg := s.CurrentSegment()
    if seg == nil {
    return ""
    }
    filterLabels := seg.GetFilterLabels(s.Config.Filter)
    if len(filterLabels) == 0 {
    return ""
    }
    l := filterLabels[0]
    if l.CallType != "" {
    return l.Species + "+" + l.CallType
    }
    return l.Species