Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -706,6 +706,8 @@ func initConfig() {
}
}

oviewer.RegisterCompatAliases(viper.GetViper())

if err := viper.Unmarshal(&config); err != nil {
fmt.Fprintln(os.Stderr, err)
return
Expand Down
24 changes: 12 additions & 12 deletions ov-less.yaml
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
# This is the ov config file.
# Copy it to `$XDG_CONFIG_HOME/ov/config.yaml` or start it with `ov --config ov.yaml`.
#
# QuitSmall: false # Quit if the file size is smaller than the terminal size.
# IsWriteOriginal: false # Write the original content when exiting.
# BeforeWriteOriginal: 0 # Write the number of lines before the current location when exiting.
# AfterWriteOriginal: 0 # Write the number of lines after the current location when exiting.
# QuitIfOneScreen: false # Quit if the file size is smaller than the terminal size.
# WriteOriginal: false # Write the original content when exiting.
# WriteContextBefore: 0 # Write the number of lines before the current location when exiting.
# WriteContextAfter: 0 # Write the number of lines after the current location when exiting.
#
# CaseSensitive: false # Case sensitive search.
# SmartCaseSensitive: false # Case sensitive search if the search string contains uppercase characters.
# RegexpSearch: false # Regular expression search.
# Incsearch: true # Incremental search.
# IncrementalSearch: true # Incremental search.
#
# MemoryLimit: -1 # The maximum number of lines that can be loaded into memory.
# MemoryLimitFile: 100 # The maximum number of lines that can be loaded into memory when opening a file.
Expand Down Expand Up @@ -45,11 +45,11 @@ General:
Header: 0
AlternateRows: false
ColumnMode: false
LineNumMode: false
LineNumberMode: false
Wrap: "character" # Wrap mode. Options: "character", "word", "none".
ColumnDelimiter: ","
MarkStyleWidth: 1
# HScrollWidth: 10%
# HScrollStep: 10%
# VScrollLines: 2
Prompt:
Normal:
Expand Down Expand Up @@ -82,7 +82,7 @@ General:
Background: "darkgoldenrod"
SectionLine:
Background: "slateblue"
VerticalHeader:
RowHeader:
# Add appropriate styles here
Ruler:
Background: "#333333"
Expand All @@ -92,7 +92,7 @@ General:
# Add appropriate styles here
SectionHeaderBorder:
# Add appropriate styles here
VerticalHeaderBorder:
RowHeaderBorder:
Background: "#c0c0c0"
MultiColorHighlight:
- Foreground: "red"
Expand Down Expand Up @@ -380,19 +380,19 @@ Mode:
Header: 2
AlternateRows: true
ColumnMode: true
LineNumMode: false
LineNumberMode: false
Wrap: "character"
ColumnDelimiter: "|"
mysql:
Header: 3
AlternateRows: true
ColumnMode: true
LineNumMode: false
LineNumberMode: false
Wrap: "character"
ColumnDelimiter: "|"
ps:
Header: 1
ColumnMode: true
ColumnRainbow: true
ColumnWidth: true
ColumnFixedWidth: true
Wrap: "none"
24 changes: 12 additions & 12 deletions ov.yaml
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
# This is the ov config file.
# Copy it to `$XDG_CONFIG_HOME/ov/config.yaml` or start it with `ov --config ov.yaml`.
#
# QuitSmall: false # Quit if the file size is smaller than the terminal size.
# IsWriteOriginal: false # Write the original content when exiting.
# BeforeWriteOriginal: 0 # Write the number of lines before the current location when exiting.
# AfterWriteOriginal: 0 # Write the number of lines after the current location when exiting.
# QuitIfOneScreen: false # Quit if the file size is smaller than the terminal size.
# WriteOriginal: false # Write the original content when exiting.
# WriteContextBefore: 0 # Write the number of lines before the current location when exiting.
# WriteContextAfter: 0 # Write the number of lines after the current location when exiting.
#
# CaseSensitive: false # Case sensitive search.
# SmartCaseSensitive: false # Case sensitive search if the search string contains uppercase characters.
# RegexpSearch: false # Regular expression search.
# Incsearch: true # Incremental search.
# IncrementalSearch: true # Incremental search.
#
# MemoryLimit: -1 # The maximum number of lines that can be loaded into memory.
# MemoryLimitFile: 100 # The maximum number of lines that can be loaded into memory when opening a file.
Expand Down Expand Up @@ -45,11 +45,11 @@ General:
Header: 0
AlternateRows: false
ColumnMode: false
LineNumMode: false
LineNumberMode: false
Wrap: "character" # Wrap mode. Options: "character", "word", "none".
ColumnDelimiter: ","
MarkStyleWidth: 1
# HScrollWidth: 10%
# HScrollStep: 10%
# VScrollLines: 2
Prompt:
Normal:
Expand Down Expand Up @@ -82,7 +82,7 @@ General:
Background: "darkgoldenrod"
SectionLine:
Background: "slateblue"
VerticalHeader:
RowHeader:
# Add appropriate styles here
Ruler:
Background: "#333333"
Expand All @@ -92,7 +92,7 @@ General:
# Add appropriate styles here
SectionHeaderBorder:
# Add appropriate styles here
VerticalHeaderBorder:
RowHeaderBorder:
Background: "#c0c0c0"
MultiColorHighlight:
- Foreground: "red"
Expand Down Expand Up @@ -362,19 +362,19 @@ Mode:
Header: 2
AlternateRows: true
ColumnMode: true
LineNumMode: false
LineNumberMode: false
Wrap: "character"
ColumnDelimiter: "|"
mysql:
Header: 3
AlternateRows: true
ColumnMode: true
LineNumMode: false
LineNumberMode: false
Wrap: "character"
ColumnDelimiter: "|"
ps:
Header: 1
ColumnMode: true
ColumnRainbow: true
ColumnWidth: true
ColumnFixedWidth: true
Wrap: "none"
24 changes: 12 additions & 12 deletions ov.yaml.template
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
# This is the ov config file.
# Copy it to `$XDG_CONFIG_HOME/ov/config.yaml` or start it with `ov --config ov.yaml`.
#
# QuitSmall: false # Quit if the file size is smaller than the terminal size.
# IsWriteOriginal: false # Write the original content when exiting.
# BeforeWriteOriginal: 0 # Write the number of lines before the current location when exiting.
# AfterWriteOriginal: 0 # Write the number of lines after the current location when exiting.
# QuitIfOneScreen: false # Quit if the file size is smaller than the terminal size.
# WriteOriginal: false # Write the original content when exiting.
# WriteContextBefore: 0 # Write the number of lines before the current location when exiting.
# WriteContextAfter: 0 # Write the number of lines after the current location when exiting.
#
# CaseSensitive: false # Case sensitive search.
# SmartCaseSensitive: false # Case sensitive search if the search string contains uppercase characters.
# RegexpSearch: false # Regular expression search.
# Incsearch: true # Incremental search.
# IncrementalSearch: true # Incremental search.
#
# MemoryLimit: -1 # The maximum number of lines that can be loaded into memory.
# MemoryLimitFile: 100 # The maximum number of lines that can be loaded into memory when opening a file.
Expand Down Expand Up @@ -45,11 +45,11 @@ General:
Header: 0
AlternateRows: false
ColumnMode: false
LineNumMode: false
LineNumberMode: false
Wrap: "character" # Wrap mode. Options: "character", "word", "none".
ColumnDelimiter: ","
MarkStyleWidth: 1
# HScrollWidth: 10%
# HScrollStep: 10%
# VScrollLines: 2
Prompt:
Normal:
Expand Down Expand Up @@ -82,7 +82,7 @@ General:
Background: "darkgoldenrod"
SectionLine:
Background: "slateblue"
VerticalHeader:
RowHeader:
# Add appropriate styles here
Ruler:
Background: "#333333"
Expand All @@ -92,7 +92,7 @@ General:
# Add appropriate styles here
SectionHeaderBorder:
# Add appropriate styles here
VerticalHeaderBorder:
RowHeaderBorder:
Background: "#c0c0c0"
MultiColorHighlight:
- Foreground: "red"
Expand Down Expand Up @@ -143,19 +143,19 @@ Mode:
Header: 2
AlternateRows: true
ColumnMode: true
LineNumMode: false
LineNumberMode: false
Wrap: "character"
ColumnDelimiter: "|"
mysql:
Header: 3
AlternateRows: true
ColumnMode: true
LineNumMode: false
LineNumberMode: false
Wrap: "character"
ColumnDelimiter: "|"
ps:
Header: 1
ColumnMode: true
ColumnRainbow: true
ColumnWidth: true
ColumnFixedWidth: true
Wrap: "none"
104 changes: 104 additions & 0 deletions oviewer/compat.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
package oviewer

import (
"context"
"fmt"
"os"

"github.com/spf13/viper"
)

// compatEntry holds the mapping between an existing internal config key name
// and its new canonical name, plus display names for deprecation messages.
type compatEntry struct {
oldKey string // existing viper key (lowercase, no change)
newKey string // new canonical viper key (lowercase)
oldName string // human-readable old key for deprecation message
newName string // human-readable new key for deprecation message
}

// compatViperEntries enumerates every config key rename from the naming audit.
// oldKey is the existing internal name that stays unchanged; newKey is the new
// name being introduced. Deprecation warnings fire on oldKey; aliases are
// registered new→old so either name works in config files and env vars.
var compatViperEntries = []compatEntry{
// A2: QuitSmall → QuitIfOneScreen (matches CLI --quit-if-one-screen)
{"quitsmall", "quitifonescreen", "QuitSmall", "QuitIfOneScreen"},
// A3: LineNumMode → LineNumberMode (abbreviation → full word)
{"general.linenumode", "general.linenumbermode", "general.LineNumMode", "general.LineNumberMode"},
// A5/B6: IsWriteOnExit → WriteOnExit (drop Go Is-prefix from YAML key)
{"iswriteonexit", "writeonexit", "IsWriteOnExit", "WriteOnExit"},
// B6: IsWriteOriginal → WriteOriginal (drop Go Is-prefix from YAML key)
{"iswriteoriginal", "writeoriginal", "IsWriteOriginal", "WriteOriginal"},
// A6: BeforeWriteOriginal → WriteContextBefore (drop impl-detail "Original")
{"beforewriteoriginal", "writecontextbefore", "BeforeWriteOriginal", "WriteContextBefore"},
// A6: AfterWriteOriginal → WriteContextAfter (drop impl-detail "Original")
{"afterwriteoriginal", "writecontextafter", "AfterWriteOriginal", "WriteContextAfter"},
// B1: VerticalHeader → RowHeader (misnomer: freezes row-identifying content, not column labels)
{"general.verticalheader", "general.rowheader", "general.VerticalHeader", "general.RowHeader"},
// B1: HeaderColumn → RowHeaderColumn (paired rename with RowHeader)
{"general.headercolumn", "general.rowheadercolumn", "general.HeaderColumn", "general.RowHeaderColumn"},
// B1: Style.VerticalHeader → Style.RowHeader
{"general.style.verticalheader", "general.style.rowheader", "general.style.VerticalHeader", "general.style.RowHeader"},
// B1: Style.VerticalHeaderBorder → Style.RowHeaderBorder
{"general.style.verticalheaderborder", "general.style.rowheaderborder", "general.style.VerticalHeaderBorder", "general.style.RowHeaderBorder"},
// B4: ColumnWidth → ColumnFixedWidth (clarify it switches detection method, not column width value)
{"general.columnwidth", "general.columnfixedwidth", "general.ColumnWidth", "general.ColumnFixedWidth"},
// B5: Incsearch → IncrementalSearch (sole abbreviation among fully-spelled keys)
{"incsearch", "incrementalsearch", "Incsearch", "IncrementalSearch"},
// B8: HScrollWidth → HScrollStep (it is a step size, not a display width)
{"general.hscrollwidth", "general.hscrollstep", "general.HScrollWidth", "general.HScrollStep"},
}

// compatActionEntries maps new canonical action names to existing internal ones.
// Users may bind either name in the keybind section of their config.
var compatActionEntries = map[string]string{
// A1: alter_rows_mode → alternate_rows_mode (truncated word → full word)
"alternate_rows_mode": actionAlternate,
// A4: rainbow_mode → column_rainbow_mode (disambiguate from multi-color search highlight)
"column_rainbow_mode": actionRainbow,
// A5: write_exit → write_on_exit (match CLI --exit-write and YAML WriteOnExit)
"write_on_exit": actionWriteExit,
// A8: hide_other → hide_other_section (drop ambiguous truncation)
"hide_other_section": actionHideOther,
// B1: vertical_header → row_header (paired with config key rename)
"row_header": actionVerticalHeader,
// B1: header_column → row_header_column (paired with config key rename)
"row_header_column": actionHeaderColumn,
// D3: set_write_exit → write_exit_range (describes what it does: configure line range)
"write_exit_range": actionWriteBA,
// D4: logdoc → debug_log (opaque internal name → intent-revealing name)
"debug_log": actionLogDoc,
}

// RegisterCompatAliases registers new canonical config key names as viper aliases
// for existing internal names and emits deprecation notices for any old names
// found in the loaded configuration. Must be called after viper.ReadInConfig
// and before viper.Unmarshal.
func RegisterCompatAliases(v *viper.Viper) {
warnDeprecatedKeys(v)
for _, e := range compatViperEntries {
v.RegisterAlias(e.newKey, e.oldKey)
}
}

// warnDeprecatedKeys writes a deprecation notice to stderr for each old config
// key name detected in the loaded configuration (file, env var, or CLI flag).
// Called before alias registration so IsSet reflects direct usage only.
func warnDeprecatedKeys(v *viper.Viper) {
for _, e := range compatViperEntries {
if v.IsSet(e.oldKey) {
fmt.Fprintf(os.Stderr, "ov: config key %q is deprecated, use %q instead\n", e.oldName, e.newName)
}
}
}

// addCompatActionAliases injects new canonical action names into the handler
// map, pointing each to the handler registered under the existing internal name.
func addCompatActionAliases(handlers map[string]func(context.Context)) {
for newName, oldName := range compatActionEntries {
if h, ok := handlers[oldName]; ok {
handlers[newName] = h
}
}
}
4 changes: 3 additions & 1 deletion oviewer/keybind.go
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ const (

// handlers returns a map of the action's handlers.
func (root *Root) handlers() map[string]func(context.Context) {
return map[string]func(context.Context){
h := map[string]func(context.Context){
// General
actionExit: root.Quit,
actionCancel: root.Cancel,
Expand Down Expand Up @@ -273,6 +273,8 @@ func (root *Root) handlers() map[string]func(context.Context) {
inputCopy: root.CopySelect,
inputPaste: root.Paste,
}
addCompatActionAliases(h)
return h
}

// KeyBind represents a mapping from action names to their associated key sequences.
Expand Down
9 changes: 7 additions & 2 deletions oviewer/keybind_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,13 @@ func Test_defaultKeyBinds(t *testing.T) {
}
hm := root.handlers()
kb := DefaultKeyBinds()
if len(hm) != len(kb) {
t.Errorf("number of KeyBind = %v, want %v", len(hm), len(kb))
// handlers() may contain more entries than DefaultKeyBinds (e.g., compat
// aliases have handlers but no default key assignment), so only check that
// every default binding has a corresponding handler.
for action := range kb {
if _, ok := hm[action]; !ok {
t.Errorf("action %q in DefaultKeyBinds has no handler", action)
}
}
})
}
Expand Down
Loading