# HG changeset patch # User Sean E. Russell # Date 1462044542 14400 # Sat Apr 30 15:29:02 2016 -0400 # Node ID 36915a38f3c7f92747e9ef66019111b6f411bc6c # Parent 35a6a483396323c3caadcc9d5e03820cf13572cd Adds force-include; fixes bug in text width diff --git a/cmd/orgchart/main.go b/cmd/orgchart/main.go --- a/cmd/orgchart/main.go +++ b/cmd/orgchart/main.go @@ -38,6 +38,7 @@ cssfile := goopt.String([]string{"-y"}, "", "CSS file to embed") ands := goopt.Strings([]string{"--ex-and"}, "", "Column,Value -- Exclude (and -- all ands must match") ors := goopt.Strings([]string{"--ex-or"}, "", "Column,Value -- Exclude (or -- any ors may match") + incls := goopt.Strings([]string{"--ex-incl"}, "", "Column,Value -- Include (overrides and and or excludes)") goopt.Version = "" goopt.Summary = "Organization chart generator" goopt.Parse(nil) @@ -82,7 +83,7 @@ fmt.Println(err.Error()) os.Exit(1) } - exc, err := makeExcludes(*ands, *ors) + exc, err := makeExcludes(*ands, *ors, *incls) if err != nil { fmt.Println(err.Error()) os.Exit(1) @@ -233,11 +234,21 @@ } type Excludes struct { - ands []Exclude - ors []Exclude + ands []Exclude + ors []Exclude + incls []Exclude } func (ex Excludes) Match(cols []string) bool { + // If any INCLUDEs match, they win + for _, e := range ex.incls { + if e.idx < len(cols) { + if e.match == cols[e.idx] { + return false + } + } + } + // If any exclude ORs match, exclude for _, e := range ex.ors { if e.idx < len(cols) { if e.match == cols[e.idx] { @@ -245,6 +256,7 @@ } } } + // If all exclude ANDs match, exclude matches := len(ex.ands) > 0 for _, e := range ex.ands { if e.idx < len(cols) { @@ -258,11 +270,12 @@ return matches } -func makeExcludes(ands, ors []string) (Excludes, error) { +func makeExcludes(ands, ors, incls []string) (Excludes, error) { var err error rv := Excludes{} rv.ands, err = breakUp(ands) rv.ors, err = breakUp(ors) + rv.incls, err = breakUp(incls) return rv, err } diff --git a/cmd/orgchart/main_test.go b/cmd/orgchart/main_test.go --- a/cmd/orgchart/main_test.go +++ b/cmd/orgchart/main_test.go @@ -61,7 +61,7 @@ C2,B2` b := bytes.NewBufferString(s) rx := make(Ruleset, 0) - exc, _ := makeExcludes([]string{}, []string{}) + exc, _ := makeExcludes([]string{}, []string{}, []string{}) ps, er := makePeople(b, exc, []int{}, rx) if er != nil { assert.Fail(t, "failed to parse: %s", er.Error()) @@ -113,7 +113,7 @@ C3B2,B2` b := bytes.NewBufferString(s) rx := make(Ruleset, 0) - exc, _ := makeExcludes([]string{}, []string{}) + exc, _ := makeExcludes([]string{}, []string{}, []string{}) ps, er := makePeople(b, exc, []int{}, rx) if er != nil { assert.Fail(t, "failed to parse: %s", er.Error()) @@ -139,7 +139,7 @@ D2,C2B3` b = bytes.NewBufferString(s) rx = make(Ruleset, 0) - exc, _ = makeExcludes([]string{}, []string{}) + exc, _ = makeExcludes([]string{}, []string{}, []string{}) ps, er = makePeople(b, exc, []int{}, rx) if er != nil { assert.Fail(t, "failed to parse: %s", er.Error()) @@ -164,7 +164,7 @@ if er != nil { assert.Fail(t, er.Error()) } - exc, _ := makeExcludes([]string{}, []string{}) + exc, _ := makeExcludes([]string{}, []string{}, []string{}) ps, er := makePeople(b, exc, []int{}, rx) if er != nil { assert.Fail(t, er.Error()) @@ -182,17 +182,19 @@ ex1, er := makeExcludes( []string{"0,TRUE", "1,TRUE"}, // AND []string{"2,TRUE", "3,TRUE"}, // OR + []string{"4,TRUE"}, // INCLUDE ) if er != nil { assert.Fail(t, "failed to parse: %s", er.Error()) } - assert.True(t, ex1.Match([]string{"", "", "", "TRUE"})) - assert.True(t, ex1.Match([]string{"", "", "TRUE", ""})) - assert.True(t, ex1.Match([]string{"TRUE", "TRUE", "", ""})) - assert.True(t, ex1.Match([]string{"TRUE", "TRUE", "", "TRUE"})) - assert.False(t, ex1.Match([]string{"", "", "", ""})) - assert.False(t, ex1.Match([]string{"TRUE", "", "", ""})) - assert.False(t, ex1.Match([]string{"", "TRUE", "", ""})) + assert.True(t, ex1.Match([]string{"", "", "", "TRUE", ""})) + assert.True(t, ex1.Match([]string{"", "", "TRUE", "", ""})) + assert.True(t, ex1.Match([]string{"TRUE", "TRUE", "", "", ""})) + assert.True(t, ex1.Match([]string{"TRUE", "TRUE", "", "TRUE", ""})) + assert.False(t, ex1.Match([]string{"", "", "", "", ""})) + assert.False(t, ex1.Match([]string{"TRUE", "", "", "", ""})) + assert.False(t, ex1.Match([]string{"", "TRUE", "", "", ""})) + assert.True(t, ex1.Match([]string{"TRUE", "TRUE", "", "TRUE", "TRUE"})) } func TestExclude(t *testing.T) { @@ -210,12 +212,14 @@ C2B3,B3,FALSE,TRUE, C3B3,B3,FALSE,FALSE, D1,C2B3,TRUE,TRUE,TRUE +D3,C2B3,TRUE,TRUE,TRUE D2,C2B3,TRUE,TRUE,FALSE` b := bytes.NewBufferString(s) rx := make(Ruleset, 0) ex1, er := makeExcludes( []string{"2,TRUE", "3,TRUE"}, // AND []string{"4,TRUE"}, // OR + []string{"0", "D3"}, // FORCE INCLUDE ) if er != nil { assert.Fail(t, "failed to parse: %s", er.Error()) @@ -242,8 +246,10 @@ foundCount += 1 case "C3B3": foundCount += 1 + case "D3": + fountCount += 1 } } } - assert.Equal(t, 4, foundCount) + assert.Equal(t, 5, foundCount) } diff --git a/cmd/orgchart/svg.go b/cmd/orgchart/svg.go --- a/cmd/orgchart/svg.go +++ b/cmd/orgchart/svg.go @@ -11,8 +11,8 @@ * Constants & global variables * **************************************************************************/ const ( - charW = 5 - padW = 30 + charW = 6 + padW = 25 gapW = 30 marginW = 20 gapH = 100 @@ -65,12 +65,15 @@ } func renderSVG(out io.Writer, rs Ranks, sup bool, css string) { + if sup { + rs = addSuperiors(rs) + } setBoxH(rs) setBoxW(rs) c := svg.New(out) bgW = boxW + gapW pageWidth := rs.width() * bgW - h := height(rs, sup) + h := height(rs) c.Start(pageWidth, h) c.Filter("blur") c.FeGaussianBlur(svg.Filterspec{In: "SourceAlpha", Result: "blur"}, 5, 5) @@ -110,9 +113,6 @@ b := make(map[string]Box) xoff := marginW - if sup { - rs = addSuperiors(rs) - } for _, p := range rs[0] { drawOrg(c, xoff, marginH/2, p, b, true, false, sup) xoff += width(p) @@ -245,11 +245,8 @@ return p.Width() * (boxW + gapW) } -func height(rs Ranks, s bool) int { +func height(rs Ranks) int { high := rs.height() - if s { - high += 1 - } return (high * boxH) + ((high - 1) * (gapH / 2)) + marginH }