Skip to content

Commit

Permalink
鈾伙笍 refactor: move ProcessMDFile from pkg to cmd/mdfmt
Browse files Browse the repository at this point in the history
  • Loading branch information
elliotxx committed Feb 25, 2022
1 parent 69821d4 commit fb1f65f
Show file tree
Hide file tree
Showing 6 changed files with 228 additions and 214 deletions.
6 changes: 3 additions & 3 deletions Makefile
Expand Up @@ -19,18 +19,18 @@ build-darwin: gen-version ## Build for MacOS
-rm -rf ./build/darwin
GOOS=darwin GOARCH=amd64 CGO_ENABLED=0 \
go build -o ./build/darwin/$(APPROOT) \
./cmd/mdfmt/main.go
./cmd/mdfmt

.PHONY: build-linux
build-linux: gen-version ## Build for Linux
-rm -rf ./build/linux
GOOS=linux GOARCH=amd64 CGO_ENABLED=0 \
go build -o ./build/linux/$(APPROOT) \
./cmd/mdfmt/main.go
./cmd/mdfmt

.PHONY: build-windows
build-windows: gen-version ## Build for Windows
-rm -rf ./build/windows
GOOS=windows GOARCH=amd64 CGO_ENABLED=0 \
go build -o ./build/windows/$(APPROOT).exe \
./cmd/mdfmt/main.go
./cmd/mdfmt
15 changes: 1 addition & 14 deletions cmd/mdfmt/main.go
Expand Up @@ -51,19 +51,6 @@ var (
`))
)

type Options struct {
ShowVersion bool
Write bool
Diff bool
List bool
Verbose bool
}

// NewOptions returns a new Options instance
func NewOptions() *Options {
return &Options{}
}

func configureCLI() *cobra.Command {
o := NewOptions()
rootCmd := &cobra.Command{
Expand Down Expand Up @@ -108,7 +95,7 @@ func configureCLI() *cobra.Command {
}()

if d != nil && !d.IsDir() && md.IsMarkdownFile(path) {
err2 = md.ProcessMDFile(path, o.Write, o.Diff, o.List)
err2 = ProcessMDFile(path, o.Write, o.Diff, o.List)
}
return
})
Expand Down
140 changes: 140 additions & 0 deletions cmd/mdfmt/options.go
@@ -0,0 +1,140 @@
package main

import (
"bytes"
"fmt"
"os"
"path/filepath"

"github.com/elliotxx/mdfmt/pkg/md"
"github.com/pkg/diff"
"github.com/pkg/diff/write"
)

// fdSem guards the number of concurrently-open file descriptors.
//
// For now, this is arbitrarily set to 200, based on the observation that many
// platforms default to a kernel limit of 256. Ideally, perhaps we should derive
// it from rlimit on platforms that support that system call.
//
// File descriptors opened from outside of this package are not tracked,
// so this limit may be approximate.
var fdSem = make(chan bool, 200)

type Options struct {
ShowVersion bool
Write bool
Diff bool
List bool
Verbose bool
}

// NewOptions returns a new Options instance
func NewOptions() *Options {
return &Options{}
}

// ProcessMDFile formats markdown file.
func ProcessMDFile(filePath string, write, diff, list bool) error {
// Get Reader and Source
source, err := os.ReadFile(filePath)
if err != nil {
return err
}

in := bytes.NewReader(source)

// Get Writer and Target
out := bytes.NewBuffer([]byte{})

err = md.FormatMarkdown(in, out)
if err != nil {
return err
}

target := out.Bytes()

if !bytes.Equal(source, target) {
// List
if list {
os.Stdout.WriteString(filePath + "\n")
}
// Write
if write {
info, err := os.Stat(filePath)
if err != nil {
return err
}

fdSem <- true

err = os.WriteFile(filePath, target, info.Mode().Perm())

<-fdSem

if err != nil {
return err
}
}

// Diff
if diff {
data, err := diffWithReplaceTempFile(source, target, filePath)
if err != nil {
return fmt.Errorf("computing diff: %s", err)
}

fmt.Fprintf(os.Stdout, "diff -u %s %s\n", filepath.ToSlash(filePath+".orig"), filepath.ToSlash(filePath))
os.Stdout.Write(data)
}
}

if !write && !diff && !list {
_, err = os.Stdout.Write(target)
}

return err
}

func diffWithReplaceTempFile(b1, b2 []byte, filename string) ([]byte, error) {
data := bytes.NewBufferString("")
err := diff.Text("origin", "target", b1, b2, data, write.TerminalColor())

if len(data.Bytes()) > 0 {
return replaceTempFilename(data.Bytes(), filename)
}

return data.Bytes(), err
}

// replaceTempFilename replaces temporary filenames in diff with actual one.
//
// --- /tmp/gofmt316145376 2017-02-03 19:13:00.280468375 -0500
// +++ /tmp/gofmt617882815 2017-02-03 19:13:00.280468375 -0500
// ...
// ->
// --- path/to/file.md.orig 2017-02-03 19:13:00.280468375 -0500
// +++ path/to/file.md 2017-02-03 19:13:00.280468375 -0500
// ...
func replaceTempFilename(diff []byte, filename string) ([]byte, error) {
bs := bytes.SplitN(diff, []byte{'\n'}, 3)
if len(bs) < 3 {
return nil, fmt.Errorf("got unexpected diff for %s", filename)
}
// Preserve timestamps.
var t0, t1 []byte
if i := bytes.LastIndexByte(bs[0], '\t'); i != -1 {
t0 = bs[0][i:]
}

if i := bytes.LastIndexByte(bs[1], '\t'); i != -1 {
t1 = bs[1][i:]
}

// Always print filepath with slash separator.
f := filepath.ToSlash(filename)
bs[0] = []byte(fmt.Sprintf("--- %s%s", f+".orig", t0))
bs[1] = []byte(fmt.Sprintf("+++ %s%s", f, t1))

return bytes.Join(bs, []byte{'\n'}), nil
}
84 changes: 84 additions & 0 deletions cmd/mdfmt/options_test.go
@@ -0,0 +1,84 @@
package main

import (
"os"
"testing"
)

func TestProcessMDFile(t *testing.T) {
mockMDFile := "./testdata/hello-temp.md"
_ = os.WriteFile(mockMDFile, []byte("# Hello World"), 0644)

defer os.Remove(mockMDFile)

type args struct {
filePath string
write bool
diff bool
list bool
}

tests := []struct {
name string
args args
wantErr bool
}{
{
name: "happy-path",
args: args{
filePath: "./testdata/hello.md",
write: false,
diff: false,
list: false,
},
wantErr: false,
},
{
name: "md-file-not-exist",
args: args{
filePath: "./testdata/hello-not-exist.md",
write: true,
diff: false,
list: false,
},
wantErr: true,
},
{
name: "diff",
args: args{
filePath: "./testdata/hello.md",
write: false,
diff: true,
list: false,
},
wantErr: false,
},
{
name: "write",
args: args{
filePath: mockMDFile,
write: true,
diff: false,
list: false,
},
wantErr: false,
},
{
name: "list",
args: args{
filePath: "./testdata/hello.md",
write: false,
diff: false,
list: true,
},
wantErr: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if err := ProcessMDFile(tt.args.filePath, tt.args.write, tt.args.diff, tt.args.list); (err != nil) != tt.wantErr {
t.Errorf("ProcessMDFile() error = %v, wantErr %v", err, tt.wantErr)
}
})
}
}

0 comments on commit fb1f65f

Please sign in to comment.