From e2d9c06649beb008a6a9f88d2b3948e07ea63c33 Mon Sep 17 00:00:00 2001 From: Noboru Saito Date: Mon, 9 Sep 2024 05:50:06 +0900 Subject: [PATCH 1/4] (Re -revision)Change the name of the variable name Change the general name forward for variables. Add ColumnAttribute and put shink and right align inside. Added ShrinkColumn and ExpandColumn. --- oviewer/action.go | 51 ++++++++++------- oviewer/action_test.go | 36 ++++++------ oviewer/convert_align.go | 30 +++++----- oviewer/convert_align_test.go | 100 ++++++++++++++++++++++++---------- oviewer/document.go | 8 +-- oviewer/input_converter.go | 6 +- oviewer/input_viewmode.go | 2 +- oviewer/keybind.go | 2 +- oviewer/oviewer.go | 14 +++-- oviewer/oviewer_test.go | 2 +- oviewer/prepare_draw.go | 30 +++++----- oviewer/prepare_draw_test.go | 2 +- 12 files changed, 171 insertions(+), 112 deletions(-) diff --git a/oviewer/action.go b/oviewer/action.go index 992464a..f1767db 100644 --- a/oviewer/action.go +++ b/oviewer/action.go @@ -425,7 +425,7 @@ func (root *Root) setViewMode(ctx context.Context, modeName string) { // modeConfig returns the configuration of the specified mode. func (root *Root) modeConfig(modeName string) (general, error) { - if modeName == generalName { + if modeName == nameGeneral { return root.General, nil } @@ -450,27 +450,27 @@ func (root *Root) setConverter(ctx context.Context, name string) { // alignFormat sets converter type to align. func (root *Root) alignFormat(ctx context.Context) { - if root.Doc.Converter == alignConv { + if root.Doc.Converter == convAlign { root.esFormat(ctx) return } - root.setConverter(ctx, alignConv) + root.setConverter(ctx, convAlign) root.setMessage("Set align mode") } // rawFormat sets converter type to raw. func (root *Root) rawFormat(ctx context.Context) { - if root.Doc.Converter == rawConv { + if root.Doc.Converter == convRaw { root.esFormat(ctx) return } - root.setConverter(ctx, rawConv) + root.setConverter(ctx, convRaw) root.setMessage("Set raw mode") } // esFormat sets converter type to es. func (root *Root) esFormat(ctx context.Context) { - root.setConverter(ctx, esConv) + root.setConverter(ctx, convEscaped) root.setMessage("Set es mode") } @@ -769,24 +769,33 @@ func (root *Root) bottomSectionLN(ctx context.Context) int { return lN - (root.Doc.topLN + root.Doc.firstLine() - root.Doc.SectionStartPosition) } -// shrinkColumnToggle shrinks or expands the current cursor column. -func (root *Root) shrinkColumnToggle(ctx context.Context) { - root.ShrinkColumn(ctx, root.Doc.columnCursor) +// ShrinkColumn shrinks the specified column. +func (root *Root) ShrinkColumn(ctx context.Context, cursor int) error { + return root.Doc.shrinkColumn(ctx, cursor, true) } -// ShrinkColumn shrinks or expands the specified column. -func (root *Root) ShrinkColumn(ctx context.Context, cursor int) bool { - m := root.Doc - if root.Doc.Converter != alignConv { - root.setMessage("Not align mode") - return false +// ExpandColumn expands the specified column. +func (root *Root) ExpandColumn(ctx context.Context, cursor int) error { + return root.Doc.shrinkColumn(ctx, cursor, false) +} + +// toggleColumnShrink shrinks or expands the current cursor column. +func (root *Root) toggleColumnShrink(ctx context.Context) { + cursor := root.Doc.columnCursor + if err := root.Doc.shrinkColumn(ctx, cursor, !root.Doc.alignConv.columnAttrs[cursor].shrink); err != nil { + root.setMessage(err.Error()) } - if cursor >= len(m.alignConv.shrink) { - root.setMessage("No column selected") - return false +} + +// shinkColumn shrinks or expands the specified column. +func (m *Document) shrinkColumn(ctx context.Context, cursor int, shrink bool) error { + if m.Converter != convAlign { + return ErrNotAlignMode + } + if cursor >= len(m.alignConv.columnAttrs) { + return ErrNoColumnSelected } - m.alignConv.shrink[cursor] = !m.alignConv.shrink[cursor] + m.alignConv.columnAttrs[cursor].shrink = shrink m.ClearCache() - root.ViewSync(ctx) - return true + return nil } diff --git a/oviewer/action_test.go b/oviewer/action_test.go index 4d1741b..ecfe83c 100644 --- a/oviewer/action_test.go +++ b/oviewer/action_test.go @@ -1250,7 +1250,7 @@ func TestRoot_modeConfig(t *testing.T) { { name: "testModeConfig general", args: args{ - modeName: generalName, + modeName: nameGeneral, }, want: general{}, wantErr: false, @@ -1527,21 +1527,21 @@ func TestRoot_setConverter(t *testing.T) { { name: "testSetConverterEscape", args: args{ - name: esConv, + name: convEscaped, }, want: newESConverter(), }, { name: "testSetConverterRaw", args: args{ - name: rawConv, + name: convRaw, }, want: newRawConverter(), }, { name: "testSetConverterAlign", args: args{ - name: alignConv, + name: convAlign, }, want: newAlignConverter(false), }, @@ -1570,45 +1570,49 @@ func TestRoot_ShrinkColumn(t *testing.T) { } type args struct { cursor int + shrink bool } tests := []struct { - name string - fields fields - args args - want bool + name string + fields fields + args args + wantErr bool }{ { name: "testShrinkColumn", fields: fields{ fileName: filepath.Join(testdata, "MOCK_DATA.csv"), - converter: alignConv, + converter: convAlign, }, args: args{ cursor: 0, + shrink: true, }, - want: true, + wantErr: false, }, { name: "testShrinkColumnFalse", fields: fields{ fileName: filepath.Join(testdata, "MOCK_DATA.csv"), - converter: esConv, + converter: convEscaped, }, args: args{ cursor: 0, + shrink: true, }, - want: false, + wantErr: true, }, { name: "testShrinkColumnOver", fields: fields{ fileName: filepath.Join(testdata, "MOCK_DATA.csv"), - converter: alignConv, + converter: convAlign, }, args: args{ cursor: 20, + shrink: true, }, - want: false, + wantErr: true, }, } for _, tt := range tests { @@ -1619,8 +1623,8 @@ func TestRoot_ShrinkColumn(t *testing.T) { root.Doc.Converter = tt.fields.converter root.Doc.ColumnDelimiter = "," root.prepareDraw(ctx) - if got := root.ShrinkColumn(ctx, tt.args.cursor); got != tt.want { - t.Errorf("Root.ShrinkColumn() = %v, want %v", got, tt.want) + if err := root.Doc.shrinkColumn(ctx, tt.args.cursor, tt.args.shrink); (err != nil) != tt.wantErr { + t.Errorf("Root.ShrinkColumn() error = %v, wantErr %v", err, tt.wantErr) } }) } diff --git a/oviewer/convert_align.go b/oviewer/convert_align.go index 163e215..93694d4 100644 --- a/oviewer/convert_align.go +++ b/oviewer/convert_align.go @@ -10,24 +10,28 @@ import ( // It is used to align columns when the delimiter is reached or to align columns by adding spaces to the end of the line. type align struct { es *escapeSequence + orgWidths []int // Original width of each column. This is the width determined by Guesswidth. maxWidths []int // Maximum width of each column. - orgWidths []int - shrink []bool // Shrink column. - rightAlign []bool // Right align column. + columnAttrs []columnAttribute WidthF bool delimiter string delimiterReg *regexp.Regexp count int } +// columnAttribute is a structure that holds the attributes of a column. +type columnAttribute struct { + shrink bool // Shrink column. + rightAlign bool // Right align column. +} + func newAlignConverter(widthF bool) *align { return &align{ - es: newESConverter(), - maxWidths: []int{}, - shrink: []bool{}, - rightAlign: []bool{}, - count: 0, - WidthF: widthF, + es: newESConverter(), + maxWidths: []int{}, + columnAttrs: []columnAttribute{}, + count: 0, + WidthF: widthF, } } @@ -185,17 +189,17 @@ func appendSpaces(lc contents, num int) contents { } func (a *align) isShrink(col int) bool { - if len(a.shrink) <= col { + if len(a.columnAttrs) <= col { return false } - return a.shrink[col] + return a.columnAttrs[col].shrink } func (a *align) isRightAlign(col int) bool { - if len(a.rightAlign) <= col { + if len(a.columnAttrs) <= col { return false } - return a.rightAlign[col] + return a.columnAttrs[col].rightAlign } func countLeftSpaces(lc contents, s int) int { diff --git a/oviewer/convert_align_test.go b/oviewer/convert_align_test.go index 51d7181..e1b6660 100644 --- a/oviewer/convert_align_test.go +++ b/oviewer/convert_align_test.go @@ -161,8 +161,7 @@ func Test_align_convertDelm(t *testing.T) { es *escapeSequence maxWidths []int orgWidths []int - shrink []bool - rightAlign []bool + columns []columnAttribute WidthF bool delimiter string delimiterReg *regexp.Regexp @@ -210,7 +209,13 @@ func Test_align_convertDelm(t *testing.T) { fields: fields{ es: newESConverter(), maxWidths: []int{1, 2, 2, 2, 2, 2}, - shrink: []bool{false, true, false, false, false}, + columns: []columnAttribute{ + {shrink: false, rightAlign: false}, + {shrink: true, rightAlign: false}, + {shrink: false, rightAlign: false}, + {shrink: false, rightAlign: false}, + {shrink: false, rightAlign: false}, + }, WidthF: false, delimiter: ",", count: 0, @@ -225,7 +230,13 @@ func Test_align_convertDelm(t *testing.T) { fields: fields{ es: newESConverter(), maxWidths: []int{1, 2, 2, 2, 2, 2}, - shrink: []bool{true, false, false, false, false}, + columns: []columnAttribute{ + {shrink: true, rightAlign: false}, + {shrink: false, rightAlign: false}, + {shrink: false, rightAlign: false}, + {shrink: false, rightAlign: false}, + {shrink: false, rightAlign: false}, + }, WidthF: false, delimiter: ",", count: 0, @@ -240,7 +251,14 @@ func Test_align_convertDelm(t *testing.T) { fields: fields{ es: newESConverter(), maxWidths: []int{1, 2, 2, 2, 2, 2}, - shrink: []bool{false, false, false, false, false, true}, + columns: []columnAttribute{ + {shrink: false, rightAlign: false}, + {shrink: false, rightAlign: false}, + {shrink: false, rightAlign: false}, + {shrink: false, rightAlign: false}, + {shrink: false, rightAlign: false}, + {shrink: true, rightAlign: false}, + }, WidthF: false, delimiter: ",", count: 0, @@ -253,12 +271,18 @@ func Test_align_convertDelm(t *testing.T) { { name: "convertAlignDelmRight", fields: fields{ - es: newESConverter(), - maxWidths: []int{1, 2, 2, 2, 2, 2}, - shrink: []bool{false, false, false, false, false, true}, - rightAlign: []bool{true, false, false, false, false, false}, - WidthF: false, - delimiter: ",", + es: newESConverter(), + maxWidths: []int{1, 2, 2, 2, 2, 2}, + columns: []columnAttribute{ + {shrink: false, rightAlign: true}, + {shrink: false, rightAlign: false}, + {shrink: false, rightAlign: false}, + {shrink: false, rightAlign: false}, + {shrink: false, rightAlign: false}, + {shrink: true, rightAlign: false}, + }, + WidthF: false, + delimiter: ",", }, args: args{ src: StrToContents("a,b,c,d,e,f", 8), @@ -272,8 +296,7 @@ func Test_align_convertDelm(t *testing.T) { es: tt.fields.es, maxWidths: tt.fields.maxWidths, orgWidths: tt.fields.orgWidths, - shrink: tt.fields.shrink, - rightAlign: tt.fields.rightAlign, + columnAttrs: tt.fields.columns, WidthF: tt.fields.WidthF, delimiter: tt.fields.delimiter, delimiterReg: tt.fields.delimiterReg, @@ -293,8 +316,7 @@ func Test_align_convertWidth(t *testing.T) { es *escapeSequence maxWidths []int orgWidths []int - shrink []bool - rightAlign []bool + columns []columnAttribute WidthF bool delimiter string delimiterReg *regexp.Regexp @@ -343,9 +365,15 @@ func Test_align_convertWidth(t *testing.T) { es: newESConverter(), maxWidths: []int{3, 3, 3, 3, 3}, orgWidths: []int{2, 5, 8, 11, 14}, - shrink: []bool{false, true, false, false, false}, - WidthF: true, - count: 0, + columns: []columnAttribute{ + {shrink: false, rightAlign: false}, + {shrink: true, rightAlign: false}, + {shrink: false, rightAlign: false}, + {shrink: false, rightAlign: false}, + {shrink: false, rightAlign: false}, + }, + WidthF: true, + count: 0, }, args: args{ src: StrToContents("a b c d e f", 8), @@ -358,9 +386,16 @@ func Test_align_convertWidth(t *testing.T) { es: newESConverter(), maxWidths: []int{3, 3, 3, 3, 3}, orgWidths: []int{2, 5, 8, 11, 14}, - shrink: []bool{false, false, false, false, false, true}, - WidthF: true, - count: 0, + columns: []columnAttribute{ + {shrink: false, rightAlign: false}, + {shrink: false, rightAlign: false}, + {shrink: false, rightAlign: false}, + {shrink: false, rightAlign: false}, + {shrink: false, rightAlign: false}, + {shrink: true, rightAlign: false}, + }, + WidthF: true, + count: 0, }, args: args{ src: StrToContents("a b c d e f", 8), @@ -370,13 +405,19 @@ func Test_align_convertWidth(t *testing.T) { { name: "convertAlignWidthRight", fields: fields{ - es: newESConverter(), - maxWidths: []int{3, 3, 3, 3, 3, 3}, - orgWidths: []int{2, 5, 8, 11, 14, 17}, - shrink: []bool{false, false, false, false, false, true}, - rightAlign: []bool{true, false, false, false, false, false}, - WidthF: true, - count: 0, + es: newESConverter(), + maxWidths: []int{3, 3, 3, 3, 3, 3}, + orgWidths: []int{2, 5, 8, 11, 14, 17}, + columns: []columnAttribute{ + {shrink: false, rightAlign: true}, + {shrink: false, rightAlign: false}, + {shrink: false, rightAlign: false}, + {shrink: false, rightAlign: false}, + {shrink: false, rightAlign: false}, + {shrink: true, rightAlign: false}, + }, + WidthF: true, + count: 0, }, args: args{ src: StrToContents("a b c d e f", 8), @@ -390,8 +431,7 @@ func Test_align_convertWidth(t *testing.T) { es: tt.fields.es, maxWidths: tt.fields.maxWidths, orgWidths: tt.fields.orgWidths, - shrink: tt.fields.shrink, - rightAlign: tt.fields.rightAlign, + columnAttrs: tt.fields.columns, WidthF: tt.fields.WidthF, delimiter: tt.fields.delimiter, delimiterReg: tt.fields.delimiterReg, diff --git a/oviewer/document.go b/oviewer/document.go index 38e11a9..ccc7c69 100644 --- a/oviewer/document.go +++ b/oviewer/document.go @@ -212,7 +212,7 @@ func NewDocument() (*Document, error) { ColumnDelimiter: "", TabWidth: 8, MarkStyleWidth: 1, - Converter: esConv, + Converter: convEscaped, }, ctlCh: make(chan controlSpecifier), memoryLimit: 100, @@ -243,11 +243,11 @@ func (m *Document) NewCache() error { // converterType returns the Converter type. func (m *Document) converterType(name string) Converter { switch name { - case rawConv: + case convRaw: return newRawConverter() - case esConv: + case convEscaped: return newESConverter() - case alignConv: + case convAlign: return m.alignConv } return defaultConverter diff --git a/oviewer/input_converter.go b/oviewer/input_converter.go index 72c1456..5b4964f 100644 --- a/oviewer/input_converter.go +++ b/oviewer/input_converter.go @@ -17,9 +17,9 @@ func (root *Root) setConvertType(context.Context) { func converterCandidate() *candidate { return &candidate{ list: []string{ - esConv, - rawConv, - alignConv, + convEscaped, + convRaw, + convAlign, }, } } diff --git a/oviewer/input_viewmode.go b/oviewer/input_viewmode.go index d1f2330..a1d117e 100644 --- a/oviewer/input_viewmode.go +++ b/oviewer/input_viewmode.go @@ -17,7 +17,7 @@ func (root *Root) setViewInputMode(context.Context) { func viewModeCandidate() *candidate { return &candidate{ list: []string{ - generalName, + nameGeneral, }, } } diff --git a/oviewer/keybind.go b/oviewer/keybind.go index 002e0e6..b9b112b 100644 --- a/oviewer/keybind.go +++ b/oviewer/keybind.go @@ -173,7 +173,7 @@ func (root *Root) handlers() map[string]func(context.Context) { actionConvertType: root.setConvertType, actionAlignFormat: root.alignFormat, actionRawFormat: root.rawFormat, - actionShrinkColumn: root.shrinkColumnToggle, + actionShrinkColumn: root.toggleColumnShrink, inputCaseSensitive: root.inputCaseSensitive, inputSmartCaseSensitive: root.inputSmartCaseSensitive, diff --git a/oviewer/oviewer.go b/oviewer/oviewer.go index 78495e6..0068420 100644 --- a/oviewer/oviewer.go +++ b/oviewer/oviewer.go @@ -362,13 +362,13 @@ const MaxWriteLog int = 10 // The name of the converter that can be specified. const ( - esConv string = "es" // esConv processes escape sequence(default). - rawConv string = "raw" // rawConv is displayed without processing escape sequences as they are. - alignConv string = "align" // alignConv is aligned in each column. + convEscaped string = "es" // convEscaped processes escape sequence(default). + convRaw string = "raw" // convRaw is displayed without processing escape sequences as they are. + convAlign string = "align" // convAlign is aligned in each column. ) const ( - generalName string = "general" + nameGeneral string = "general" ) var Shrink rune = '…' @@ -422,6 +422,10 @@ var ( ErrAlreadyLoaded = errors.New("chunk already loaded") // ErrEvictedMemory indicates that it has been evicted from memory. ErrEvictedMemory = errors.New("evicted memory") + // ErrNotAlignMode indicates that it is not an align mode. + ErrNotAlignMode = errors.New("not align mode") + // ErrNoColumnSelected indicates that no column is selected. + ErrNoColumnSelected = errors.New("no column selected") ) // This is a function of tcell.NewScreen but can be replaced with mock. @@ -734,7 +738,7 @@ func (root *Root) setCaption() { // setViewModeConfig sets view mode config. func (root *Root) setViewModeConfig() { list := make([]string, 0, len(root.Config.Mode)+1) - list = append(list, generalName) + list = append(list, nameGeneral) for name := range root.Config.Mode { list = append(list, name) } diff --git a/oviewer/oviewer_test.go b/oviewer/oviewer_test.go index 8e82918..59e6e14 100644 --- a/oviewer/oviewer_test.go +++ b/oviewer/oviewer_test.go @@ -560,7 +560,7 @@ func TestRoot_setViewModeConfig(t *testing.T) { "view1": {}, }, }, - wantList: []string{generalName, "view1"}, + wantList: []string{nameGeneral, "view1"}, }, } for _, tt := range tests { diff --git a/oviewer/prepare_draw.go b/oviewer/prepare_draw.go index 0d21b6b..52980f6 100644 --- a/oviewer/prepare_draw.go +++ b/oviewer/prepare_draw.go @@ -89,7 +89,7 @@ func (root *Root) prepareDraw(ctx context.Context) { } // Sets alignConv if the converter is align. - if root.Doc.Converter == alignConv { + if root.Doc.Converter == convAlign { root.setAlignConverter() } @@ -120,22 +120,20 @@ func (root *Root) setAlignConverter() { maxWidths, addRight = m.maxColumnWidths(maxWidths, addRight, ln) } - if !slices.Equal(m.alignConv.maxWidths, maxWidths) { - m.alignConv.orgWidths = m.columnWidths - m.alignConv.maxWidths = maxWidths - for n := len(m.alignConv.shrink); n < len(maxWidths)+1; n++ { - m.alignConv.shrink = append(m.alignConv.shrink, false) - } - for n := len(m.alignConv.rightAlign); n < len(maxWidths)+1; n++ { - m.alignConv.rightAlign = append(m.alignConv.rightAlign, false) - } - for i := 0; i < len(addRight); i++ { - if !m.alignConv.rightAlign[i] { - m.alignConv.rightAlign[i] = addRight[i] > 1 - } + if slices.Equal(m.alignConv.maxWidths, maxWidths) { + return + } + m.alignConv.orgWidths = m.columnWidths + m.alignConv.maxWidths = maxWidths + for n := len(m.alignConv.columnAttrs); n < len(maxWidths)+1; n++ { + m.alignConv.columnAttrs = append(m.alignConv.columnAttrs, columnAttribute{}) + } + for i := 0; i < len(addRight); i++ { + if !m.alignConv.columnAttrs[i].rightAlign { + m.alignConv.columnAttrs[i].rightAlign = addRight[i] > 1 } - m.ClearCache() } + m.ClearCache() } // maxColumnWidths returns the maximum width of the column. @@ -508,7 +506,7 @@ func (root *Root) columnWidthHighlight(line LineC) { start := 0 for c := 0; c < len(indexes)+1; c++ { end := 0 - if m.Converter == alignConv { + if m.Converter == convAlign { end = alignColumnEnd(line.lc, m.alignConv.maxWidths, c, start) } else { end = findColumnEnd(line.lc, indexes, c) diff --git a/oviewer/prepare_draw_test.go b/oviewer/prepare_draw_test.go index d6b3412..3dfd444 100644 --- a/oviewer/prepare_draw_test.go +++ b/oviewer/prepare_draw_test.go @@ -1144,7 +1144,7 @@ func TestRoot_setAlignConverter(t *testing.T) { root.prepareScreen() ctx := context.Background() root.Doc.ColumnRainbow = true - root.Doc.Converter = alignConv + root.Doc.Converter = convAlign root.Doc.alignConv = newAlignConverter(true) root.prepareDraw(ctx) if got := root.Doc.alignConv.maxWidths; !reflect.DeepEqual(got, tt.want) { From d4826a25968f057867f799df13277c8e940ef5b5 Mon Sep 17 00:00:00 2001 From: Noboru Saito Date: Mon, 9 Sep 2024 06:24:23 +0900 Subject: [PATCH 2/4] Add a check to shrink in Align mode Add a shrinking column or judgment function. Add functions other than the shrink and expansion tooggle. --- oviewer/action.go | 23 +++++++++++++++++++---- oviewer/action_test.go | 2 +- 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/oviewer/action.go b/oviewer/action.go index f1767db..3241d04 100644 --- a/oviewer/action.go +++ b/oviewer/action.go @@ -771,24 +771,39 @@ func (root *Root) bottomSectionLN(ctx context.Context) int { // ShrinkColumn shrinks the specified column. func (root *Root) ShrinkColumn(ctx context.Context, cursor int) error { - return root.Doc.shrinkColumn(ctx, cursor, true) + return root.Doc.shrinkColumn(cursor, true) } // ExpandColumn expands the specified column. func (root *Root) ExpandColumn(ctx context.Context, cursor int) error { - return root.Doc.shrinkColumn(ctx, cursor, false) + return root.Doc.shrinkColumn(cursor, false) } // toggleColumnShrink shrinks or expands the current cursor column. func (root *Root) toggleColumnShrink(ctx context.Context) { cursor := root.Doc.columnCursor - if err := root.Doc.shrinkColumn(ctx, cursor, !root.Doc.alignConv.columnAttrs[cursor].shrink); err != nil { + shrink, err := root.Doc.isColumnShink(cursor) + if err != nil { + root.setMessage(err.Error()) + } + if err := root.Doc.shrinkColumn(cursor, !shrink); err != nil { root.setMessage(err.Error()) } } +// isColumnShink returns whether the specified column is shrink. +func (m *Document) isColumnShink(cursor int) (bool, error) { + if m.Converter != convAlign { + return false, ErrNotAlignMode + } + if cursor >= len(m.alignConv.columnAttrs) { + return false, ErrNoColumnSelected + } + return m.alignConv.columnAttrs[cursor].shrink, nil +} + // shinkColumn shrinks or expands the specified column. -func (m *Document) shrinkColumn(ctx context.Context, cursor int, shrink bool) error { +func (m *Document) shrinkColumn(cursor int, shrink bool) error { if m.Converter != convAlign { return ErrNotAlignMode } diff --git a/oviewer/action_test.go b/oviewer/action_test.go index ecfe83c..d732d27 100644 --- a/oviewer/action_test.go +++ b/oviewer/action_test.go @@ -1623,7 +1623,7 @@ func TestRoot_ShrinkColumn(t *testing.T) { root.Doc.Converter = tt.fields.converter root.Doc.ColumnDelimiter = "," root.prepareDraw(ctx) - if err := root.Doc.shrinkColumn(ctx, tt.args.cursor, tt.args.shrink); (err != nil) != tt.wantErr { + if err := root.Doc.shrinkColumn(tt.args.cursor, tt.args.shrink); (err != nil) != tt.wantErr { t.Errorf("Root.ShrinkColumn() error = %v, wantErr %v", err, tt.wantErr) } }) From 44df926e61eecc73f78b42cda52d0162c86d28df Mon Sep 17 00:00:00 2001 From: Noboru Saito Date: Mon, 9 Sep 2024 07:06:53 +0900 Subject: [PATCH 3/4] Fix typo and add comments --- oviewer/action.go | 6 +++--- oviewer/oviewer.go | 2 +- oviewer/prepare_draw.go | 1 + 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/oviewer/action.go b/oviewer/action.go index 3241d04..ea21cde 100644 --- a/oviewer/action.go +++ b/oviewer/action.go @@ -782,7 +782,7 @@ func (root *Root) ExpandColumn(ctx context.Context, cursor int) error { // toggleColumnShrink shrinks or expands the current cursor column. func (root *Root) toggleColumnShrink(ctx context.Context) { cursor := root.Doc.columnCursor - shrink, err := root.Doc.isColumnShink(cursor) + shrink, err := root.Doc.isColumnShrink(cursor) if err != nil { root.setMessage(err.Error()) } @@ -791,8 +791,8 @@ func (root *Root) toggleColumnShrink(ctx context.Context) { } } -// isColumnShink returns whether the specified column is shrink. -func (m *Document) isColumnShink(cursor int) (bool, error) { +// isColumnShrink returns whether the specified column is shrink. +func (m *Document) isColumnShrink(cursor int) (bool, error) { if m.Converter != convAlign { return false, ErrNotAlignMode } diff --git a/oviewer/oviewer.go b/oviewer/oviewer.go index 0068420..f6f8a8e 100644 --- a/oviewer/oviewer.go +++ b/oviewer/oviewer.go @@ -423,7 +423,7 @@ var ( // ErrEvictedMemory indicates that it has been evicted from memory. ErrEvictedMemory = errors.New("evicted memory") // ErrNotAlignMode indicates that it is not an align mode. - ErrNotAlignMode = errors.New("not align mode") + ErrNotAlignMode = errors.New("not an align mode") // ErrNoColumnSelected indicates that no column is selected. ErrNoColumnSelected = errors.New("no column selected") ) diff --git a/oviewer/prepare_draw.go b/oviewer/prepare_draw.go index 52980f6..cca8e4f 100644 --- a/oviewer/prepare_draw.go +++ b/oviewer/prepare_draw.go @@ -125,6 +125,7 @@ func (root *Root) setAlignConverter() { } m.alignConv.orgWidths = m.columnWidths m.alignConv.maxWidths = maxWidths + // column attributes are inherited, so only the required columns are added. for n := len(m.alignConv.columnAttrs); n < len(maxWidths)+1; n++ { m.alignConv.columnAttrs = append(m.alignConv.columnAttrs, columnAttribute{}) } From 039d5e39d98cf8a3c19a1763492051b6824ae5bc Mon Sep 17 00:00:00 2001 From: Noboru Saito Date: Tue, 10 Sep 2024 08:39:56 +0900 Subject: [PATCH 4/4] Clarify the range determination of slice --- oviewer/action.go | 2 +- oviewer/convert_align.go | 12 ++--- oviewer/convert_align_test.go | 88 +++++++++++++++++++++++++++++++++++ 3 files changed, 95 insertions(+), 7 deletions(-) diff --git a/oviewer/action.go b/oviewer/action.go index ea21cde..5a851df 100644 --- a/oviewer/action.go +++ b/oviewer/action.go @@ -807,7 +807,7 @@ func (m *Document) shrinkColumn(cursor int, shrink bool) error { if m.Converter != convAlign { return ErrNotAlignMode } - if cursor >= len(m.alignConv.columnAttrs) { + if cursor < 0 || cursor >= len(m.alignConv.columnAttrs) { return ErrNoColumnSelected } m.alignConv.columnAttrs[cursor].shrink = shrink diff --git a/oviewer/convert_align.go b/oviewer/convert_align.go index 93694d4..596628a 100644 --- a/oviewer/convert_align.go +++ b/oviewer/convert_align.go @@ -189,17 +189,17 @@ func appendSpaces(lc contents, num int) contents { } func (a *align) isShrink(col int) bool { - if len(a.columnAttrs) <= col { - return false + if col >= 0 && col < len(a.columnAttrs) { + return a.columnAttrs[col].shrink } - return a.columnAttrs[col].shrink + return false } func (a *align) isRightAlign(col int) bool { - if len(a.columnAttrs) <= col { - return false + if col >= 0 && col < len(a.columnAttrs) { + return a.columnAttrs[col].rightAlign } - return a.columnAttrs[col].rightAlign + return false } func countLeftSpaces(lc contents, s int) int { diff --git a/oviewer/convert_align_test.go b/oviewer/convert_align_test.go index e1b6660..e595f10 100644 --- a/oviewer/convert_align_test.go +++ b/oviewer/convert_align_test.go @@ -445,3 +445,91 @@ func Test_align_convertWidth(t *testing.T) { }) } } + +func Test_align_isRightAlign(t *testing.T) { + type fields struct { + es *escapeSequence + orgWidths []int + maxWidths []int + columnAttrs []columnAttribute + WidthF bool + delimiter string + delimiterReg *regexp.Regexp + count int + } + type args struct { + col int + } + tests := []struct { + name string + fields fields + args args + want bool + }{ + { + name: "isRightAlign1", + fields: fields{ + es: newESConverter(), + maxWidths: []int{1, 2, 3}, + columnAttrs: []columnAttribute{{rightAlign: true}, {rightAlign: true}, {rightAlign: true}}, + }, + args: args{ + col: 0, + }, + want: true, + }, + { + name: "isRightAlign2", + fields: fields{ + es: newESConverter(), + maxWidths: []int{1, 2, 3}, + columnAttrs: []columnAttribute{{rightAlign: true}, {rightAlign: true}, {rightAlign: true}}, + }, + args: args{ + col: 1, + }, + want: true, + }, + { + name: "isRightAlign4", + fields: fields{ + es: newESConverter(), + maxWidths: []int{1, 2, 3}, + columnAttrs: []columnAttribute{{rightAlign: true}, {rightAlign: true}, {rightAlign: true}}, + }, + args: args{ + col: 4, + }, + want: false, + }, + { + name: "isRightAlign-1", + fields: fields{ + es: newESConverter(), + maxWidths: []int{1, 2, 3}, + columnAttrs: []columnAttribute{{rightAlign: true}, {rightAlign: true}, {rightAlign: true}}, + }, + args: args{ + col: -1, + }, + want: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + a := &align{ + es: tt.fields.es, + orgWidths: tt.fields.orgWidths, + maxWidths: tt.fields.maxWidths, + columnAttrs: tt.fields.columnAttrs, + WidthF: tt.fields.WidthF, + delimiter: tt.fields.delimiter, + delimiterReg: tt.fields.delimiterReg, + count: tt.fields.count, + } + if got := a.isRightAlign(tt.args.col); got != tt.want { + t.Errorf("align.isRightAlign() = %v, want %v", got, tt.want) + } + }) + } +}