From 562dad49817f8c8b8ee83d69f9b89a28c41d285f Mon Sep 17 00:00:00 2001 From: tobi Date: Thu, 5 Feb 2026 21:30:51 +0100 Subject: [PATCH 1/4] Start with implementation for #58 --- .../internal/mdbl/markdownoutput.go | 29 +++++++++++++----- .../internal/mdbl/markdownoutput_test.go | 30 ++++++++++++++++++- 2 files changed, 50 insertions(+), 9 deletions(-) diff --git a/src/tobi.backfrak.de/internal/mdbl/markdownoutput.go b/src/tobi.backfrak.de/internal/mdbl/markdownoutput.go index 7c9ff67..22a64d5 100644 --- a/src/tobi.backfrak.de/internal/mdbl/markdownoutput.go +++ b/src/tobi.backfrak.de/internal/mdbl/markdownoutput.go @@ -199,28 +199,41 @@ func (formater *MDOutputFormater) WriteOutput(outFile *os.File, summary gpsabl.S // GetOutputLines - Get all lines of the output func (formater *MDOutputFormater) GetOutputLines(summary gpsabl.SummaryArg) ([]string, error) { - var lines []string + var contentLines []string + var outputLines []string var headerLines []string + if summary == gpsabl.ADDITIONAL { + outputLines = append(outputLines, fmt.Sprintf("List of Tracks:%s", GetNewLine())) + outputLines = append(outputLines, GetNewLine()) + } headerLines = append(headerLines, formater.GetHeader()) headerLines = append(headerLines, formater.GetHeaderContentSeparator()) switch summary { case gpsabl.NONE: - lines = append(lines, formater.GetLines()...) + contentLines = append(contentLines, formater.GetLines()...) case gpsabl.ONLY: - lines = append(lines, formater.GetStatisticSummaryLines()...) + contentLines = append(contentLines, formater.GetStatisticSummaryLines()...) case gpsabl.ADDITIONAL: - lines = append(lines, formater.GetLines()...) - lines = append(lines, formater.GetStatisticSummaryLines()...) + contentLines = append(contentLines, formater.GetLines()...) default: return nil, gpsabl.NewSummaryParamaterNotKnown(summary) } - formater.entriesToWriteCount = len(lines) + formater.entriesToWriteCount = len(contentLines) if formater.entriesToWriteCount > 0 { - return append(headerLines, lines...), nil + outputLines = append(outputLines, headerLines...) + outputLines = append(outputLines, contentLines...) + if summary == gpsabl.ADDITIONAL { + outputLines = append(outputLines, GetNewLine()) + outputLines = append(outputLines, fmt.Sprintf("Summary table:%s", GetNewLine())) + outputLines = append(outputLines, GetNewLine()) + outputLines = append(outputLines, headerLines...) + outputLines = append(outputLines, formater.GetStatisticSummaryLines()...) + } + return outputLines, nil } - return lines, nil + return contentLines, nil } // getOutPutEntries - Add the output of a TrackFile diff --git a/src/tobi.backfrak.de/internal/mdbl/markdownoutput_test.go b/src/tobi.backfrak.de/internal/mdbl/markdownoutput_test.go index 03b256e..f6885b3 100644 --- a/src/tobi.backfrak.de/internal/mdbl/markdownoutput_test.go +++ b/src/tobi.backfrak.de/internal/mdbl/markdownoutput_test.go @@ -782,9 +782,37 @@ func TestGetOutputLinesSummaryAdditional(t *testing.T) { if errOut != nil { t.Errorf("Got an error but did not expect one. The error is: %s", err.Error()) } - if len(lines) != 8 { + if len(lines) != 15 { t.Errorf("Got an unexpected number of lines") } + + if lines[0] != fmt.Sprintf("List of Tracks:%s", GetNewLine()) { + t.Errorf("The 1. line has not the expected content. It is '%s' but should be 'List of Tracks:'", lines[0]) + } + + if lines[1] != GetNewLine() { + t.Errorf("The 2. line has not the expected content. It is '%s' but should be ''", lines[1]) + } + + if lines[2] != frt.GetHeader() { + t.Errorf("The 3. line has not the expected content. It is '%s' but should be '%s'", lines[3], frt.GetHeader()) + } + + if lines[6] != GetNewLine() { + t.Errorf("The 7. line has not the expected content. It is '%s' but should be ''", lines[6]) + } + + if lines[7] != fmt.Sprintf("Summary table:%s", GetNewLine()) { + t.Errorf("The 8. line has not the expected content. It is '%s' but should be 'Summary table:'", lines[7]) + } + + if lines[8] != GetNewLine() { + t.Errorf("The 9. line has not the expected content. It is '%s' but should be ''", lines[8]) + } + + if lines[9] != frt.GetHeader() { + t.Errorf("The 10. line has not the expected content. It is '%s' but should be '%s'", lines[9], frt.GetHeader()) + } } func TestGetOutputLinesSummaryUnValid(t *testing.T) { From 755d012e65e3230b558a260675b5ca7e13a9e672 Mon Sep 17 00:00:00 2001 From: tobi Date: Thu, 5 Feb 2026 22:09:41 +0100 Subject: [PATCH 2/4] Add feature parameters --- src/tobi.backfrak.de/cmd/gpsa/input.go | 10 ++++++++++ src/tobi.backfrak.de/cmd/gpsa/main.go | 3 +++ src/tobi.backfrak.de/cmd/gpsa/main_test.go | 2 ++ src/tobi.backfrak.de/internal/mdbl/markdownoutput.go | 8 ++++++-- 4 files changed, 21 insertions(+), 2 deletions(-) diff --git a/src/tobi.backfrak.de/cmd/gpsa/input.go b/src/tobi.backfrak.de/cmd/gpsa/input.go index 468e324..520b735 100644 --- a/src/tobi.backfrak.de/cmd/gpsa/input.go +++ b/src/tobi.backfrak.de/cmd/gpsa/input.go @@ -73,6 +73,12 @@ var MinStartTime string // MaxStartTime - The maximum StartTime for a track to be added to the output. Formatted in "YYYY-MMM-dd HH:mm:ss", may without seconds or just a date var MaxStartTime string +// MarkdownAdditionalSummaryTrackListText - The text written before the track list table in case markdown output and '-summary=additional' is used in combination +var MarkdownAdditionalSummaryTrackListText string + +// MarkdownAdditionalSummaryText - The text written before the summary table in case markdown output and '-summary=additional' is used in combination +var MarkdownAdditionalSummaryText string + // ReadInputStreamBuffer - Read an input stream and figure out what kind of files are given func ReadInputStreamBuffer(reader *bufio.Reader) ([]gpsabl.InputFile, error) { var fileArgs []gpsabl.InputFile @@ -222,6 +228,10 @@ func handleComandlineOptions() { "The minimum StartTime for a track to be added to the output. Formatted in \"YYYY-MMM-dd HH:mm:ss\", may without seconds or just a date") flag.StringVar(&MaxStartTime, "maximum-start-time", "", "The maximum StartTime for a track to be added to the output. Formatted in \"YYYY-MMM-dd HH:mm:ss\", may without seconds or just a date") + flag.StringVar(&MarkdownAdditionalSummaryTrackListText, "markdown-track-list-text", "List of Tracks:", + "The text written before the track list table in case markdown output and '-summary=additional' is used in combination") + flag.StringVar(&MarkdownAdditionalSummaryText, "markdown-summary-text", "Summary table:", + "The text written before the summary table in case markdown output and '-summary=additional' is used in combination") // Overwrite the std Usage function with some custom stuff flag.Usage = customHelpMessage diff --git a/src/tobi.backfrak.de/cmd/gpsa/main.go b/src/tobi.backfrak.de/cmd/gpsa/main.go index a9d3829..32de25a 100644 --- a/src/tobi.backfrak.de/cmd/gpsa/main.go +++ b/src/tobi.backfrak.de/cmd/gpsa/main.go @@ -330,6 +330,9 @@ func getOutPutFormater(outFile os.File) gpsabl.OutputFormater { switch iFormater.(type) { case gpsabl.TextOutputFormater: iFormater = setTextutputFormater(iFormater.GetTextOutputFormater()) + case *mdbl.MDOutputFormater: + (iFormater.(*mdbl.MDOutputFormater)).SummaryText = MarkdownAdditionalSummaryText + (iFormater.(*mdbl.MDOutputFormater)).TrackListText = MarkdownAdditionalSummaryTrackListText } if iFormater == nil { HandleError(newUnKnownFileTypeError(outFile.Name()), "", false, DontPanicFlag) diff --git a/src/tobi.backfrak.de/cmd/gpsa/main_test.go b/src/tobi.backfrak.de/cmd/gpsa/main_test.go index df6544f..7aaa151 100644 --- a/src/tobi.backfrak.de/cmd/gpsa/main_test.go +++ b/src/tobi.backfrak.de/cmd/gpsa/main_test.go @@ -1074,3 +1074,5 @@ func TestProcessValidFilesWithStartTimeFilters(t *testing.T) { MinStartTime = oldMinStartTime DefinedFilters = []gpsabl.TrackFilter{} } + +// ToDo: Add test for -markdown-track-list-text and -markdown-summary-text parameter diff --git a/src/tobi.backfrak.de/internal/mdbl/markdownoutput.go b/src/tobi.backfrak.de/internal/mdbl/markdownoutput.go index 22a64d5..ffc424a 100644 --- a/src/tobi.backfrak.de/internal/mdbl/markdownoutput.go +++ b/src/tobi.backfrak.de/internal/mdbl/markdownoutput.go @@ -41,6 +41,8 @@ type MDOutputFormater struct { entriesToWriteCount int lineBuffer []gpsabl.OutputLine mux sync.Mutex + TrackListText string + SummaryText string } // NewMDOutputFormater - Get a new MDOutputFormater @@ -51,6 +53,8 @@ func NewMDOutputFormater() *MDOutputFormater { ret.timeFormater = gpsabl.RFC3339 ret.lineBuffer = []gpsabl.OutputLine{} ret.Separator = "|" + ret.TrackListText = "List of Tracks:" + ret.SummaryText = "Summary table:" return &ret } @@ -203,7 +207,7 @@ func (formater *MDOutputFormater) GetOutputLines(summary gpsabl.SummaryArg) ([]s var outputLines []string var headerLines []string if summary == gpsabl.ADDITIONAL { - outputLines = append(outputLines, fmt.Sprintf("List of Tracks:%s", GetNewLine())) + outputLines = append(outputLines, fmt.Sprintf("%s%s", formater.TrackListText, GetNewLine())) outputLines = append(outputLines, GetNewLine()) } headerLines = append(headerLines, formater.GetHeader()) @@ -225,7 +229,7 @@ func (formater *MDOutputFormater) GetOutputLines(summary gpsabl.SummaryArg) ([]s outputLines = append(outputLines, contentLines...) if summary == gpsabl.ADDITIONAL { outputLines = append(outputLines, GetNewLine()) - outputLines = append(outputLines, fmt.Sprintf("Summary table:%s", GetNewLine())) + outputLines = append(outputLines, fmt.Sprintf("%s%s", formater.SummaryText, GetNewLine())) outputLines = append(outputLines, GetNewLine()) outputLines = append(outputLines, headerLines...) outputLines = append(outputLines, formater.GetStatisticSummaryLines()...) From 6862394d665b735788cb250e0cb652836e192855 Mon Sep 17 00:00:00 2001 From: tobi Date: Sat, 7 Feb 2026 16:08:35 +0100 Subject: [PATCH 3/4] Add tests for the two markdown table feature --- .../internal/mdbl/markdownoutput.go | 7 +- .../internal/mdbl/markdownoutput_test.go | 76 +++++++++++++++++++ 2 files changed, 82 insertions(+), 1 deletion(-) diff --git a/src/tobi.backfrak.de/internal/mdbl/markdownoutput.go b/src/tobi.backfrak.de/internal/mdbl/markdownoutput.go index ffc424a..fc67230 100644 --- a/src/tobi.backfrak.de/internal/mdbl/markdownoutput.go +++ b/src/tobi.backfrak.de/internal/mdbl/markdownoutput.go @@ -190,14 +190,19 @@ func (formater *MDOutputFormater) WriteOutput(outFile *os.File, summary gpsabl.S return getErr } + if formater.entriesToWriteCount == 0 { + formater.writtenEntiresCount = formater.entriesToWriteCount + return nil + } + for _, line := range lines { _, errWrite := outFile.WriteString(line) if errWrite != nil { return errWrite } } - formater.writtenEntiresCount = formater.entriesToWriteCount + formater.writtenEntiresCount = formater.entriesToWriteCount return nil } diff --git a/src/tobi.backfrak.de/internal/mdbl/markdownoutput_test.go b/src/tobi.backfrak.de/internal/mdbl/markdownoutput_test.go index f6885b3..f58fcfd 100644 --- a/src/tobi.backfrak.de/internal/mdbl/markdownoutput_test.go +++ b/src/tobi.backfrak.de/internal/mdbl/markdownoutput_test.go @@ -426,6 +426,20 @@ func TestWriteOutputNoTrack(t *testing.T) { } } +func TestWriteOutputEmptyTrackListAdditionalSummary(t *testing.T) { + frt := NewMDOutputFormater() + + errWrite := frt.WriteOutput(os.Stdout, "additional") + + if errWrite != nil { + t.Errorf("Error while writing the output: %s", errWrite.Error()) + } + + if frt.GetNumberOfOutputEntries() != 0 { + t.Errorf("Error: The number of output entries is %d but should be %d", frt.GetNumberOfOutputEntries(), 0) + } +} + func TestWriteOutputSummaryUnknown(t *testing.T) { frt := NewMDOutputFormater() trackFile := getTrackFileTwoTracksWithThreeSegments() @@ -722,6 +736,10 @@ func TestGetOutputLinesNoLinesInList(t *testing.T) { if len(lines) != numberlinesExpected { t.Errorf("Don't get an empty list when no entries are added") } + + if frt.entriesToWriteCount != numberlinesExpected { + t.Errorf("The entriesToWriteCount is '%d' but should be '%d'", frt.entriesToWriteCount, numberlinesExpected) + } } func TestGetOutputLinesSummaryNone(t *testing.T) { @@ -813,6 +831,64 @@ func TestGetOutputLinesSummaryAdditional(t *testing.T) { if lines[9] != frt.GetHeader() { t.Errorf("The 10. line has not the expected content. It is '%s' but should be '%s'", lines[9], frt.GetHeader()) } + + if frt.entriesToWriteCount != 2 { + t.Errorf("GetNumberOfOutputEntries does not return the expected value. It is '%d' but should be '%d'", frt.entriesToWriteCount, 2) + } +} + +func TestGetOutputLinesSummaryAdditionalNoTrackPassFilter(t *testing.T) { + frt := NewMDOutputFormater() + + trackFile1 := getTrackFileWithDifferentTime() + err := frt.AddOutPut(trackFile1, "file", false) + if err != nil { + t.Errorf("Got an error but did not expect one. The error is: %s", err.Error()) + } + trackFile2 := getSimpleTrackFileWithTime() + err = frt.AddOutPut(trackFile2, "file", false) + if err != nil { + t.Errorf("Got an error but did not expect one. The error is: %s", err.Error()) + } + lines, errOut := frt.GetOutputLines("additional") + if errOut != nil { + t.Errorf("Got an error but did not expect one. The error is: %s", err.Error()) + } + if len(lines) != 15 { + t.Errorf("Got an unexpected number of lines") + } + + if lines[0] != fmt.Sprintf("List of Tracks:%s", GetNewLine()) { + t.Errorf("The 1. line has not the expected content. It is '%s' but should be 'List of Tracks:'", lines[0]) + } + + if lines[1] != GetNewLine() { + t.Errorf("The 2. line has not the expected content. It is '%s' but should be ''", lines[1]) + } + + if lines[2] != frt.GetHeader() { + t.Errorf("The 3. line has not the expected content. It is '%s' but should be '%s'", lines[3], frt.GetHeader()) + } + + if lines[6] != GetNewLine() { + t.Errorf("The 7. line has not the expected content. It is '%s' but should be ''", lines[6]) + } + + if lines[7] != fmt.Sprintf("Summary table:%s", GetNewLine()) { + t.Errorf("The 8. line has not the expected content. It is '%s' but should be 'Summary table:'", lines[7]) + } + + if lines[8] != GetNewLine() { + t.Errorf("The 9. line has not the expected content. It is '%s' but should be ''", lines[8]) + } + + if lines[9] != frt.GetHeader() { + t.Errorf("The 10. line has not the expected content. It is '%s' but should be '%s'", lines[9], frt.GetHeader()) + } + + if frt.entriesToWriteCount != 2 { + t.Errorf("GetNumberOfOutputEntries does not return the expected value. It is '%d' but should be '%d'", frt.entriesToWriteCount, 2) + } } func TestGetOutputLinesSummaryUnValid(t *testing.T) { From 6813a20e97689fcd39ba7d7db2b8efba9f8e7a65 Mon Sep 17 00:00:00 2001 From: tobi Date: Sat, 7 Feb 2026 16:28:25 +0100 Subject: [PATCH 4/4] Add more integration tests for new feature --- build/IntegrationTests.sh | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/build/IntegrationTests.sh b/build/IntegrationTests.sh index b01785d..d800c59 100755 --- a/build/IntegrationTests.sh +++ b/build/IntegrationTests.sh @@ -96,6 +96,10 @@ assert_raises "$gpsa -verbose $valid_gpx | grep \"16 of 16 files processed succe assert_raises "$gpsa -verbose -skip-error-exit $valid_gpx $testdata/invalid-tcx/02.tcx | grep \"16 of 17 files processed successfully\" &> /dev/null" 0 assert_raises "$gpsa -verbose -skip-error-exit $valid_gpx $testdata/invalid-tcx/02.tcx | grep \"At least one error occurred\" &> /dev/null" 1 assert_raises "$gpsa -verbose -minimum-start-time=2012-01-02 -maximum-start-time=2015-03-04 $valid_gpx | grep \"does not contain any tracks after applying the given filters\" | wc -l | grep 13 &> /dev/null" 0 +assert_raises "$gpsa -verbose -std-out-format=MD -summary=additional -minimum-start-time=2026-01-01 $valid_gpx | grep \"does not contain any tracks after applying the given filters\" | wc -l | grep 16 &> /dev/null" 0 +assert_raises "$gpsa -std-out-format=MD -summary=additional -markdown-track-list-text=\"my value:\" $valid_gpx | grep \"my value:\" | wc -l | grep 1 &> /dev/null" 0 +assert_raises "$gpsa -std-out-format=MD -summary=additional -markdown-summary-text=\"my value:\" $valid_gpx | grep \"my value:\" | wc -l | grep 1 &> /dev/null" 0 +assert_raises "$gpsa -std-out-format=MD -summary=additional -markdown-summary-text=\"my value:\" -markdown-track-list-text=\"my value:\" $valid_gpx | grep \"my value:\" | wc -l | grep 2 &> /dev/null" 0 # Test stdin if [ -f "$csv_out" ]; then