-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 0b818dc
Showing
15 changed files
with
578 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
package commands | ||
|
||
import ( | ||
"errors" | ||
"fmt" | ||
) | ||
|
||
// A Command executes a predefined procedure established before its creation. | ||
type Command interface { | ||
Execute() error | ||
} | ||
|
||
type setup interface { | ||
Parse(args []string) Command | ||
} | ||
|
||
// Parse creates a valid Command from args. The expected format | ||
// of args is: "<subcommand> <arguments...>". If an error occurs and a | ||
// valid command can not be constructed, a new command is created explaining | ||
// the error and suggesting the "lawyer help" command. | ||
func Parse(args []string) Command { | ||
if len(args) == 0 { | ||
return suggestHelp(errors.New("no subcommand specified")) | ||
} | ||
|
||
setup, err := getSetup(args[0]) | ||
if err != nil { | ||
return suggestHelp(err) | ||
} | ||
|
||
return setup.Parse(args[1:]) | ||
} | ||
|
||
func getSetup(command string) (setup, error) { | ||
switch command { | ||
case "indict": | ||
return setupForIndict(), nil | ||
case "help", "--help", "-h": | ||
return setupForHelp(), nil | ||
default: | ||
return nil, fmt.Errorf("unknown command \"%v\"", command) | ||
} | ||
} | ||
|
||
func suggestHelp(err error) suggestHelpCommand { | ||
return suggestHelpCommand{ | ||
error: err, | ||
} | ||
} | ||
|
||
type suggestHelpCommand struct { | ||
error | ||
} | ||
|
||
func (suggHelp suggestHelpCommand) Execute() error { | ||
fmt.Println("invalid command: " + suggHelp.error.Error()) | ||
fmt.Println("use \"lawyer help\" to show usage information") | ||
return nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
package commands | ||
|
||
import ( | ||
"testing" | ||
|
||
"github.com/stretchr/testify/require" | ||
) | ||
|
||
func TestParsesCommands(t *testing.T) { | ||
path := "tes.txt" | ||
|
||
var cases = []struct { | ||
in []string | ||
want Command | ||
}{ | ||
{ | ||
in: []string{"indict", path}, | ||
want: &indictCommand{ | ||
paths: []string{path}, | ||
lawPath: "", | ||
}, | ||
}, | ||
} | ||
|
||
for _, cas := range cases { | ||
got := Parse(cas.in) | ||
require.Equal(t, cas.want, got) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
package commands | ||
|
||
import ( | ||
"fmt" | ||
|
||
"./manuals" | ||
) | ||
|
||
type helpCommand struct { | ||
subject string | ||
} | ||
|
||
func (help helpCommand) Execute() (err error) { | ||
if help.subject == "" { | ||
printSummary() | ||
} else { | ||
err = printManual(help.subject) | ||
} | ||
|
||
return err | ||
} | ||
|
||
func printSummary() { | ||
fmt.Println("Lawyer is a tool for maintaining copyright headers in source code.") | ||
fmt.Println() | ||
printUsage() | ||
fmt.Println() | ||
printCommands() | ||
fmt.Println() | ||
printTopics() | ||
} | ||
|
||
func printUsage() { | ||
fmt.Print("Usage:") | ||
fmt.Println() | ||
fmt.Println("\tlawyer <command> [arguments]") | ||
} | ||
|
||
func printCommands() { | ||
fmt.Println("The commands are:") | ||
fmt.Println() | ||
for command, manual := range manuals.CommandManualMap { | ||
fmt.Printf("\t%-10v %v\n", command, manual.Summary) | ||
} | ||
fmt.Println() | ||
fmt.Println("Use \"go help <command>\" for more information about a command.") | ||
} | ||
|
||
func printTopics() { | ||
fmt.Println("Additional help topics:") | ||
fmt.Println() | ||
for topic, manual := range manuals.TopicManualMap { | ||
fmt.Printf("\t%-10v %v\n", topic, manual.Summary) | ||
} | ||
fmt.Println() | ||
fmt.Println("Use \"go help <topic>\" for more information about that topic.") | ||
} | ||
|
||
func printManual(command string) error { | ||
foundManual := manuals.EntireManualMap[command] | ||
|
||
if foundManual == *new(manuals.Manual) { | ||
return fmt.Errorf("no manual found for \"%v\"", command) | ||
} | ||
|
||
fmt.Println(foundManual.Content) | ||
return nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
package commands | ||
|
||
import ( | ||
"errors" | ||
"flag" | ||
) | ||
|
||
type helpSetup struct { | ||
flags *flag.FlagSet | ||
print bool | ||
} | ||
|
||
func setupForHelp() setup { | ||
return new(helpSetup) | ||
} | ||
|
||
func (setup helpSetup) Parse(args []string) Command { | ||
switch len(args) { | ||
case 0: | ||
return new(helpCommand) | ||
case 1: | ||
return helpCommand{ | ||
subject: args[0], | ||
} | ||
default: | ||
return suggestHelp(errors.New("too many arguments")) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
package commands | ||
|
||
import ( | ||
"fmt" | ||
"os" | ||
"regexp" | ||
|
||
"../laws" | ||
"../trial" | ||
"github.com/TwinProduction/go-color" | ||
) | ||
|
||
type indictCommand struct { | ||
paths []string | ||
lawPath string | ||
} | ||
|
||
func (indictment *indictCommand) Execute() error { | ||
law, err := laws.RetrieveFrom(indictment.lawPath) | ||
if err != nil { | ||
return fmt.Errorf("unable to retrieve law contents\n%w", err) | ||
} | ||
|
||
for _, path := range indictment.paths { | ||
err := indict(path, law.Expected) | ||
|
||
if err != nil { | ||
fmt.Print(color.Yellow) | ||
fmt.Printf("%v dismissed\n", path) | ||
fmt.Println(err.Error()) | ||
fmt.Print(color.Reset) | ||
} | ||
} | ||
|
||
fmt.Println("indictment complete") | ||
return nil | ||
} | ||
|
||
func indict(path string, expected regexp.Regexp) error { | ||
file, err := os.Open(path) | ||
if err != nil { | ||
return err | ||
} | ||
defer file.Close() | ||
|
||
innocent, evidence := trial.Conduct(expected, file) | ||
fmt.Printf("%v is %v\n", path, trial.ToVerdict(innocent)) | ||
|
||
if !innocent { | ||
fmt.Println("\n" + trial.FormatEvidence(evidence)) | ||
} | ||
|
||
return nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
package commands | ||
|
||
import ( | ||
"errors" | ||
"flag" | ||
) | ||
|
||
type indictSetup struct { | ||
flags *flag.FlagSet | ||
} | ||
|
||
func setupForIndict() indictSetup { | ||
flags := flag.NewFlagSet("indict", flag.ExitOnError) | ||
|
||
return indictSetup{ | ||
flags: flags, | ||
} | ||
} | ||
|
||
func (setup indictSetup) Parse(args []string) Command { | ||
setup.flags.Parse(args) | ||
|
||
paths := setup.flags.Args() | ||
if len(paths) == 0 { | ||
return suggestHelp( | ||
errors.New("defendant path(s) required for indictment")) | ||
} | ||
|
||
return &indictCommand{ | ||
paths: paths, | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
package manuals | ||
|
||
var indictManual Manual = Manual{ | ||
Summary: "verify files have the expected header", | ||
Content: `Reads the top 10 lines (the header) of every file found matching | ||
<file_pattern> and compares them to the regular expression of | ||
"expected" inside the law file. Enter "lawyer help law" for more | ||
information on the law file. | ||
Usage: | ||
lawyer indict <file_pattern> | ||
Arguments: | ||
<file_pattern> file(s) to indict | ||
If the header does not match the expected header, the header | ||
is printed as evidence and the file is marked guilty.`, | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
package manuals | ||
|
||
var lawManual Manual = Manual{ | ||
Summary: "law file", | ||
Content: `The "Law File" is a YAML file that describes the possible values | ||
of a file header. Here is an example Law File: | ||
expected: ^// © ABC Company 1996. All rights reserved.$ | ||
Explanation: | ||
expected Regular expression of the expected file header. | ||
The Law File should be located in the current directory from which lawyer is | ||
executed with the name "law" and the "yml" or "yaml" extension. | ||
Also note that YAML has multi-line support for file headers that require | ||
multiple lines or even newlines after multiple lines. See the YAML specfication | ||
for more details.`, | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
package manuals | ||
|
||
// Manual represents the coupling of the one-line summary and detailed | ||
// explaination of a cli command or general Lawyer topic. | ||
type Manual struct { | ||
Summary string | ||
Content string | ||
} | ||
|
||
// ManualMap represents a one-to-one mapping between a cli help keyword | ||
// (ex. lawyer help "indict") and the corresponding Manual. | ||
type ManualMap = map[string]Manual | ||
|
||
// CommandManualMap is a list of all cli command Manuals mapped by their | ||
// corresponding help keywords. | ||
var CommandManualMap = ManualMap{ | ||
"help": Manual{"print this help page", "stop repeating yourself"}, | ||
"indict": indictManual, | ||
} | ||
|
||
// TopicManualMap is a list of all help topics mapped by their corresponding | ||
// help keywords. | ||
var TopicManualMap = ManualMap{ | ||
"law": lawManual, | ||
} | ||
|
||
// EntireManualMap is a list of all cli command Manuals AND help topic mapped | ||
// by their corresponding help keywords. | ||
var EntireManualMap = merge(CommandManualMap, TopicManualMap) | ||
|
||
func merge(a, b ManualMap) ManualMap { | ||
for key, value := range a { | ||
b[key] = value | ||
} | ||
return b | ||
} |
Oops, something went wrong.