Skip to content
Merged
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
18 changes: 10 additions & 8 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,17 @@ VERSION?=${shell git describe --tags}

all: lint test build

run:
@echo "building ${VERSION}"
go run ./cmd/jlv assets/example.log
.PHONY: build
run: build
./bin/jlv assets/example.log
.PHONY: run

run.stdin:
@echo "building ${VERSION}"
go run ./cmd/jlv < assets/example.log
.PHONY: build
run.version: build
./bin/jlv --version
.PHONY: run.version

run.stdin: build
./bin/jlv < assets/example.log
.PHONY: run.stdin

build:
@echo "building ${VERSION}"
Expand Down
34 changes: 31 additions & 3 deletions cmd/jlv/main.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package main

import (
"bytes"
"flag"
"fmt"
"os"
Expand All @@ -15,12 +16,23 @@ import (
"github.com/hedhyw/json-log-viewer/internal/pkg/source/readerinput"
)

// version will be set on build.
var version = "development"

const configFileName = ".jlv.jsonc"

func main() {
configPath := flag.String("config", "", "Path to the config")
printVersion := flag.Bool("version", false, "Print version")
flag.Parse()

if *printVersion {
// nolint: forbidigo // Version command.
print("github.com/hedhyw/json-log-viewer@" + version + "\n")

return
}

cfg, err := readConfig(*configPath)
if err != nil {
fatalf("Error reading config: %s\n", err)
Expand All @@ -30,21 +42,37 @@ func main() {

switch flag.NArg() {
case 0:
sourceInput = readerinput.New(os.Stdin, cfg.StdinReadTimeout)
sourceInput, err = getStdinSource(cfg)
if err != nil {
fatalf("Stdin: %s\n", err)
}
case 1:
sourceInput = fileinput.New(flag.Arg(0))
default:
fatalf("Invalid arguments, usage: %s file.log\n", os.Args[0])
}

appModel := app.NewModel(sourceInput, cfg)
program := tea.NewProgram(appModel, tea.WithAltScreen())
appModel := app.NewModel(sourceInput, cfg, version)
program := tea.NewProgram(appModel, tea.WithInputTTY(), tea.WithAltScreen())

if _, err := program.Run(); err != nil {
fatalf("Error running program: %s\n", err)
}
}

func getStdinSource(cfg *config.Config) (source.Input, error) {
stat, err := os.Stdin.Stat()
if err != nil {
return nil, fmt.Errorf("stat: %w", err)
}

if stat.Mode()&os.ModeNamedPipe == 0 {
return readerinput.New(bytes.NewReader(nil), cfg.StdinReadTimeout), nil
}

return readerinput.New(os.Stdin, cfg.StdinReadTimeout), nil
}

func fatalf(message string, args ...any) {
fmt.Fprintf(os.Stderr, message, args...)
os.Exit(1)
Expand Down
18 changes: 15 additions & 3 deletions internal/app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,15 @@ type Application struct {
FooterStyle lipgloss.Style

LastWindowSize tea.WindowSizeMsg

Version string
}

func newApplication(sourceInput source.Input, config *config.Config) Application {
func newApplication(
sourceInput source.Input,
config *config.Config,
version string,
) Application {
const (
initialWidth = 70
initialHeight = 20
Expand All @@ -36,11 +42,17 @@ func newApplication(sourceInput source.Input, config *config.Config) Application
Width: initialWidth,
Height: initialHeight,
},

Version: version,
}
}

// NewModel initializes a new application model. It accept the path
// to the file with logs.
func NewModel(sourceInput source.Input, config *config.Config) tea.Model {
return newStateInitial(newApplication(sourceInput, config))
func NewModel(
sourceInput source.Input,
config *config.Config,
version string,
) tea.Model {
return newStateInitial(newApplication(sourceInput, config, version))
}
4 changes: 3 additions & 1 deletion internal/app/app_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,14 @@ import (
"github.com/hedhyw/json-log-viewer/internal/pkg/tests"
)

const testVersion = "v0.0.1"

func newTestModel(tb testing.TB, content []byte) tea.Model {
tb.Helper()

testFile := tests.RequireCreateFile(tb, content)

model := app.NewModel(fileinput.New(testFile), config.GetDefaultConfig())
model := app.NewModel(fileinput.New(testFile), config.GetDefaultConfig(), testVersion)
model = handleUpdate(model, model.Init()())

return model
Expand Down
1 change: 1 addition & 0 deletions internal/app/stateinitial_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ func TestStateInitial(t *testing.T) {
model := app.NewModel(
readerinput.New(bytes.NewReader([]byte{}), time.Millisecond),
config.GetDefaultConfig(),
testVersion,
)

_, ok := model.(app.StateInitialModel)
Expand Down
2 changes: 1 addition & 1 deletion internal/app/stateloaded.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ func (s StateLoadedModel) viewTable() string {
}

func (s StateLoadedModel) viewHelp() string {
return "\n" + s.help.View(s.keys)
return "\n" + s.Version + " " + s.help.View(s.keys)
}

// Update handles events. It implements tea.Model.
Expand Down
6 changes: 6 additions & 0 deletions internal/app/stateloaded_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,12 @@ func TestStateLoaded(t *testing.T) {
_, ok = model.(app.StateErrorModel)
assert.Truef(t, ok, "%s", model)
})

t.Run("version_printed", func(t *testing.T) {
t.Parallel()

assert.Contains(t, model.View(), testVersion)
})
}

func TestStateLoadedQuit(t *testing.T) {
Expand Down