Skip to content

Commit

Permalink
3 generate suisa list (#14)
Browse files Browse the repository at this point in the history
* Add `generate suisa` command

* Render the Suisa List

* Configure margin in setlist template

* docs: improve README
  • Loading branch information
laenzlinger authored Apr 1, 2024
1 parent 1ec70b1 commit 416fa70
Show file tree
Hide file tree
Showing 12 changed files with 147 additions and 31 deletions.
1 change: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ integration-test: clean docker-build
$(RUN) generate sheet --band-name Band --all
$(RUN) generate sheet --band-name Band "Grand Ole Opry"
$(RUN) generate list --band-name Band "Grand Ole Opry"
$(RUN) generate suisa --band-name Band "Grand Ole Opry"
ls -lart test/Repertoire/out

lint: ## lint source code
Expand Down
17 changes: 10 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,13 +49,16 @@ Repertoire.md file. See [example]{test/Repertoire/Band/Repertoire.md).
The Table must have a header row. The only mandatory column is the `Title` column which is used to refer to the song titles
for both `generte sheet` and `generate list`.

Optional columns used by default generate output.

| Column | Type | Used by command |
|-------------|-----------|-----------------|
| Title | Mandatory | list, cheat |
| Year | Optional | list |
| Description | Optional | list |
Optional columns used (by default) generate output.

| Column | Type | Used by command |
|-------------|-----------|--------------------|
| Title | Mandatory | list, cheat, suisa |
| Year | Optional | list, suisa |
| Description | Optional | list |
| Arranger | Optional | suisa |
| Composer | Optional | suisa |
| Duration | Optional | suisa |

The output columns can be selected by the `--include-columns` flag, but the order or the columns is defined by the input
Repertoire.md
Expand Down
2 changes: 2 additions & 0 deletions cmd/generate_setlist.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,10 +70,12 @@ func generateSetlist(gigName string) error {

content := rep.Filter(gig).
IncludeColumns(include...).
NoHeader().
Render()

data := tmpl.Data{
Title: gig.Name,
Margin: "0cm",
Content: template.HTML(content), //nolint: gosec // not a web application
}

Expand Down
87 changes: 87 additions & 0 deletions cmd/generate_suisa.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
/*
Copyright © 2024 Christof Laenzlinger <christof@laenzlinger.net>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package cmd

import (
"fmt"
"html/template"
"path/filepath"

"github.com/laenzlinger/setlist/internal/config"
"github.com/laenzlinger/setlist/internal/gig"
convert "github.com/laenzlinger/setlist/internal/html/pdf"
tmpl "github.com/laenzlinger/setlist/internal/html/template"
"github.com/laenzlinger/setlist/internal/repertoire"
"github.com/spf13/cobra"
"github.com/spf13/viper"
)

//nolint:gochecknoglobals // cobra is designed like this
var suisaCmd = &cobra.Command{
Use: "suisa",
Short: "Generate a Suisa list",
Args: cobra.MatchAll(cobra.ExactArgs(1), cobra.OnlyValidArgs),
Long: `Generates a Suisa list for a gig.
`,
Run: func(_ *cobra.Command, args []string) {
err := generateSuisalist(args[0])
cobra.CheckErr(err)
},
}

//nolint:gochecknoinits // cobra is desigend like this
func init() {
generateCmd.AddCommand(suisaCmd)

suisaCmd.Flags().StringSliceP("include-columns", "i", []string{"Title", "Year", "Composer", "Arranger", "Duration"},
"defines the repertoire columns to include in the output")

err := viper.BindPFlag("suisa.include-columns", suisaCmd.Flags().Lookup("include-columns"))
cobra.CheckErr(err)
}

func generateSuisalist(gigName string) error {
include := viper.GetStringSlice("suisa.include-columns")
band := config.NewBand()

rep, err := repertoire.New(band)
if err != nil {
return err
}

gig, err := gig.New(band, gigName)
if err != nil {
return err
}

content := rep.Filter(gig).
IncludeColumns(include...).
Render()

data := tmpl.Data{
Title: gig.Name,
Margin: "1cm",
Content: template.HTML(content), //nolint: gosec // not a web application
}

filename, err := tmpl.CreateSetlist(&data)
if err != nil {
return err
}

return convert.HTMLToPDF(filename, filepath.Join(config.Target(), fmt.Sprintf("Suisa List %s.pdf", gig.Name)))
}
2 changes: 1 addition & 1 deletion cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ func init() {
// Cobra supports persistent flags, which, if defined here,
// will be global for your application.

rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $PWD/.setlist.yaml)")
rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is .setlist.yaml)")

rootCmd.PersistentFlags().StringP("band-name", "b", "", "the name of the band")
err := viper.BindPFlag("band.name", rootCmd.PersistentFlags().Lookup("band-name"))
Expand Down
1 change: 1 addition & 0 deletions internal/html/template/generate.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ func init() {

type Data struct {
Title string
Margin string
Content template.HTML
}

Expand Down
4 changes: 2 additions & 2 deletions internal/html/template/setlist.html
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
<meta charset='utf-8'>
<style>
@page {
margin: 0;
padding: 0;
margin: {{.Margin}};
padding: 0cm;
}
table {
border-collapse: collapse;
Expand Down
20 changes: 20 additions & 0 deletions internal/repertoire/helper.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package repertoire

import "github.com/yuin/goldmark/ast"

type indexes map[int]bool

func removeCols(idx indexes, row ast.Node) ast.Node {
i := 0
toRemove := []ast.Node{}
for r := row.FirstChild(); r != nil; r = r.NextSibling() {
if idx[i] {
toRemove = append(toRemove, r)
}
i++
}
for _, r := range toRemove {
row.RemoveChild(row, r)
}
return row
}
17 changes: 14 additions & 3 deletions internal/repertoire/repertoire.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ type Repertoire struct {
songs []Song
columns []string
source []byte
header ast.Node
markdown goldmark.Markdown
}

Expand Down Expand Up @@ -56,6 +57,7 @@ func from(source []byte) Repertoire {
result.songs = append(result.songs, SongFrom(row, source))
}
if row.Kind() == east.KindTableHeader {
result.header = row
for h := row.FirstChild(); h != nil; h = h.NextSibling() {
result.columns = append(result.columns, string(h.Text(source)))
}
Expand Down Expand Up @@ -97,18 +99,24 @@ func (rep Repertoire) Render() string {
return buf.String()
}

func (rep Repertoire) NoHeader() Repertoire {
rep.header = nil
return rep
}

func (rep Repertoire) ExcludeColumns(columns ...string) Repertoire {
indexes := map[int]bool{}
idx := indexes{}
for _, toRemove := range columns {
for i, c := range rep.columns {
if normalize(c) == normalize(toRemove) {
indexes[i] = true
idx[i] = true
}
}
}
for _, song := range rep.songs {
song.RemoveRows(indexes)
song.removeColumns(idx)
}
rep.header = removeCols(idx, rep.header)
return rep
}

Expand All @@ -132,6 +140,9 @@ func (rep Repertoire) generate() *ast.Document {
doc := ast.NewDocument()
table := east.NewTable()
doc.AppendChild(doc, table)
if rep.header != nil {
table.AppendChild(table, rep.header)
}
for _, song := range rep.songs {
table.AppendChild(table, song.TableRow)
}
Expand Down
3 changes: 2 additions & 1 deletion internal/repertoire/repertoire_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ func TestNew(t *testing.T) {
name: "good",
args: args{band: config.Band{Source: "Band"}},
want: Repertoire{
columns: []string{"Title", "Year", "Copyright", "Description"},
columns: []string{"Title", "Year", "Description", "Composer", "Arranger", "Duration"},
songs: []Song{
{Title: "On the Alamo"},
{Title: "Frankie and Johnnie"},
Expand All @@ -38,6 +38,7 @@ func TestNew(t *testing.T) {
tt.assertion(t, err)
got.markdown = nil
got.source = nil
got.header = nil
for i, song := range got.songs {
song.TableRow = nil
got.songs[i] = song
Expand Down
14 changes: 2 additions & 12 deletions internal/repertoire/song.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,17 +18,7 @@ func (s Song) String() string {
return s.Title
}

func (s Song) RemoveRows(indexes map[int]bool) Song {
i := 0
toRemove := []ast.Node{}
for r := s.TableRow.FirstChild(); r != nil; r = r.NextSibling() {
if indexes[i] {
toRemove = append(toRemove, r)
}
i++
}
for _, r := range toRemove {
s.TableRow.RemoveChild(s.TableRow, r)
}
func (s Song) removeColumns(idx indexes) Song {
s.TableRow = removeCols(idx, s.TableRow)
return s
}
10 changes: 5 additions & 5 deletions test/Repertoire/Band/Repertoire.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@

| Title | Year | Copyright | Description |
|-----------------------|------|----------------------|-------------------|
| On the Alamo | 1922 | Public Domain | Lyrics: Gus Kahn |
| Frankie and Johnnie | 1904 | Hughie Cannon | |
| Nowhere to go | 2024 | Christof Laenzlinger | Instrumental |
| Title | Year | Description | Composer | Arranger | Duration |
|-----------------------|------|-------------------|------------------|----------------|----------|
| On the Alamo | 1922 | Lyrics: Gus Kahn | Isham Jones | Chris Lae | 3m 2s |
| Frankie and Johnnie | 1904 | | Hughie Cannon | Chris Lae | 2m 30s |
| Nowhere to go | 2024 | Instrumental | Chris Lae | Chris Lae | 7m |

0 comments on commit 416fa70

Please sign in to comment.