mirror of
				https://gitea.com/gitea/tea.git
				synced 2025-10-30 16:55:25 +01:00 
			
		
		
		
	Show issue reactions (#421)
``` $ tea issue 230 #230 issue/pull details: show reactions (open) @6543 created 2020-10-22 16:39 since reactions are utf8 now and most terminals too, we can display them nicely :) https://gitea.com/api/v1/repos/gitea/tea/issues/230/reactions -------- 1x 🎉 | 1x 👀 | 1x| 1x 👍 | 1x 👎 | 1x 😆 | 1x 😕 | 1x ❤️ ``` caveats: - reactions are not returned as UTF8 (as was claimed in #230), so they need to be parsed. the library I use doesn't (and can't →
) support all reactions available in gitea - currently only for issues, as reactions for comments mean an additional API request for each comment.. fixes #230 Co-authored-by: Norwin <git@nroo.de> Reviewed-on: https://gitea.com/gitea/tea/pulls/421 Reviewed-by: Lunny Xiao <xiaolunwen@gmail.com> Reviewed-by: techknowlogick <techknowlogick@gitea.io> Co-authored-by: Norwin <noerw@noreply.gitea.io> Co-committed-by: Norwin <noerw@noreply.gitea.io>
This commit is contained in:
		| @@ -54,11 +54,16 @@ func runIssueDetail(cmd *cli.Context, index string) error { | |||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return err | 		return err | ||||||
| 	} | 	} | ||||||
| 	issue, _, err := ctx.Login.Client().GetIssue(ctx.Owner, ctx.Repo, idx) | 	client := ctx.Login.Client() | ||||||
|  | 	issue, _, err := client.GetIssue(ctx.Owner, ctx.Repo, idx) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return err | 		return err | ||||||
| 	} | 	} | ||||||
| 	print.IssueDetails(issue) | 	reactions, _, err := client.GetIssueReactions(ctx.Owner, ctx.Repo, idx) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  | 	print.IssueDetails(issue, reactions) | ||||||
|  |  | ||||||
| 	if issue.Comments > 0 { | 	if issue.Comments > 0 { | ||||||
| 		err = interact.ShowCommentsMaybeInteractive(ctx, idx, issue.Comments) | 		err = interact.ShowCommentsMaybeInteractive(ctx, idx, issue.Comments) | ||||||
|   | |||||||
| @@ -47,6 +47,6 @@ func editIssueState(cmd *cli.Context, opts gitea.EditIssueOption) error { | |||||||
| 		return err | 		return err | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	print.IssueDetails(issue) | 	print.IssueDetails(issue, nil) | ||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
|   | |||||||
							
								
								
									
										1
									
								
								go.mod
									
									
									
									
									
								
							
							
						
						
									
										1
									
								
								go.mod
									
									
									
									
									
								
							| @@ -13,6 +13,7 @@ require ( | |||||||
| 	github.com/araddon/dateparse v0.0.0-20210429162001-6b43995a97de | 	github.com/araddon/dateparse v0.0.0-20210429162001-6b43995a97de | ||||||
| 	github.com/charmbracelet/glamour v0.3.0 | 	github.com/charmbracelet/glamour v0.3.0 | ||||||
| 	github.com/cpuguy83/go-md2man/v2 v2.0.1 // indirect | 	github.com/cpuguy83/go-md2man/v2 v2.0.1 // indirect | ||||||
|  | 	github.com/enescakir/emoji v1.0.0 | ||||||
| 	github.com/go-git/go-git/v5 v5.4.2 | 	github.com/go-git/go-git/v5 v5.4.2 | ||||||
| 	github.com/hashicorp/go-version v1.3.0 // indirect | 	github.com/hashicorp/go-version v1.3.0 // indirect | ||||||
| 	github.com/kevinburke/ssh_config v1.1.0 // indirect | 	github.com/kevinburke/ssh_config v1.1.0 // indirect | ||||||
|   | |||||||
							
								
								
									
										2
									
								
								go.sum
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								go.sum
									
									
									
									
									
								
							| @@ -53,6 +53,8 @@ github.com/dlclark/regexp2 v1.4.0 h1:F1rxgk7p4uKjwIQxBs9oAXe5CqrXlCduYEJvrF4u93E | |||||||
| github.com/dlclark/regexp2 v1.4.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc= | github.com/dlclark/regexp2 v1.4.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc= | ||||||
| github.com/emirpasic/gods v1.12.0 h1:QAUIPSaCu4G+POclxeqb3F+WPpdKqFGlw36+yOzGlrg= | github.com/emirpasic/gods v1.12.0 h1:QAUIPSaCu4G+POclxeqb3F+WPpdKqFGlw36+yOzGlrg= | ||||||
| github.com/emirpasic/gods v1.12.0/go.mod h1:YfzfFFoVP/catgzJb4IKIqXjX78Ha8FMSDh3ymbK86o= | github.com/emirpasic/gods v1.12.0/go.mod h1:YfzfFFoVP/catgzJb4IKIqXjX78Ha8FMSDh3ymbK86o= | ||||||
|  | github.com/enescakir/emoji v1.0.0 h1:W+HsNql8swfCQFtioDGDHCHri8nudlK1n5p2rHCJoog= | ||||||
|  | github.com/enescakir/emoji v1.0.0/go.mod h1:Bt1EKuLnKDTYpLALApstIkAjdDrS/8IAgTkKp+WKFD0= | ||||||
| github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568 h1:BHsljHzVlRcyQhjrss6TZTdY2VfCqZPbv5k3iBFa2ZQ= | github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568 h1:BHsljHzVlRcyQhjrss6TZTdY2VfCqZPbv5k3iBFa2ZQ= | ||||||
| github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= | github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= | ||||||
| github.com/gliderlabs/ssh v0.2.2 h1:6zsha5zo/TWhRhwqCD3+EarCAgZ2yN28ipRnGPnwkI0= | github.com/gliderlabs/ssh v0.2.2 h1:6zsha5zo/TWhRhwqCD3+EarCAgZ2yN28ipRnGPnwkI0= | ||||||
|   | |||||||
| @@ -9,11 +9,12 @@ import ( | |||||||
| 	"strings" | 	"strings" | ||||||
|  |  | ||||||
| 	"code.gitea.io/sdk/gitea" | 	"code.gitea.io/sdk/gitea" | ||||||
|  | 	"github.com/enescakir/emoji" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| // IssueDetails print an issue rendered to stdout | // IssueDetails print an issue rendered to stdout | ||||||
| func IssueDetails(issue *gitea.Issue) { | func IssueDetails(issue *gitea.Issue, reactions []*gitea.Reaction) { | ||||||
| 	outputMarkdown(fmt.Sprintf( | 	out := fmt.Sprintf( | ||||||
| 		"# #%d %s (%s)\n@%s created %s\n\n%s\n", | 		"# #%d %s (%s)\n@%s created %s\n\n%s\n", | ||||||
| 		issue.Index, | 		issue.Index, | ||||||
| 		issue.Title, | 		issue.Title, | ||||||
| @@ -21,7 +22,27 @@ func IssueDetails(issue *gitea.Issue) { | |||||||
| 		issue.Poster.UserName, | 		issue.Poster.UserName, | ||||||
| 		FormatTime(issue.Created), | 		FormatTime(issue.Created), | ||||||
| 		issue.Body, | 		issue.Body, | ||||||
| 	), issue.HTMLURL) | 	) | ||||||
|  |  | ||||||
|  | 	if len(reactions) > 0 { | ||||||
|  | 		out += fmt.Sprintf("\n---\n\n%s\n", formatReactions(reactions)) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	outputMarkdown(out, issue.HTMLURL) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func formatReactions(reactions []*gitea.Reaction) string { | ||||||
|  | 	reactionCounts := make(map[string]uint16) | ||||||
|  | 	for _, r := range reactions { | ||||||
|  | 		reactionCounts[r.Reaction] += 1 | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	reactionStrings := make([]string, 0, len(reactionCounts)) | ||||||
|  | 	for reaction, count := range reactionCounts { | ||||||
|  | 		reactionStrings = append(reactionStrings, fmt.Sprintf("%dx :%s:", count, reaction)) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return emoji.Parse(strings.Join(reactionStrings, "  |  ")) | ||||||
| } | } | ||||||
|  |  | ||||||
| // IssuesPullsList prints a listing of issues & pulls | // IssuesPullsList prints a listing of issues & pulls | ||||||
|   | |||||||
| @@ -25,7 +25,7 @@ func CreateIssue(login *config.Login, repoOwner, repoName string, opts gitea.Cre | |||||||
| 		return fmt.Errorf("could not create issue: %s", err) | 		return fmt.Errorf("could not create issue: %s", err) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	print.IssueDetails(issue) | 	print.IssueDetails(issue, nil) | ||||||
|  |  | ||||||
| 	fmt.Println(issue.HTMLURL) | 	fmt.Println(issue.HTMLURL) | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										15
									
								
								vendor/github.com/enescakir/emoji/.gitignore
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								vendor/github.com/enescakir/emoji/.gitignore
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,15 @@ | |||||||
|  | # Binaries for programs and plugins | ||||||
|  | *.exe | ||||||
|  | *.exe~ | ||||||
|  | *.dll | ||||||
|  | *.so | ||||||
|  | *.dylib | ||||||
|  |  | ||||||
|  | # Test binary, built with `go test -c` | ||||||
|  | *.test | ||||||
|  |  | ||||||
|  | # Output of the go coverage tool, specifically when used with LiteIDE | ||||||
|  | *.out | ||||||
|  |  | ||||||
|  | # Dependency directories (remove the comment below to include it) | ||||||
|  | # vendor/ | ||||||
							
								
								
									
										21
									
								
								vendor/github.com/enescakir/emoji/LICENSE
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								vendor/github.com/enescakir/emoji/LICENSE
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,21 @@ | |||||||
|  | MIT License | ||||||
|  |  | ||||||
|  | Copyright (c) 2020 Enes Çakır | ||||||
|  |  | ||||||
|  | Permission is hereby granted, free of charge, to any person obtaining a copy | ||||||
|  | of this software and associated documentation files (the "Software"), to deal | ||||||
|  | in the Software without restriction, including without limitation the rights | ||||||
|  | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||||
|  | copies of the Software, and to permit persons to whom the Software is | ||||||
|  | furnished to do so, subject to the following conditions: | ||||||
|  |  | ||||||
|  | The above copyright notice and this permission notice shall be included in all | ||||||
|  | copies or substantial portions of the Software. | ||||||
|  |  | ||||||
|  | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||||
|  | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||||
|  | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||||
|  | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||||
|  | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||||
|  | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||||||
|  | SOFTWARE. | ||||||
							
								
								
									
										99
									
								
								vendor/github.com/enescakir/emoji/README.md
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										99
									
								
								vendor/github.com/enescakir/emoji/README.md
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,99 @@ | |||||||
|  | # emoji :rocket: :school_satchel: :tada: | ||||||
|  | [](https://github.com/enescakir/emoji/actions) | ||||||
|  | [](https://godoc.org/github.com/enescakir/emoji) | ||||||
|  | [](https://goreportcard.com/report/github.com/enescakir/emoji) | ||||||
|  | [](https://codecov.io/gh/enescakir/emoji) | ||||||
|  | [](https://github.com/enescakir/emoji/blob/master/LICENSE) | ||||||
|  |  | ||||||
|  | `emoji` is a minimalistic emoji library for Go. It lets you use emoji characters in strings. | ||||||
|  |  | ||||||
|  | Inspired by [spatie/emoji](https://github.com/spatie/emoji) | ||||||
|  |  | ||||||
|  | ## Install :floppy_disk: | ||||||
|  | ``` bash | ||||||
|  | go get github.com/enescakir/emoji | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | ## Usage :surfer: | ||||||
|  | ```go | ||||||
|  | package main | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  |     "fmt" | ||||||
|  |  | ||||||
|  |     "github.com/enescakir/emoji" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | func main() { | ||||||
|  | 	fmt.Printf("Hello %v\n", emoji.WavingHand) | ||||||
|  | 	fmt.Printf("I am %v from %v\n", | ||||||
|  | 		emoji.ManTechnologist, | ||||||
|  | 		emoji.FlagForTurkey, | ||||||
|  | 	) | ||||||
|  | 	fmt.Printf("Different skin tones.\n  default: %v light: %v dark: %v\n", | ||||||
|  | 		emoji.ThumbsUp, | ||||||
|  | 		emoji.OkHand.Tone(emoji.Light), | ||||||
|  | 		emoji.CallMeHand.Tone(emoji.Dark), | ||||||
|  | 	) | ||||||
|  | 	fmt.Printf("Emojis with multiple skin tones.\n  both medium: %v light and dark: %v\n", | ||||||
|  | 		emoji.PeopleHoldingHands.Tone(emoji.Medium), | ||||||
|  | 		emoji.PeopleHoldingHands.Tone(emoji.Light, emoji.Dark), | ||||||
|  | 	) | ||||||
|  | 	fmt.Println(emoji.Parse("Emoji aliases are :sunglasses:")) | ||||||
|  | 	emoji.Println("Use fmt wrappers :+1: with emoji support :tada:") | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* OUTPUT | ||||||
|  |  | ||||||
|  |     Hello 👋 | ||||||
|  |     I am 👨💻 from 🇹🇷 | ||||||
|  |     Different skin tones. | ||||||
|  |       default: 👍 light: 👌🏻 dark: 🤙🏿 | ||||||
|  |     Emojis with multiple skin tones. | ||||||
|  |       both medium: 🧑🏽🤝🧑🏽 light and dark: 🧑🏻🤝🧑🏿 | ||||||
|  |     Emoji aliases are 😎 | ||||||
|  |     Use fmt wrappers 👍 with emoji support 🎉 | ||||||
|  | */ | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | This package contains emojis constants based on [Full Emoji List v13.0](https://unicode.org/Public/emoji/13.0/emoji-test.txt). | ||||||
|  | ```go | ||||||
|  | emoji.CallMeHand // 🤙 | ||||||
|  | emoji.CallMeHand.Tone(emoji.Dark) // 🤙🏿 | ||||||
|  | ``` | ||||||
|  | Also, it has additional emoji aliases from [github/gemoji](https://github.com/github/gemoji). | ||||||
|  | ```go | ||||||
|  | emoji.Parse(":+1:") // 👍 | ||||||
|  | emoji.Parse(":100:") // 💯 | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | You can generate country flag emoji with [ISO 3166 Alpha2](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2) codes: | ||||||
|  | ```go | ||||||
|  | emoji.CountryFlag("tr") // 🇹🇷 | ||||||
|  | emoji.CountryFlag("US") // 🇺🇸 | ||||||
|  | emoji.Parse("country flag alias :flag-gb:") // country flag alias 🇬🇧 | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | All constants are generated by `internal/generator`. | ||||||
|  |  | ||||||
|  | ## Testing :hammer: | ||||||
|  | ``` bash | ||||||
|  | go test | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | ## Todo :pushpin: | ||||||
|  | * Add examples to `godoc` | ||||||
|  |  | ||||||
|  | ## Contributing :man_technologist: | ||||||
|  | I am accepting PRs that add aliases to the package. | ||||||
|  | You have to add it to `customEmojis` list at `internal/generator/main`. | ||||||
|  |  | ||||||
|  | If you think an emoji constant is not correct, open an issue. | ||||||
|  | Please use [this list](http://unicode.org/emoji/charts/full-emoji-list.html) | ||||||
|  | to look up the correct unicode value and the name of the character. | ||||||
|  |  | ||||||
|  | ## Credits :star: | ||||||
|  | - [Enes Çakır](https://github.com/enescakir) | ||||||
|  |  | ||||||
|  | ## License :scroll: | ||||||
|  | The MIT License (MIT). Please see [License File](LICENSE.md) for more information. | ||||||
							
								
								
									
										1944
									
								
								vendor/github.com/enescakir/emoji/constants.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1944
									
								
								vendor/github.com/enescakir/emoji/constants.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										4
									
								
								vendor/github.com/enescakir/emoji/doc.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								vendor/github.com/enescakir/emoji/doc.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,4 @@ | |||||||
|  | /* | ||||||
|  | Package emoji makes working with emojis easier. | ||||||
|  | */ | ||||||
|  | package emoji | ||||||
							
								
								
									
										124
									
								
								vendor/github.com/enescakir/emoji/emoji.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										124
									
								
								vendor/github.com/enescakir/emoji/emoji.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,124 @@ | |||||||
|  | package emoji | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"fmt" | ||||||
|  | 	"strings" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | // Base attributes | ||||||
|  | const ( | ||||||
|  | 	TonePlaceholder = "@" | ||||||
|  | 	flagBaseIndex   = '\U0001F1E6' - 'a' | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | // Skin tone colors | ||||||
|  | const ( | ||||||
|  | 	Default     Tone = "" | ||||||
|  | 	Light       Tone = "\U0001F3FB" | ||||||
|  | 	MediumLight Tone = "\U0001F3FC" | ||||||
|  | 	Medium      Tone = "\U0001F3FD" | ||||||
|  | 	MediumDark  Tone = "\U0001F3FE" | ||||||
|  | 	Dark        Tone = "\U0001F3FF" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | // Emoji defines an emoji object with no skin variations. | ||||||
|  | type Emoji string | ||||||
|  |  | ||||||
|  | // String returns string representation of the simple emoji. | ||||||
|  | func (e Emoji) String() string { | ||||||
|  | 	return string(e) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // EmojiWithTone defines an emoji object that has skin tone options. | ||||||
|  | type EmojiWithTone struct { | ||||||
|  | 	oneTonedCode string | ||||||
|  | 	twoTonedCode string | ||||||
|  | 	defaultTone  Tone | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // newEmojiWithTone constructs a new emoji object that has skin tone options. | ||||||
|  | func newEmojiWithTone(codes ...string) EmojiWithTone { | ||||||
|  | 	if len(codes) == 0 { | ||||||
|  | 		return EmojiWithTone{} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	one := codes[0] | ||||||
|  | 	two := codes[0] | ||||||
|  |  | ||||||
|  | 	if len(codes) > 1 { | ||||||
|  | 		two = codes[1] | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return EmojiWithTone{ | ||||||
|  | 		oneTonedCode: one, | ||||||
|  | 		twoTonedCode: two, | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // withDefaultTone sets default tone for an emoji and returns it. | ||||||
|  | func (e EmojiWithTone) withDefaultTone(tone string) EmojiWithTone { | ||||||
|  | 	e.defaultTone = Tone(tone) | ||||||
|  |  | ||||||
|  | 	return e | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // String returns string representation of the emoji with default skin tone. | ||||||
|  | func (e EmojiWithTone) String() string { | ||||||
|  | 	return strings.ReplaceAll(e.oneTonedCode, TonePlaceholder, e.defaultTone.String()) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Tone returns string representation of the emoji with given skin tone. | ||||||
|  | func (e EmojiWithTone) Tone(tones ...Tone) string { | ||||||
|  | 	// if no tone given, return with default skin tone | ||||||
|  | 	if len(tones) == 0 { | ||||||
|  | 		return e.String() | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	str := e.twoTonedCode | ||||||
|  | 	replaceCount := 1 | ||||||
|  |  | ||||||
|  | 	// if one tone given or emoji doesn't have twoTonedCode, use oneTonedCode | ||||||
|  | 	// Also, replace all with one tone | ||||||
|  | 	if len(tones) == 1 { | ||||||
|  | 		str = e.oneTonedCode | ||||||
|  | 		replaceCount = -1 | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// replace tone one by one | ||||||
|  | 	for _, t := range tones { | ||||||
|  | 		// use emoji's default tone | ||||||
|  | 		if t == Default { | ||||||
|  | 			t = e.defaultTone | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		str = strings.Replace(str, TonePlaceholder, t.String(), replaceCount) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return str | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Tone defines skin tone options for emojis. | ||||||
|  | type Tone string | ||||||
|  |  | ||||||
|  | // String returns string representation of the skin tone. | ||||||
|  | func (t Tone) String() string { | ||||||
|  | 	return string(t) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // CountryFlag returns a country flag emoji from given country code. | ||||||
|  | // Full list of country codes: https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2 | ||||||
|  | func CountryFlag(code string) (Emoji, error) { | ||||||
|  | 	if len(code) != 2 { | ||||||
|  | 		return "", fmt.Errorf("not valid country code: %q", code) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	code = strings.ToLower(code) | ||||||
|  | 	flag := countryCodeLetter(code[0]) + countryCodeLetter(code[1]) | ||||||
|  |  | ||||||
|  | 	return Emoji(flag), nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // countryCodeLetter shifts given letter byte as flagBaseIndex. | ||||||
|  | func countryCodeLetter(l byte) string { | ||||||
|  | 	return string(rune(l) + flagBaseIndex) | ||||||
|  | } | ||||||
							
								
								
									
										56
									
								
								vendor/github.com/enescakir/emoji/fmt.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										56
									
								
								vendor/github.com/enescakir/emoji/fmt.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,56 @@ | |||||||
|  | package emoji | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"fmt" | ||||||
|  | 	"io" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | // Sprint wraps fmt.Sprint with emoji support | ||||||
|  | func Sprint(a ...interface{}) string { | ||||||
|  | 	return Parse(fmt.Sprint(a...)) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Sprintf wraps fmt.Sprintf with emoji support | ||||||
|  | func Sprintf(format string, a ...interface{}) string { | ||||||
|  | 	return Parse(fmt.Sprintf(format, a...)) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Sprintln wraps fmt.Sprintln with emoji support | ||||||
|  | func Sprintln(a ...interface{}) string { | ||||||
|  | 	return Parse(fmt.Sprintln(a...)) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Print wraps fmt.Print with emoji support | ||||||
|  | func Print(a ...interface{}) (n int, err error) { | ||||||
|  | 	return fmt.Print(Sprint(a...)) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Println wraps fmt.Println with emoji support | ||||||
|  | func Println(a ...interface{}) (n int, err error) { | ||||||
|  | 	return fmt.Println(Sprint(a...)) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Printf wraps fmt.Printf with emoji support | ||||||
|  | func Printf(format string, a ...interface{}) (n int, err error) { | ||||||
|  | 	return fmt.Print(Sprintf(format, a...)) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Fprint wraps fmt.Fprint with emoji support | ||||||
|  | func Fprint(w io.Writer, a ...interface{}) (n int, err error) { | ||||||
|  | 	return fmt.Fprint(w, Sprint(a...)) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Fprintf wraps fmt.Fprintf with emoji support | ||||||
|  | func Fprintf(w io.Writer, format string, a ...interface{}) (n int, err error) { | ||||||
|  | 	return fmt.Fprint(w, Sprintf(format, a...)) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Fprintln wraps fmt.Fprintln with emoji support | ||||||
|  | func Fprintln(w io.Writer, a ...interface{}) (n int, err error) { | ||||||
|  | 	return fmt.Fprintln(w, Sprint(a...)) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Errorf wraps fmt.Errorf with emoji support | ||||||
|  | func Errorf(format string, a ...interface{}) error { | ||||||
|  | 	return fmt.Errorf(Sprintf(format, a...)) | ||||||
|  | } | ||||||
							
								
								
									
										3
									
								
								vendor/github.com/enescakir/emoji/go.mod
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								vendor/github.com/enescakir/emoji/go.mod
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,3 @@ | |||||||
|  | module github.com/enescakir/emoji | ||||||
|  |  | ||||||
|  | go 1.13 | ||||||
							
								
								
									
										0
									
								
								vendor/github.com/enescakir/emoji/go.sum
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								vendor/github.com/enescakir/emoji/go.sum
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
								
								
									
										2715
									
								
								vendor/github.com/enescakir/emoji/map.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										2715
									
								
								vendor/github.com/enescakir/emoji/map.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										127
									
								
								vendor/github.com/enescakir/emoji/parser.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										127
									
								
								vendor/github.com/enescakir/emoji/parser.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,127 @@ | |||||||
|  | package emoji | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"fmt" | ||||||
|  | 	"regexp" | ||||||
|  | 	"strings" | ||||||
|  | 	"unicode" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | var ( | ||||||
|  | 	flagRegex = regexp.MustCompile(`^:flag-([a-zA-Z]{2}):$`) | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | // Parse replaces emoji aliases (:pizza:) with unicode representation. | ||||||
|  | func Parse(input string) string { | ||||||
|  | 	var matched strings.Builder | ||||||
|  | 	var output strings.Builder | ||||||
|  |  | ||||||
|  | 	for _, r := range input { | ||||||
|  | 		// when it's not `:`, it might be inner or outer of the emoji alias | ||||||
|  | 		if r != ':' { | ||||||
|  | 			// if matched is empty, it's the outer of the emoji alias | ||||||
|  | 			if matched.Len() == 0 { | ||||||
|  | 				output.WriteRune(r) | ||||||
|  | 				continue | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			matched.WriteRune(r) | ||||||
|  |  | ||||||
|  | 			// if it's space, the alias's not valid. | ||||||
|  | 			// reset matched for breaking the emoji alias | ||||||
|  | 			if unicode.IsSpace(r) { | ||||||
|  | 				output.WriteString(matched.String()) | ||||||
|  | 				matched.Reset() | ||||||
|  | 			} | ||||||
|  | 			continue | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		// r is `:` now | ||||||
|  | 		// if matched is empty, it's the beginning of the emoji alias | ||||||
|  | 		if matched.Len() == 0 { | ||||||
|  | 			matched.WriteRune(r) | ||||||
|  | 			continue | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		// it's the end of the emoji alias | ||||||
|  | 		match := matched.String() | ||||||
|  | 		alias := match + ":" | ||||||
|  |  | ||||||
|  | 		// check for emoji alias | ||||||
|  | 		if code, ok := Find(alias); ok { | ||||||
|  | 			output.WriteString(code) | ||||||
|  | 			matched.Reset() | ||||||
|  | 			continue | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		// not found any emoji | ||||||
|  | 		output.WriteString(match) | ||||||
|  | 		// it might be the beginning of the another emoji alias | ||||||
|  | 		matched.Reset() | ||||||
|  | 		matched.WriteRune(r) | ||||||
|  |  | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// if matched not empty, add it to output | ||||||
|  | 	if matched.Len() != 0 { | ||||||
|  | 		output.WriteString(matched.String()) | ||||||
|  | 		matched.Reset() | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return output.String() | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Map returns the emojis map. | ||||||
|  | // Key is the alias of the emoji. | ||||||
|  | // Value is the code of the emoji. | ||||||
|  | func Map() map[string]string { | ||||||
|  | 	return emojiMap | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // AppendAlias adds new emoji pair to the emojis map. | ||||||
|  | func AppendAlias(alias, code string) error { | ||||||
|  | 	if c, ok := emojiMap[alias]; ok { | ||||||
|  | 		return fmt.Errorf("emoji already exist: %q => %+q", alias, c) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	for _, r := range alias { | ||||||
|  | 		if unicode.IsSpace(r) { | ||||||
|  | 			return fmt.Errorf("emoji alias is not valid: %q", alias) | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	emojiMap[alias] = code | ||||||
|  |  | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Exist checks existence of the emoji by alias. | ||||||
|  | func Exist(alias string) bool { | ||||||
|  | 	_, ok := Find(alias) | ||||||
|  |  | ||||||
|  | 	return ok | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Find returns the emoji code by alias. | ||||||
|  | func Find(alias string) (string, bool) { | ||||||
|  | 	if code, ok := emojiMap[alias]; ok { | ||||||
|  | 		return code, true | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if flag := checkFlag(alias); len(flag) > 0 { | ||||||
|  | 		return flag, true | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return "", false | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // checkFlag finds flag emoji for `flag-[CODE]` pattern | ||||||
|  | func checkFlag(alias string) string { | ||||||
|  | 	if matches := flagRegex.FindStringSubmatch(alias); len(matches) == 2 { | ||||||
|  | 		flag, _ := CountryFlag(matches[1]) | ||||||
|  |  | ||||||
|  | 		return flag.String() | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return "" | ||||||
|  | } | ||||||
							
								
								
									
										2
									
								
								vendor/modules.txt
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								vendor/modules.txt
									
									
									
									
										vendored
									
									
								
							| @@ -93,6 +93,8 @@ github.com/emirpasic/gods/lists/arraylist | |||||||
| github.com/emirpasic/gods/trees | github.com/emirpasic/gods/trees | ||||||
| github.com/emirpasic/gods/trees/binaryheap | github.com/emirpasic/gods/trees/binaryheap | ||||||
| github.com/emirpasic/gods/utils | github.com/emirpasic/gods/utils | ||||||
|  | # github.com/enescakir/emoji v1.0.0 | ||||||
|  | github.com/enescakir/emoji | ||||||
| # github.com/go-git/gcfg v1.5.0 | # github.com/go-git/gcfg v1.5.0 | ||||||
| github.com/go-git/gcfg | github.com/go-git/gcfg | ||||||
| github.com/go-git/gcfg/scanner | github.com/go-git/gcfg/scanner | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Norwin
					Norwin