Improvements to display code
Now switchable, detects terminal. Don't be weird with tabs. Known issues are not being themeable and bold match output stopping if colours are used inside.
This commit is contained in:
		
							parent
							
								
									b438aef169
								
							
						
					
					
						commit
						4fd3ae4c7e
					
				|  | @ -0,0 +1,54 @@ | ||||||
|  | package main | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"fmt" | ||||||
|  | 
 | ||||||
|  | 	"github.com/logrusorgru/aurora/v4" | ||||||
|  | 	"golang.org/x/sys/unix" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | type Display struct { | ||||||
|  | 	a *aurora.Aurora | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func NewDisplay(noColour bool) *Display { | ||||||
|  | 	if _, err := unix.IoctlGetTermios(1, unix.TCGETS); err != nil { | ||||||
|  | 		noColour = true | ||||||
|  | 	} | ||||||
|  | 	a := aurora.New(aurora.WithColors(!noColour)) | ||||||
|  | 	return &Display{ | ||||||
|  | 		a: a, | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (d *Display) Filename(name string) aurora.Value { | ||||||
|  | 	return d.a.BgBlue(d.a.White(name)) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (d *Display) LineNumber(lineNum int) aurora.Value { | ||||||
|  | 	return d.a.Green(lineNum) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (d *Display) Match(text string) aurora.Value { | ||||||
|  | 	return d.a.Bold(text) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (d *Display) TruncatedMarker() aurora.Value { | ||||||
|  | 	return d.a.Magenta("…") | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (d *Display) TruncatedBytes(byteCount int) aurora.Value { | ||||||
|  | 	return d.a.Faint(fmt.Sprintf("(%d bytes)", byteCount)) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (d *Display) BadUTF8Char() aurora.Value { | ||||||
|  | 	return d.a.Magenta("\uFFFD") | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (d *Display) CarriageReturn() aurora.Value { | ||||||
|  | 	return d.a.Magenta(`\r`) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (d *Display) UnprintableChar() aurora.Value { | ||||||
|  | 	return d.a.Magenta(`·`) | ||||||
|  | } | ||||||
							
								
								
									
										44
									
								
								main.go
								
								
								
								
							
							
						
						
									
										44
									
								
								main.go
								
								
								
								
							|  | @ -14,14 +14,12 @@ import ( | ||||||
| 	"unicode" | 	"unicode" | ||||||
| 	"unicode/utf8" | 	"unicode/utf8" | ||||||
| 
 | 
 | ||||||
| 	"github.com/logrusorgru/aurora/v4" |  | ||||||
| 	"github.com/spf13/cobra" | 	"github.com/spf13/cobra" | ||||||
| 	"golang.org/x/sys/unix" | 	"golang.org/x/sys/unix" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| // TODO:
 | // TODO:
 | ||||||
| //  - option to squelch aurora output
 | //  - bold of escaped output doesn't work
 | ||||||
| //  - detect if terminal
 |  | ||||||
| //  - binary file detection
 | //  - binary file detection
 | ||||||
| //  - long-line / minified-file detection
 | //  - long-line / minified-file detection
 | ||||||
| //  - ignore files by extension (or glob?)
 | //  - ignore files by extension (or glob?)
 | ||||||
|  | @ -65,6 +63,9 @@ var ( | ||||||
| 	ignoreList   []string | 	ignoreList   []string | ||||||
| 	ignoreMap    map[string]struct{} | 	ignoreMap    map[string]struct{} | ||||||
| 	ignoreCase   bool | 	ignoreCase   bool | ||||||
|  | 	noColour     bool | ||||||
|  | 	display      *Display | ||||||
|  | 	matchedAny   bool | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| func init() { | func init() { | ||||||
|  | @ -72,9 +73,12 @@ func init() { | ||||||
| 	rootCmd.Flags().StringSliceVarP(&searchFixed, "fixed", "Q", nil, "pattern to match (fixed string)") | 	rootCmd.Flags().StringSliceVarP(&searchFixed, "fixed", "Q", nil, "pattern to match (fixed string)") | ||||||
| 	rootCmd.Flags().StringSliceVarP(&ignoreList, "exclude", "x", []string{".git"}, "files/directories to exclude") | 	rootCmd.Flags().StringSliceVarP(&ignoreList, "exclude", "x", []string{".git"}, "files/directories to exclude") | ||||||
| 	rootCmd.Flags().BoolVarP(&ignoreCase, "ignore-case", "i", false, "make all searches case insensitive") | 	rootCmd.Flags().BoolVarP(&ignoreCase, "ignore-case", "i", false, "make all searches case insensitive") | ||||||
|  | 	rootCmd.Flags().BoolVarP(&noColour, "no-colour", "C", false, "disable colour output") | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func run(c *cobra.Command, args []string) error { | func run(c *cobra.Command, args []string) error { | ||||||
|  | 	display = NewDisplay(noColour) | ||||||
|  | 
 | ||||||
| 	if len(searchRegexp) == 0 && len(searchFixed) == 0 { | 	if len(searchRegexp) == 0 && len(searchFixed) == 0 { | ||||||
| 		if len(args) == 0 { | 		if len(args) == 0 { | ||||||
| 			return errors.New("no pattern specified") | 			return errors.New("no pattern specified") | ||||||
|  | @ -196,11 +200,16 @@ func search(path string) error { | ||||||
| 
 | 
 | ||||||
| 		if !printedHeader { | 		if !printedHeader { | ||||||
| 			printedHeader = true | 			printedHeader = true | ||||||
| 			fmt.Println(aurora.BgBlue(aurora.Bold(path))) | 			if !matchedAny { | ||||||
|  | 				matchedAny = true | ||||||
|  | 			} else { | ||||||
|  | 				fmt.Println("") | ||||||
|  | 			} | ||||||
|  | 			fmt.Println(display.Filename(path)) | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		b.Reset() | 		b.Reset() | ||||||
| 		fmt.Fprintf(&b, "%4d: ", aurora.Gray(16, lineNum)) | 		fmt.Fprintf(&b, "%4d: ", display.LineNumber(lineNum)) | ||||||
| 
 | 
 | ||||||
| 		if loc[0] < 128 { | 		if loc[0] < 128 { | ||||||
| 			escape(&b, line[0:loc[0]]) | 			escape(&b, line[0:loc[0]]) | ||||||
|  | @ -213,14 +222,15 @@ func search(path string) error { | ||||||
| 				start++ | 				start++ | ||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
| 			fmt.Fprintf(&b, "(%d bytes)%s", start, aurora.Magenta("…")) | 			b.WriteString(display.TruncatedBytes(start).String()) | ||||||
|  | 			b.WriteString(display.TruncatedMarker().String()) | ||||||
| 			escape(&b, line[start:loc[0]]) | 			escape(&b, line[start:loc[0]]) | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		if loc[1]-loc[0] < 128 { | 		if loc[1]-loc[0] < 128 { | ||||||
| 			b2.Reset() | 			b2.Reset() | ||||||
| 			escape(&b2, line[loc[0]:loc[1]]) | 			escape(&b2, line[loc[0]:loc[1]]) | ||||||
| 			b.WriteString(aurora.Bold(b2.String()).String()) | 			b.WriteString(display.Match(b2.String()).String()) | ||||||
| 
 | 
 | ||||||
| 			if loc[1]+128 > len(line) { | 			if loc[1]+128 > len(line) { | ||||||
| 				escape(&b, line[loc[1]:]) | 				escape(&b, line[loc[1]:]) | ||||||
|  | @ -233,7 +243,8 @@ func search(path string) error { | ||||||
| 					end-- | 					end-- | ||||||
| 				} | 				} | ||||||
| 				escape(&b, line[loc[1]:end]) | 				escape(&b, line[loc[1]:end]) | ||||||
| 				fmt.Fprintf(&b, "(%d bytes)%s", len(line)-end, aurora.Magenta("…")) | 				b.WriteString(display.TruncatedBytes(len(line) - end).String()) | ||||||
|  | 				b.WriteString(display.TruncatedMarker().String()) | ||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
| 		} else { | 		} else { | ||||||
|  | @ -247,8 +258,9 @@ func search(path string) error { | ||||||
| 
 | 
 | ||||||
| 			b2.Reset() | 			b2.Reset() | ||||||
| 			escape(&b2, line[loc[0]:end]) | 			escape(&b2, line[loc[0]:end]) | ||||||
| 			b.WriteString(aurora.Bold(b2.String()).String()) | 			b.WriteString(display.Match(b2.String()).String()) | ||||||
| 			fmt.Fprintf(&b, "%s(%d bytes)", aurora.Magenta("…"), len(line)-end) | 			b.WriteString(display.TruncatedMarker().String()) | ||||||
|  | 			b.WriteString(display.TruncatedBytes(len(line) - end).String()) | ||||||
| 
 | 
 | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
|  | @ -282,19 +294,17 @@ func escape(b *strings.Builder, s []byte) { | ||||||
| 
 | 
 | ||||||
| 		switch { | 		switch { | ||||||
| 		case r == utf8.RuneError && size == 1: | 		case r == utf8.RuneError && size == 1: | ||||||
| 			b.WriteString(aurora.Magenta("\uFFFD").String()) | 			b.WriteString(display.BadUTF8Char().String()) | ||||||
| 
 | 
 | ||||||
| 		case r == '\r': | 		case r == '\r': | ||||||
| 			b.WriteString(aurora.Magenta(`\r`).String()) | 			b.WriteString(display.CarriageReturn().String()) | ||||||
| 
 | 
 | ||||||
| 		case r == '\t': | 		case r == '\t', | ||||||
| 			b.WriteString(aurora.Magenta(`\t`).String()) | 			unicode.IsPrint(r): | ||||||
| 
 |  | ||||||
| 		case unicode.IsPrint(r): |  | ||||||
| 			b.WriteRune(r) | 			b.WriteRune(r) | ||||||
| 
 | 
 | ||||||
| 		default: | 		default: | ||||||
| 			b.WriteString(aurora.Magenta(".").String()) | 			b.WriteString(display.UnprintableChar().String()) | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue