Skip to content

Commit

Permalink
Merge pull request #23 from xztaityozx/v1.1.4
Browse files Browse the repository at this point in the history
V1.1.4
  • Loading branch information
xztaityozx authored Oct 30, 2021
2 parents dda7b66 + b2eeca1 commit db32960
Show file tree
Hide file tree
Showing 21 changed files with 1,580 additions and 255 deletions.
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
MIT License

Copyright (c) 2020 xztaityozx
Copyright (c) 2021 xztaityozx

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
28 changes: 13 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,7 @@ $ sel completion zsh > ${fpath[1]}/_sel
# Usage

```
_
_
___ ___| |
/ __|/ _ \ |
\__ \ __/ |
Expand All @@ -45,23 +44,23 @@ $ sel completion zsh > ${fpath[1]}/_sel
__sel__ect column
Usage:
sel [queries...]
sel [queries...]
Query:
index select 'index'
start:stop select columns from 'start' to 'stop'
start:stop:step select columns each 'step' from 'start' to 'stop'
index select 'index'
start:stop select columns from 'start' to 'stop'
start:stop:step select columns each 'step' from 'start' to 'stop'
start:/end regexp/ select columns from 'start' to /end regexp/
/start regexp/:end select columns from /start regexp/ to 'end'
/start regexp/:/end regexp/ select columns from /start regexp/ to /end regexp/
start:/end regexp/ select columns from 'start' to /end regexp/
/start regexp/:end select columns from /start regexp/ to 'end'
/start regexp/:/end regexp/ select columns from /start regexp/ to /end regexp/
Examples:
$ cat /path/to/file | sel 1
$ sel 1:10 -f ./file
$ cat /path/to/file.csv | sel -d, 1 2 3 4 -1 -2 -3 -4
$ sel 2:: -f ./file
$ cat /path/to/file | sel 1
$ sel 1:10 -f ./file
$ cat /path/to/file.csv | sel -d, 1 2 3 4 -1 -2 -3 -4
$ sel 2:: -f ./file
Available Commands:
completion Generate completion script
Expand All @@ -73,10 +72,9 @@ Flags:
-f, --input-files strings input files
-D, --output-delimiter string sets field delimiter(output) (default " ")
-r, --remove-empty remove empty sequence
-S, --split-before split all column before select
-g, --use-regexp use regular expressions for input delimiter
-v, --version version for sel
Use "sel [command] --help" for more information about a command.
```

# Features
Expand Down
46 changes: 33 additions & 13 deletions cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,11 @@ import (
"bufio"
"log"
"os"
"regexp"
"strings"

"github.com/xztaityozx/sel/iterator"

"github.com/spf13/cobra"
"github.com/spf13/viper"
"github.com/xztaityozx/sel/column"
Expand All @@ -25,7 +28,7 @@ var rootCmd = &cobra.Command{
__sel__ect column`,
Args: cobra.MinimumNArgs(1),
Version: "1.1.1",
Version: "1.1.4",
Run: func(cmd *cobra.Command, args []string) {
opt := option.NewOption(viper.GetViper())
selectors, err := parser.Parse(args)
Expand All @@ -34,14 +37,34 @@ __sel__ect column`,
}

w := column.NewWriter(opt.OutPutDelimiter, os.Stdout)
var splitter column.Splitter

var iter iterator.IEnumerable

// これから使うイテレーターを生成
// オプションのON/OFFで行の分割戦略を変える
if opt.UseRegexp {
splitter, err = column.NewSplitterRegexp(opt.InputDelimiter, opt.RemoveEmpty)
// Regexpを使う系の分割。遅め
r, err := regexp.Compile(opt.InputDelimiter)
if err != nil {
log.Fatalln(err)
}

if opt.SplitBefore {
// 事前に分割する。選択しないカラムも分割するが、後半のカラムを選択するときにはこちらが有利
iter = iterator.NewPreSplitByRegexpIterator("", r, opt.RemoveEmpty)
} else {
// 欲しいところまで分割する。前の方に位置するカラムだけを選ぶ時に有利。
// 負のインデックスを指定する場合は全部分割してしまうので不利
iter = iterator.NewRegexpIterator("", r, opt.RemoveEmpty)
}
} else {
splitter = column.NewSplitter(opt.InputDelimiter, opt.RemoveEmpty)
if opt.SplitBefore {
// 事前に分割する。regexp版と説明は同じ
iter = iterator.NewPreSplitIterator("", opt.InputDelimiter, opt.RemoveEmpty)
} else {
// 最速。ただし、シンプルなIndex指定の時だけ
iter = iterator.NewIterator("", opt.InputDelimiter, opt.RemoveEmpty)
}
}

if len(opt.Files) != 0 {
Expand All @@ -54,13 +77,13 @@ __sel__ect column`,
if fp, err := os.OpenFile(file, os.O_RDONLY, 0644); err != nil {
log.Fatalln(err)
} else {
if err := run(fp, splitter, w, selectors); err != nil {
if err := run(fp, iter, w, selectors); err != nil {
log.Fatalln(err)
}
}
}
} else {
if err := run(os.Stdin, splitter, w, selectors); err != nil {
if err := run(os.Stdin, iter, w, selectors); err != nil {
log.Fatalln(err)
}
}
Expand All @@ -79,6 +102,7 @@ func init() {
rootCmd.Flags().StringP(option.NameOutPutDelimiter, "D", " ", "sets field delimiter(output)")
rootCmd.Flags().BoolP(option.NameRemoveEmpty, "r", false, "remove empty sequence")
rootCmd.Flags().BoolP(option.NameUseRegexp, "g", false, "use regular expressions for input delimiter")
rootCmd.Flags().BoolP(option.NameSplitBefore, "S", false, "split all column before select")
_ = rootCmd.MarkFlagFilename(option.NameInputFiles)

for _, key := range option.GetOptionNames() {
Expand Down Expand Up @@ -126,7 +150,7 @@ Use "{{.CommandPath}} [command] --help" for more information about a command.{{e
`)
}

