Skip to content

Commit

Permalink
Merge pull request #13 from myitcv/pkgconcat
Browse files Browse the repository at this point in the history
cmd/pkgconcat: initial commit
  • Loading branch information
myitcv authored Apr 11, 2018
2 parents 9879d50 + 195b0c9 commit 517b5a6
Show file tree
Hide file tree
Showing 25 changed files with 1,273 additions and 185 deletions.
4 changes: 4 additions & 0 deletions _scripts/run_tests.sh
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,10 @@ fi

export PATH=$GOPATH/bin:$PATH

# work out a better way of priming the build tools
pushd cmd/pkgconcat > /dev/null
$go install .
popd > /dev/null

# get all packages that do not belong to a module that has its
# own _scripts/run_tests.sh file
Expand Down
213 changes: 213 additions & 0 deletions _tmpls/cliflag/cliflag.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,213 @@
package main

import (
"bufio"
"flag"
"fmt"
"os"
"strings"
"unicode"
"unicode/utf8"

"golang.org/x/text/unicode/norm"
)

var (
usage string
)

func setupAndParseFlags(msg string) {
flag.Usage = func() {
res := new(strings.Builder)
fmt.Fprint(res, msg)

// this feels a bit gross...
flag.CommandLine.SetOutput(res)
flag.PrintDefaults()
res.WriteString("\n")
res.WriteString("\n")

fmt.Fprint(os.Stderr, foldOnSpaces(res.String(), 80))

os.Exit(0)
}
flag.Parse()

flag.CommandLine.SetOutput(os.Stderr)
}

func foldOnSpaces(input string, width int) string {
var carry string
var indent string // the indent (if there is one) when we carry

sc := bufio.NewScanner(strings.NewReader(input))

res := new(strings.Builder)
first := true

Line:
for {
carried := carry != ""
if !carried {
if !sc.Scan() {
break
}

if first {
first = false
} else {
res.WriteString("\n")
}

carry = sc.Text()

// caclculate the indent
iBuilder := new(strings.Builder)

for _, r := range carry {
if !unicode.IsSpace(r) {
break
}
iBuilder.WriteRune(r)
}

indent = iBuilder.String()

// now strip the space on the line
carry = strings.TrimSpace(carry)
}

if len(carry) == 0 {
continue
}

// we always strip the indent - so write it back
res.WriteString(indent)

// fast path where number of bytes is less than width
// nothing to calculate in terms of width
// TODO is this safe?
if len(indent)+len(carry) < width {
res.WriteString(carry)
carry = ""
continue
}

lastSpace := -1

var ia norm.Iter
ia.InitString(norm.NFD, carry)
nc := len(indent)

// TODO handle this better
if nc >= width {
fatalf("cannot foldOnSpaces where indent is greater than width")
}

var postSpace string

Space:
for !ia.Done() {
prevPos := ia.Pos()
nbs := ia.Next()
r, rw := utf8.DecodeRune(nbs)
if rw != len(nbs) {
fatalf("didn't expect a multi-rune normalisation response: %v", string(nbs))
}

nc++

// do we have a space? If so there should only be a single rune
spaceCount := 0

if isSplitter(r) {
spaceCount++
}

switch spaceCount {
case 0:
// we can't split - keep going
if lastSpace == -1 {
res.WriteRune(r)
continue Space
}

// so at this point we know we have previously seen
// a space so nc cannot have previously have been == w
if nc == width {
// we are about to exceed the limit; write a new line
// to our output then put postSpace + prevPos: into carry
// remembering that postSpace will have a space on the
// left so we need to trim it
res.WriteString("\n")
carry = strings.TrimLeftFunc(postSpace+carry[prevPos:], unicode.IsSpace)
continue Line
}

// so the only thing left to do is add to postSpace
postSpace += string(r)
continue Space
case 1:
// we have hit a space; if we are already
// over the limit we want to drop the space
// and set carry to be the left-space-trimmed
// remainder

res.WriteString(postSpace)

switch {
case nc == width:
res.WriteRune(r)
fallthrough
case nc > width:
res.WriteString("\n")
carry = strings.TrimLeftFunc(carry[ia.Pos():], unicode.IsSpace)
// indent remains as it was
continue Line
}

// we still have capacity
res.WriteRune(r)

// otherwise we are still ok... move our last space
// pointer up, print anything we had from the previous
// last space and continue
lastSpace = nc
postSpace = ""
continue Space
default:
fatalf("is this even possible?")
}
}

// we exhausted the line
carry = ""
}

if err := sc.Err(); err != nil {
fatalf("failed to scan in foldOnSpaces: %v", err)
}

return res.String()
}

