From 6af2b5c6e1433cab23f499ca91ce8a432c7ecc6d Mon Sep 17 00:00:00 2001 From: morganamilo Date: Sun, 6 May 2018 22:04:04 +0100 Subject: [PATCH 1/3] Respect bottomup for -Pw This commit also refactors the news related sructs into their own types instead of being anonymous and moves the printing to its own .Print() function. --- print.go | 68 +++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 45 insertions(+), 23 deletions(-) diff --git a/print.go b/print.go index 9b2c4cd9..8d7c2a09 100644 --- a/print.go +++ b/print.go @@ -402,21 +402,39 @@ outer: return nil } +type Item struct { + Title string `xml:"title"` + Link string `xml:"link"` + Description string `xml:"description"` + PubDate string `xml:"pubDate"` + Creator string `xml:"dc:creator"` +} + +func (item Item) Print() error { + date, err := time.Parse(time.RFC1123Z, item.PubDate) + + if err != nil { + return err + } + + fd := formatTime(int(date.Unix())) + + fmt.Println(magenta(fd), strings.TrimSpace(item.Title)) + + return nil +} + +type Channel struct { + Title string `xml:"title"` + Link string `xml:"link"` + Description string `xml:"description"` + Language string `xml:"language"` + Lastbuilddate string `xml:"lastbuilddate"` + Items []Item `xml:"item"` +} + type rss struct { - Channel struct { - Title string `xml:"title"` - Link string `xml:"link"` - Description string `xml:"description"` - Language string `xml:"language"` - Lastbuilddate string `xml:"lastbuilddate"` - Item []struct { - Title string `xml:"title"` - Link string `xml:"link"` - Description string `xml:"description"` - PubDate string `xml:"pubDate"` - Creator string `xml:"dc:creator"` - } `xml:"item"` - } `xml:"channel"` + Channel Channel `xml:"channel"` } func printNewsFeed() error { @@ -439,16 +457,20 @@ func printNewsFeed() error { return err } - for _, item := range rss.Channel.Item { - date, err := time.Parse(time.RFC1123Z, item.PubDate) - - if err != nil { - return err + if config.SortMode == BottomUp { + for i := len(rss.Channel.Items) - 1; i >= 0; i-- { + err := rss.Channel.Items[i].Print() + if err != nil { + return err + } + } + } else { + for i := 0; i < len(rss.Channel.Items); i++ { + err := rss.Channel.Items[i].Print() + if err != nil { + return err + } } - - fd := formatTime(int(date.Unix())) - - fmt.Println(magenta(fd), strings.TrimSpace(item.Title)) } return nil From a10241f7ab5f0671da176179029aa18f9ee45e13 Mon Sep 17 00:00:00 2001 From: morganamilo Date: Mon, 7 May 2018 01:25:47 +0100 Subject: [PATCH 2/3] Print descriptions of news Print the full descriptions of each news item. The description is formatted as html, basic parsing is done to display it properly. -q/--quiet can be used to diplay title only. --- parser.go | 96 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ print.go | 8 ++++- 2 files changed, 103 insertions(+), 1 deletion(-) diff --git a/parser.go b/parser.go index 4ce96228..67c2f05e 100644 --- a/parser.go +++ b/parser.go @@ -1,6 +1,7 @@ package main import ( + "bytes" "fmt" "io" "os" @@ -8,6 +9,15 @@ import ( "strings" ) +var htmlEscapeSequences = map[string]rune{ + "quot": '"', + "apos": '\'', + "amp": '&', + "lt": '<', + "gt": '>', + "nbsp": '\u008a', +} + // A basic set implementation for strings. // This is used a lot so it deserves its own type. // Other types of sets are used throughout the code but do not have @@ -673,3 +683,89 @@ func parseNumberMenu(input string) (intRanges, intRanges, stringSet, stringSet) return include, exclude, otherInclude, otherExclude } + +func unescapeHtmlChar(str string) rune { + var first string + var rest string + for i := range str { + first = str[0:i] + rest = str[i:] + } + + if first == "#" { + num, err := strconv.Atoi(rest) + if err != nil { + return '?' + } + + return rune(num) + } + + char, ok := htmlEscapeSequences[str] + if !ok { + return '?' + } + + return char +} + +// Crude html parsing, good enough for the arch news +// This is only displayed in the terminal so there should be no security +// concerns +func parseNews(str string) string { + var buffer bytes.Buffer + var tagBuffer bytes.Buffer + var escapeBuffer bytes.Buffer + inTag := false + inEscape := false + + for _, char := range str { + if inTag { + if char == '>' { + inTag = false + switch tagBuffer.String() { + case "code": + buffer.WriteString(cyanCode) + case "/code": + buffer.WriteString(resetCode) + case "/p": + buffer.WriteRune('\n') + } + + continue + } + + tagBuffer.WriteRune(char) + continue + } + + if inEscape { + if char == ';' { + inEscape = false + char := unescapeHtmlChar(escapeBuffer.String()) + buffer.WriteRune(char) + continue + } + + escapeBuffer.WriteRune(char) + continue + } + + if char == '<' { + inTag = true + tagBuffer.Reset() + continue + } + + if char == '&' { + inEscape = true + escapeBuffer.Reset() + continue + } + + buffer.WriteRune(char) + } + + buffer.WriteString(resetCode) + return buffer.String() +} diff --git a/print.go b/print.go index 8d7c2a09..8996e6d5 100644 --- a/print.go +++ b/print.go @@ -419,7 +419,13 @@ func (item Item) Print() error { fd := formatTime(int(date.Unix())) - fmt.Println(magenta(fd), strings.TrimSpace(item.Title)) + fmt.Println(bold(magenta(fd)), bold(strings.TrimSpace(item.Title))) + //fmt.Println(strings.TrimSpace(item.Link)) + + if !cmdArgs.existsArg("q", "quiet") { + desc := strings.TrimSpace(parseNews(item.Description)) + fmt.Println(desc) + } return nil } From 21b7899083fe6342cba7649ef8decc490bd2ba61 Mon Sep 17 00:00:00 2001 From: morganamilo Date: Mon, 7 May 2018 06:26:29 +0100 Subject: [PATCH 3/3] Use built in html escaping --- parser.go | 41 +++++------------------------------------ 1 file changed, 5 insertions(+), 36 deletions(-) diff --git a/parser.go b/parser.go index 67c2f05e..826bd075 100644 --- a/parser.go +++ b/parser.go @@ -7,17 +7,9 @@ import ( "os" "strconv" "strings" + "html" ) -var htmlEscapeSequences = map[string]rune{ - "quot": '"', - "apos": '\'', - "amp": '&', - "lt": '<', - "gt": '>', - "nbsp": '\u008a', -} - // A basic set implementation for strings. // This is used a lot so it deserves its own type. // Other types of sets are used throughout the code but do not have @@ -684,31 +676,6 @@ func parseNumberMenu(input string) (intRanges, intRanges, stringSet, stringSet) return include, exclude, otherInclude, otherExclude } -func unescapeHtmlChar(str string) rune { - var first string - var rest string - for i := range str { - first = str[0:i] - rest = str[i:] - } - - if first == "#" { - num, err := strconv.Atoi(rest) - if err != nil { - return '?' - } - - return rune(num) - } - - char, ok := htmlEscapeSequences[str] - if !ok { - return '?' - } - - return char -} - // Crude html parsing, good enough for the arch news // This is only displayed in the terminal so there should be no security // concerns @@ -742,8 +709,9 @@ func parseNews(str string) string { if inEscape { if char == ';' { inEscape = false - char := unescapeHtmlChar(escapeBuffer.String()) - buffer.WriteRune(char) + escapeBuffer.WriteRune(char) + s := html.UnescapeString(escapeBuffer.String()) + buffer.WriteString(s) continue } @@ -760,6 +728,7 @@ func parseNews(str string) string { if char == '&' { inEscape = true escapeBuffer.Reset() + escapeBuffer.WriteRune(char) continue }