func run(input *os.File, splitter column.Splitter, writer *column.Writer, selectors []column.Selector) error {
func run(input *os.File, iter iterator.IEnumerable, writer *column.Writer, selectors []column.Selector) error {
defer func(input *os.File) {
err := input.Close()
if err != nil {
Expand All @@ -136,16 +160,12 @@ func run(input *os.File, splitter column.Splitter, writer *column.Writer, select

scan := bufio.NewScanner(input)
for scan.Scan() {
line := splitter.Split(scan.Text())
iter.Reset(scan.Text())
for _, selector := range selectors {
cols, err := selector.Select(line)
err := selector.Select(writer, iter)
if err != nil {
return err
}

if err := writer.Write(cols); err != nil {
return err
}
}

if err := writer.WriteNewLine(); err != nil {
Expand Down
18 changes: 8 additions & 10 deletions column/index.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package column

import (
"fmt"
"github.com/xztaityozx/sel/iterator"
"strconv"
)

Expand All @@ -22,17 +22,15 @@ func NewIndexSelectorFromString(str string, def int) (IndexSelector, error) {
return NewIndexSelector(num), err
}

func (i IndexSelector) Select(strings []string) ([]string, error) {
if len(strings) < i.index {
return nil, fmt.Errorf("index out of range")
}
func (i IndexSelector) Select(w *Writer, iter iterator.IEnumerable) error {

if i.index == 0 {
return strings, nil
return w.Write(iter.ToArray()...)
}

if i.index < 0 {
return []string{strings[len(strings)+(i.index)]}, nil
item, err := iter.ElementAt(i.index)
if err != nil {
return err
}

return []string{strings[i.index-1]}, nil
return w.Write(item)
}
18 changes: 13 additions & 5 deletions column/index_test.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
package column

import (
"bytes"
"github.com/stretchr/testify/assert"
"github.com/xztaityozx/sel/iterator"
"github.com/xztaityozx/sel/test_util"
"math/rand"
"reflect"
"strings"
"testing"
"time"
)
Expand Down Expand Up @@ -57,14 +60,19 @@ func TestIndexSelector_Select(t *testing.T) {

is := IndexSelector{index: rand.Int() % 10}

actual, err := is.Select(cols)
var buf []byte
w := bytes.NewBuffer(buf)

writer := NewWriter(" ", w)

err := is.Select(writer, iterator.NewIterator(strings.Join(cols, " "), " ", false))

assert.Nil(t, writer.Flush())
assert.Nil(t, err)
assert.NotNil(t, actual)
if is.index == 0 {
assert.Equal(t, cols, actual)
assert.Equal(t, strings.Join(cols, " "), w.String())
} else {
assert.Equal(t, 1, len(actual))
assert.Equal(t, cols[is.index-1], actual[0])
assert.Equal(t, cols[is.index-1], w.String())
}
}
}
59 changes: 46 additions & 13 deletions column/range.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package column

import (
"fmt"
"github.com/xztaityozx/sel/iterator"
)

// RangeSelector はカラムの範囲選択するやつ
Expand All @@ -16,7 +17,8 @@ func NewRangeSelector(start, step, stop int, isInfStop bool) RangeSelector {
return RangeSelector{start: start, step: step, stop: stop, isInfStop: isInfStop}
}

func (r RangeSelector) Select(strings []string) ([]string, error) {
func (r RangeSelector) Select(w *Writer, iter iterator.IEnumerable) error {
strings := iter.ToArray()
max := len(strings)

start := r.start
Expand All @@ -36,36 +38,67 @@ func (r RangeSelector) Select(strings []string) ([]string, error) {

if start == stop {
if start > max {
return nil, fmt.Errorf("index out of range")
return fmt.Errorf("index out of range")
}
return []string{strings[start-1]}, nil

return w.Write(strings[start-1])
} else if start < stop {
if step < 0 {
return nil, fmt.Errorf("step must be bigger than 0(start:step:stop=%d:%d:%d)", start, step, stop)
return fmt.Errorf("step must be bigger than 0(start:step:stop=%d:%d:%d)", start, step, stop)
}

l := 0
for i := start; i <= stop; i += step {
if i == 0 {
l += len(strings)
} else {
l++
}
}

var rt []string
rt := make([]string, l)
idx := 0
for i := start; i <= stop; i += step {
if i == 0 {
rt = append(rt, strings...)
for _, v := range strings {
rt[idx] = v
idx++
}
} else {
rt = append(rt, strings[i-1])
rt[idx] = strings[i-1]
idx++
}
}
return rt, nil

return w.Write(rt...)
} else {
if step > 0 {
return nil, fmt.Errorf("step must be less than 0(start:step:stop=%d:%d:%d)", start, step, stop)
return fmt.Errorf("step must be less than 0(start:step:stop=%d:%d:%d)", start, step, stop)
}
var rt []string

l := 0
for i := start; i >= stop; i += step {
if i == 0 {
l += len(strings)
} else {
l++
}
}

rt := make([]string, l)
idx := 0
for i := start; i >= stop; i += step {
if i == 0 {
rt = append(rt, strings...)
for _, v := range strings {
rt[idx] = v
idx++
}
} else {
rt = append(rt, strings[i-1])
rt[idx] = strings[i-1]
idx++
}
}

return rt, nil
return w.Write(rt...)
}
}
Loading

0 comments on commit db32960

Please sign in to comment.