func isSplitter(r rune) bool {
if unicode.IsSpace(r) {
return true
}

switch r {
case '/':
return true
}

return false
}

func fatalf(format string, args ...interface{}) {
if format[len(format)-1] != '\n' {
format += "\n"
}
fmt.Fprintf(os.Stderr, format, args...)
os.Exit(1)
}
22 changes: 18 additions & 4 deletions cmd/mdreplace/README.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,20 @@
<!-- __JSON: go list -json .
## `{{ filepathBase .ImportPath}}`
{{.Doc}}
```
go get -u {{.ImportPath}}
```
-->
## `mdreplace`

`mdreplace` is a tool to help you keep your markdown README/documentation current.
mdreplace is a tool to help you keep your markdown README/documentation current.

```
go get -u myitcv.io/cmd/mdreplace
```
<!-- END -->

_(will soon be available as a [`vgo` module](https://github.com/golang/go/issues/24301))_

Expand Down Expand Up @@ -40,13 +50,16 @@ hello world today
_To see this in action, look at the [source of the
`README.md`](https://raw.githubusercontent.com/myitcv/x/master/cmd/mdreplace/README.md) you are currently reading._


<!-- __TEMPLATE: sh -c "${DOLLAR}(go list -f '{{.ImportPath}}' | xargs basename) -h"
### Usage
<!-- __TEMPLATE: mdreplace -h
```
{{.}}
```
-->
### Usage

```
Usage:
Expand All @@ -56,10 +69,11 @@ Usage:
When called with no file arguments, mdreplace works with stdin
Flags:
-h show usage information
-strip
whether to strip special comments from the file
-w whether to write back to input files (cannot be used when reading from stdin)
-w whether to write back to input files (cannot be used when reading from
stdin)
```
<!-- END -->
Expand Down
14 changes: 8 additions & 6 deletions cmd/mdreplace/common_block.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import (
"strconv"
"strings"
"text/template"

"myitcv.io/cmd/mdreplace/internal/itemtype"
)

func (p *processor) processCommonBlock(prefix string, conv func([]byte) interface{}) procFn {
Expand All @@ -21,8 +23,8 @@ Args:
t := i.val

switch i.typ {
case itemArg:
case itemQuoteArg:
case itemtype.ItemArg:
case itemtype.ItemQuoteArg:
v, err := strconv.Unquote(i.val)
if err != nil {
p.errorf("failed to unquote %q: %v", i.val, err)
Expand Down Expand Up @@ -61,9 +63,9 @@ Args:
// together
tmpl := new(strings.Builder)

for p.curr.typ != itemCommEnd {
for p.curr.typ != itemtype.ItemCommEnd {
switch p.curr.typ {
case itemCodeFence, itemCode, itemText:
case itemtype.ItemCodeFence, itemtype.ItemCode, itemtype.ItemText:
tmpl.WriteString(p.curr.val)
default:
p.errorf("didn't expect to see a %v", p.curr.typ)
Expand All @@ -76,9 +78,9 @@ Args:

// again we can expect text or code fence blocks here; we are just
// going to ignore them.
for p.curr.typ != itemBlockEnd {
for p.curr.typ != itemtype.ItemBlockEnd {
switch p.curr.typ {
case itemCodeFence, itemCode, itemText:
case itemtype.ItemCodeFence, itemtype.ItemCode, itemtype.ItemText:
// noop
default:
p.errorf("didn't expect to see a %v", p.curr.typ)
Expand Down
34 changes: 0 additions & 34 deletions cmd/mdreplace/flag.go

This file was deleted.

Loading

0 comments on commit 517b5a6

Please sign in to comment.