mirror of
				https://github.com/go-gitea/gitea.git
				synced 2025-11-03 20:36:07 +01:00 
			
		
		
		
	Show download count info in release list (#10124)
* Show download count info in release list * Use go-humanize
This commit is contained in:
		
							
								
								
									
										1
									
								
								go.mod
									
									
									
									
									
								
							
							
						
						
									
										1
									
								
								go.mod
									
									
									
									
									
								
							@@ -32,6 +32,7 @@ require (
 | 
				
			|||||||
	github.com/cznic/strutil v0.0.0-20181122101858-275e90344537 // indirect
 | 
						github.com/cznic/strutil v0.0.0-20181122101858-275e90344537 // indirect
 | 
				
			||||||
	github.com/denisenkom/go-mssqldb v0.0.0-20191128021309-1d7a30a10f73
 | 
						github.com/denisenkom/go-mssqldb v0.0.0-20191128021309-1d7a30a10f73
 | 
				
			||||||
	github.com/dgrijalva/jwt-go v3.2.0+incompatible
 | 
						github.com/dgrijalva/jwt-go v3.2.0+incompatible
 | 
				
			||||||
 | 
						github.com/dustin/go-humanize v1.0.0
 | 
				
			||||||
	github.com/editorconfig/editorconfig-core-go/v2 v2.1.1
 | 
						github.com/editorconfig/editorconfig-core-go/v2 v2.1.1
 | 
				
			||||||
	github.com/emirpasic/gods v1.12.0
 | 
						github.com/emirpasic/gods v1.12.0
 | 
				
			||||||
	github.com/etcd-io/bbolt v1.3.3 // indirect
 | 
						github.com/etcd-io/bbolt v1.3.3 // indirect
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										2
									
								
								go.sum
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								go.sum
									
									
									
									
									
								
							@@ -133,6 +133,8 @@ github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZm
 | 
				
			|||||||
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
 | 
					github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
 | 
				
			||||||
github.com/docker/go-units v0.3.3/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
 | 
					github.com/docker/go-units v0.3.3/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
 | 
				
			||||||
github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
 | 
					github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
 | 
				
			||||||
 | 
					github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo=
 | 
				
			||||||
 | 
					github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
 | 
				
			||||||
github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs=
 | 
					github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs=
 | 
				
			||||||
github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU=
 | 
					github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU=
 | 
				
			||||||
github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I=
 | 
					github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I=
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -13,7 +13,6 @@ import (
 | 
				
			|||||||
	"encoding/hex"
 | 
						"encoding/hex"
 | 
				
			||||||
	"fmt"
 | 
						"fmt"
 | 
				
			||||||
	"io"
 | 
						"io"
 | 
				
			||||||
	"math"
 | 
					 | 
				
			||||||
	"net/http"
 | 
						"net/http"
 | 
				
			||||||
	"net/url"
 | 
						"net/url"
 | 
				
			||||||
	"os"
 | 
						"os"
 | 
				
			||||||
@@ -29,6 +28,7 @@ import (
 | 
				
			|||||||
	"code.gitea.io/gitea/modules/log"
 | 
						"code.gitea.io/gitea/modules/log"
 | 
				
			||||||
	"code.gitea.io/gitea/modules/setting"
 | 
						"code.gitea.io/gitea/modules/setting"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/dustin/go-humanize"
 | 
				
			||||||
	"github.com/unknwon/com"
 | 
						"github.com/unknwon/com"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -214,40 +214,15 @@ func AvatarLink(email string) string {
 | 
				
			|||||||
	return SizedAvatarLink(email, DefaultAvatarSize)
 | 
						return SizedAvatarLink(email, DefaultAvatarSize)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Storage space size types
 | 
					 | 
				
			||||||
const (
 | 
					 | 
				
			||||||
	Byte  = 1
 | 
					 | 
				
			||||||
	KByte = Byte * 1024
 | 
					 | 
				
			||||||
	MByte = KByte * 1024
 | 
					 | 
				
			||||||
	GByte = MByte * 1024
 | 
					 | 
				
			||||||
	TByte = GByte * 1024
 | 
					 | 
				
			||||||
	PByte = TByte * 1024
 | 
					 | 
				
			||||||
	EByte = PByte * 1024
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func logn(n, b float64) float64 {
 | 
					 | 
				
			||||||
	return math.Log(n) / math.Log(b)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func humanateBytes(s uint64, base float64, sizes []string) string {
 | 
					 | 
				
			||||||
	if s < 10 {
 | 
					 | 
				
			||||||
		return fmt.Sprintf("%dB", s)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	e := math.Floor(logn(float64(s), base))
 | 
					 | 
				
			||||||
	suffix := sizes[int(e)]
 | 
					 | 
				
			||||||
	val := float64(s) / math.Pow(base, math.Floor(e))
 | 
					 | 
				
			||||||
	f := "%.0f"
 | 
					 | 
				
			||||||
	if val < 10 {
 | 
					 | 
				
			||||||
		f = "%.1f"
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return fmt.Sprintf(f+"%s", val, suffix)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// FileSize calculates the file size and generate user-friendly string.
 | 
					// FileSize calculates the file size and generate user-friendly string.
 | 
				
			||||||
func FileSize(s int64) string {
 | 
					func FileSize(s int64) string {
 | 
				
			||||||
	sizes := []string{"B", "KB", "MB", "GB", "TB", "PB", "EB"}
 | 
						return humanize.IBytes(uint64(s))
 | 
				
			||||||
	return humanateBytes(uint64(s), 1024, sizes)
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// PrettyNumber produces a string form of the given number in base 10 with
 | 
				
			||||||
 | 
					// commas after every three orders of magnitud
 | 
				
			||||||
 | 
					func PrettyNumber(v int64) string {
 | 
				
			||||||
 | 
						return humanize.Comma(v)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Subtract deals with subtraction of all types of number.
 | 
					// Subtract deals with subtraction of all types of number.
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -103,19 +103,19 @@ func TestAvatarLink(t *testing.T) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
func TestFileSize(t *testing.T) {
 | 
					func TestFileSize(t *testing.T) {
 | 
				
			||||||
	var size int64 = 512
 | 
						var size int64 = 512
 | 
				
			||||||
	assert.Equal(t, "512B", FileSize(size))
 | 
						assert.Equal(t, "512 B", FileSize(size))
 | 
				
			||||||
	size *= 1024
 | 
						size *= 1024
 | 
				
			||||||
	assert.Equal(t, "512KB", FileSize(size))
 | 
						assert.Equal(t, "512 KiB", FileSize(size))
 | 
				
			||||||
	size *= 1024
 | 
						size *= 1024
 | 
				
			||||||
	assert.Equal(t, "512MB", FileSize(size))
 | 
						assert.Equal(t, "512 MiB", FileSize(size))
 | 
				
			||||||
	size *= 1024
 | 
						size *= 1024
 | 
				
			||||||
	assert.Equal(t, "512GB", FileSize(size))
 | 
						assert.Equal(t, "512 GiB", FileSize(size))
 | 
				
			||||||
	size *= 1024
 | 
						size *= 1024
 | 
				
			||||||
	assert.Equal(t, "512TB", FileSize(size))
 | 
						assert.Equal(t, "512 TiB", FileSize(size))
 | 
				
			||||||
	size *= 1024
 | 
						size *= 1024
 | 
				
			||||||
	assert.Equal(t, "512PB", FileSize(size))
 | 
						assert.Equal(t, "512 PiB", FileSize(size))
 | 
				
			||||||
	size *= 4
 | 
						size *= 4
 | 
				
			||||||
	assert.Equal(t, "2.0EB", FileSize(size))
 | 
						assert.Equal(t, "2.0 EiB", FileSize(size))
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func TestSubtract(t *testing.T) {
 | 
					func TestSubtract(t *testing.T) {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -93,6 +93,7 @@ func NewFuncMap() []template.FuncMap {
 | 
				
			|||||||
		"TimeSinceUnix": timeutil.TimeSinceUnix,
 | 
							"TimeSinceUnix": timeutil.TimeSinceUnix,
 | 
				
			||||||
		"RawTimeSince":  timeutil.RawTimeSince,
 | 
							"RawTimeSince":  timeutil.RawTimeSince,
 | 
				
			||||||
		"FileSize":      base.FileSize,
 | 
							"FileSize":      base.FileSize,
 | 
				
			||||||
 | 
							"PrettyNumber":  base.PrettyNumber,
 | 
				
			||||||
		"Subtract":      base.Subtract,
 | 
							"Subtract":      base.Subtract,
 | 
				
			||||||
		"EntryIcon":     base.EntryIcon,
 | 
							"EntryIcon":     base.EntryIcon,
 | 
				
			||||||
		"MigrationIcon": MigrationIcon,
 | 
							"MigrationIcon": MigrationIcon,
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1565,6 +1565,7 @@ release.deletion_success = The release has been deleted.
 | 
				
			|||||||
release.tag_name_already_exist = A release with this tag name already exists.
 | 
					release.tag_name_already_exist = A release with this tag name already exists.
 | 
				
			||||||
release.tag_name_invalid = The tag name is not valid.
 | 
					release.tag_name_invalid = The tag name is not valid.
 | 
				
			||||||
release.downloads = Downloads
 | 
					release.downloads = Downloads
 | 
				
			||||||
 | 
					release.download_count = Downloads: %s
 | 
				
			||||||
 | 
					
 | 
				
			||||||
branch.name = Branch Name
 | 
					branch.name = Branch Name
 | 
				
			||||||
branch.search = Search branches
 | 
					branch.search = Search branches
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -84,6 +84,7 @@
 | 
				
			|||||||
									{{if .Attachments}}
 | 
														{{if .Attachments}}
 | 
				
			||||||
										{{range .Attachments}}
 | 
															{{range .Attachments}}
 | 
				
			||||||
										<li>
 | 
															<li>
 | 
				
			||||||
 | 
																<span class="ui text right" data-tooltip="{{$.i18n.Tr "repo.release.download_count" (.DownloadCount | PrettyNumber)}}" data-position="bottom right"><i class="ui octicon octicon-info"></i></span>
 | 
				
			||||||
											<a target="_blank" rel="noopener noreferrer" href="{{.DownloadURL}}">
 | 
																<a target="_blank" rel="noopener noreferrer" href="{{.DownloadURL}}">
 | 
				
			||||||
												<strong><span class="ui image octicon octicon-package" title='{{.Name}}'></span> {{.Name}}</strong>
 | 
																	<strong><span class="ui image octicon octicon-package" title='{{.Name}}'></span> {{.Name}}</strong>
 | 
				
			||||||
												<span class="ui text grey right">{{.Size | FileSize}}</span>
 | 
																	<span class="ui text grey right">{{.Size | FileSize}}</span>
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										21
									
								
								vendor/github.com/dustin/go-humanize/.travis.yml
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								vendor/github.com/dustin/go-humanize/.travis.yml
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,21 @@
 | 
				
			|||||||
 | 
					sudo: false
 | 
				
			||||||
 | 
					language: go
 | 
				
			||||||
 | 
					go:
 | 
				
			||||||
 | 
					  - 1.3.x
 | 
				
			||||||
 | 
					  - 1.5.x
 | 
				
			||||||
 | 
					  - 1.6.x
 | 
				
			||||||
 | 
					  - 1.7.x
 | 
				
			||||||
 | 
					  - 1.8.x
 | 
				
			||||||
 | 
					  - 1.9.x
 | 
				
			||||||
 | 
					  - master
 | 
				
			||||||
 | 
					matrix:
 | 
				
			||||||
 | 
					  allow_failures:
 | 
				
			||||||
 | 
					    - go: master
 | 
				
			||||||
 | 
					  fast_finish: true
 | 
				
			||||||
 | 
					install:
 | 
				
			||||||
 | 
					  - # Do nothing. This is needed to prevent default install action "go get -t -v ./..." from happening here (we want it to happen inside script step).
 | 
				
			||||||
 | 
					script:
 | 
				
			||||||
 | 
					  - go get -t -v ./...
 | 
				
			||||||
 | 
					  - diff -u <(echo -n) <(gofmt -d -s .)
 | 
				
			||||||
 | 
					  - go tool vet .
 | 
				
			||||||
 | 
					  - go test -v -race ./...
 | 
				
			||||||
							
								
								
									
										21
									
								
								vendor/github.com/dustin/go-humanize/LICENSE
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								vendor/github.com/dustin/go-humanize/LICENSE
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,21 @@
 | 
				
			|||||||
 | 
					Copyright (c) 2005-2008  Dustin Sallings <dustin@spy.net>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<http://www.opensource.org/licenses/mit-license.php>
 | 
				
			||||||
							
								
								
									
										124
									
								
								vendor/github.com/dustin/go-humanize/README.markdown
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										124
									
								
								vendor/github.com/dustin/go-humanize/README.markdown
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,124 @@
 | 
				
			|||||||
 | 
					# Humane Units [](https://travis-ci.org/dustin/go-humanize) [](https://godoc.org/github.com/dustin/go-humanize)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Just a few functions for helping humanize times and sizes.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					`go get` it as `github.com/dustin/go-humanize`, import it as
 | 
				
			||||||
 | 
					`"github.com/dustin/go-humanize"`, use it as `humanize`.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					See [godoc](https://godoc.org/github.com/dustin/go-humanize) for
 | 
				
			||||||
 | 
					complete documentation.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Sizes
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This lets you take numbers like `82854982` and convert them to useful
 | 
				
			||||||
 | 
					strings like, `83 MB` or `79 MiB` (whichever you prefer).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Example:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```go
 | 
				
			||||||
 | 
					fmt.Printf("That file is %s.", humanize.Bytes(82854982)) // That file is 83 MB.
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Times
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This lets you take a `time.Time` and spit it out in relative terms.
 | 
				
			||||||
 | 
					For example, `12 seconds ago` or `3 days from now`.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Example:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```go
 | 
				
			||||||
 | 
					fmt.Printf("This was touched %s.", humanize.Time(someTimeInstance)) // This was touched 7 hours ago.
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Thanks to Kyle Lemons for the time implementation from an IRC
 | 
				
			||||||
 | 
					conversation one day. It's pretty neat.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Ordinals
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					From a [mailing list discussion][odisc] where a user wanted to be able
 | 
				
			||||||
 | 
					to label ordinals.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    0 -> 0th
 | 
				
			||||||
 | 
					    1 -> 1st
 | 
				
			||||||
 | 
					    2 -> 2nd
 | 
				
			||||||
 | 
					    3 -> 3rd
 | 
				
			||||||
 | 
					    4 -> 4th
 | 
				
			||||||
 | 
					    [...]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Example:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```go
 | 
				
			||||||
 | 
					fmt.Printf("You're my %s best friend.", humanize.Ordinal(193)) // You are my 193rd best friend.
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Commas
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Want to shove commas into numbers? Be my guest.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    0 -> 0
 | 
				
			||||||
 | 
					    100 -> 100
 | 
				
			||||||
 | 
					    1000 -> 1,000
 | 
				
			||||||
 | 
					    1000000000 -> 1,000,000,000
 | 
				
			||||||
 | 
					    -100000 -> -100,000
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Example:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```go
 | 
				
			||||||
 | 
					fmt.Printf("You owe $%s.\n", humanize.Comma(6582491)) // You owe $6,582,491.
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Ftoa
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Nicer float64 formatter that removes trailing zeros.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```go
 | 
				
			||||||
 | 
					fmt.Printf("%f", 2.24)                // 2.240000
 | 
				
			||||||
 | 
					fmt.Printf("%s", humanize.Ftoa(2.24)) // 2.24
 | 
				
			||||||
 | 
					fmt.Printf("%f", 2.0)                 // 2.000000
 | 
				
			||||||
 | 
					fmt.Printf("%s", humanize.Ftoa(2.0))  // 2
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## SI notation
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Format numbers with [SI notation][sinotation].
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Example:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```go
 | 
				
			||||||
 | 
					humanize.SI(0.00000000223, "M") // 2.23 nM
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## English-specific functions
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The following functions are in the `humanize/english` subpackage.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### Plurals
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Simple English pluralization
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```go
 | 
				
			||||||
 | 
					english.PluralWord(1, "object", "") // object
 | 
				
			||||||
 | 
					english.PluralWord(42, "object", "") // objects
 | 
				
			||||||
 | 
					english.PluralWord(2, "bus", "") // buses
 | 
				
			||||||
 | 
					english.PluralWord(99, "locus", "loci") // loci
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					english.Plural(1, "object", "") // 1 object
 | 
				
			||||||
 | 
					english.Plural(42, "object", "") // 42 objects
 | 
				
			||||||
 | 
					english.Plural(2, "bus", "") // 2 buses
 | 
				
			||||||
 | 
					english.Plural(99, "locus", "loci") // 99 loci
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### Word series
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Format comma-separated words lists with conjuctions:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```go
 | 
				
			||||||
 | 
					english.WordSeries([]string{"foo"}, "and") // foo
 | 
				
			||||||
 | 
					english.WordSeries([]string{"foo", "bar"}, "and") // foo and bar
 | 
				
			||||||
 | 
					english.WordSeries([]string{"foo", "bar", "baz"}, "and") // foo, bar and baz
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					english.OxfordWordSeries([]string{"foo", "bar", "baz"}, "and") // foo, bar, and baz
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[odisc]: https://groups.google.com/d/topic/golang-nuts/l8NhI74jl-4/discussion
 | 
				
			||||||
 | 
					[sinotation]: http://en.wikipedia.org/wiki/Metric_prefix
 | 
				
			||||||
							
								
								
									
										31
									
								
								vendor/github.com/dustin/go-humanize/big.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								vendor/github.com/dustin/go-humanize/big.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,31 @@
 | 
				
			|||||||
 | 
					package humanize
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"math/big"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// order of magnitude (to a max order)
 | 
				
			||||||
 | 
					func oomm(n, b *big.Int, maxmag int) (float64, int) {
 | 
				
			||||||
 | 
						mag := 0
 | 
				
			||||||
 | 
						m := &big.Int{}
 | 
				
			||||||
 | 
						for n.Cmp(b) >= 0 {
 | 
				
			||||||
 | 
							n.DivMod(n, b, m)
 | 
				
			||||||
 | 
							mag++
 | 
				
			||||||
 | 
							if mag == maxmag && maxmag >= 0 {
 | 
				
			||||||
 | 
								break
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return float64(n.Int64()) + (float64(m.Int64()) / float64(b.Int64())), mag
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// total order of magnitude
 | 
				
			||||||
 | 
					// (same as above, but with no upper limit)
 | 
				
			||||||
 | 
					func oom(n, b *big.Int) (float64, int) {
 | 
				
			||||||
 | 
						mag := 0
 | 
				
			||||||
 | 
						m := &big.Int{}
 | 
				
			||||||
 | 
						for n.Cmp(b) >= 0 {
 | 
				
			||||||
 | 
							n.DivMod(n, b, m)
 | 
				
			||||||
 | 
							mag++
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return float64(n.Int64()) + (float64(m.Int64()) / float64(b.Int64())), mag
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										173
									
								
								vendor/github.com/dustin/go-humanize/bigbytes.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										173
									
								
								vendor/github.com/dustin/go-humanize/bigbytes.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,173 @@
 | 
				
			|||||||
 | 
					package humanize
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
 | 
						"math/big"
 | 
				
			||||||
 | 
						"strings"
 | 
				
			||||||
 | 
						"unicode"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var (
 | 
				
			||||||
 | 
						bigIECExp = big.NewInt(1024)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// BigByte is one byte in bit.Ints
 | 
				
			||||||
 | 
						BigByte = big.NewInt(1)
 | 
				
			||||||
 | 
						// BigKiByte is 1,024 bytes in bit.Ints
 | 
				
			||||||
 | 
						BigKiByte = (&big.Int{}).Mul(BigByte, bigIECExp)
 | 
				
			||||||
 | 
						// BigMiByte is 1,024 k bytes in bit.Ints
 | 
				
			||||||
 | 
						BigMiByte = (&big.Int{}).Mul(BigKiByte, bigIECExp)
 | 
				
			||||||
 | 
						// BigGiByte is 1,024 m bytes in bit.Ints
 | 
				
			||||||
 | 
						BigGiByte = (&big.Int{}).Mul(BigMiByte, bigIECExp)
 | 
				
			||||||
 | 
						// BigTiByte is 1,024 g bytes in bit.Ints
 | 
				
			||||||
 | 
						BigTiByte = (&big.Int{}).Mul(BigGiByte, bigIECExp)
 | 
				
			||||||
 | 
						// BigPiByte is 1,024 t bytes in bit.Ints
 | 
				
			||||||
 | 
						BigPiByte = (&big.Int{}).Mul(BigTiByte, bigIECExp)
 | 
				
			||||||
 | 
						// BigEiByte is 1,024 p bytes in bit.Ints
 | 
				
			||||||
 | 
						BigEiByte = (&big.Int{}).Mul(BigPiByte, bigIECExp)
 | 
				
			||||||
 | 
						// BigZiByte is 1,024 e bytes in bit.Ints
 | 
				
			||||||
 | 
						BigZiByte = (&big.Int{}).Mul(BigEiByte, bigIECExp)
 | 
				
			||||||
 | 
						// BigYiByte is 1,024 z bytes in bit.Ints
 | 
				
			||||||
 | 
						BigYiByte = (&big.Int{}).Mul(BigZiByte, bigIECExp)
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var (
 | 
				
			||||||
 | 
						bigSIExp = big.NewInt(1000)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// BigSIByte is one SI byte in big.Ints
 | 
				
			||||||
 | 
						BigSIByte = big.NewInt(1)
 | 
				
			||||||
 | 
						// BigKByte is 1,000 SI bytes in big.Ints
 | 
				
			||||||
 | 
						BigKByte = (&big.Int{}).Mul(BigSIByte, bigSIExp)
 | 
				
			||||||
 | 
						// BigMByte is 1,000 SI k bytes in big.Ints
 | 
				
			||||||
 | 
						BigMByte = (&big.Int{}).Mul(BigKByte, bigSIExp)
 | 
				
			||||||
 | 
						// BigGByte is 1,000 SI m bytes in big.Ints
 | 
				
			||||||
 | 
						BigGByte = (&big.Int{}).Mul(BigMByte, bigSIExp)
 | 
				
			||||||
 | 
						// BigTByte is 1,000 SI g bytes in big.Ints
 | 
				
			||||||
 | 
						BigTByte = (&big.Int{}).Mul(BigGByte, bigSIExp)
 | 
				
			||||||
 | 
						// BigPByte is 1,000 SI t bytes in big.Ints
 | 
				
			||||||
 | 
						BigPByte = (&big.Int{}).Mul(BigTByte, bigSIExp)
 | 
				
			||||||
 | 
						// BigEByte is 1,000 SI p bytes in big.Ints
 | 
				
			||||||
 | 
						BigEByte = (&big.Int{}).Mul(BigPByte, bigSIExp)
 | 
				
			||||||
 | 
						// BigZByte is 1,000 SI e bytes in big.Ints
 | 
				
			||||||
 | 
						BigZByte = (&big.Int{}).Mul(BigEByte, bigSIExp)
 | 
				
			||||||
 | 
						// BigYByte is 1,000 SI z bytes in big.Ints
 | 
				
			||||||
 | 
						BigYByte = (&big.Int{}).Mul(BigZByte, bigSIExp)
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var bigBytesSizeTable = map[string]*big.Int{
 | 
				
			||||||
 | 
						"b":   BigByte,
 | 
				
			||||||
 | 
						"kib": BigKiByte,
 | 
				
			||||||
 | 
						"kb":  BigKByte,
 | 
				
			||||||
 | 
						"mib": BigMiByte,
 | 
				
			||||||
 | 
						"mb":  BigMByte,
 | 
				
			||||||
 | 
						"gib": BigGiByte,
 | 
				
			||||||
 | 
						"gb":  BigGByte,
 | 
				
			||||||
 | 
						"tib": BigTiByte,
 | 
				
			||||||
 | 
						"tb":  BigTByte,
 | 
				
			||||||
 | 
						"pib": BigPiByte,
 | 
				
			||||||
 | 
						"pb":  BigPByte,
 | 
				
			||||||
 | 
						"eib": BigEiByte,
 | 
				
			||||||
 | 
						"eb":  BigEByte,
 | 
				
			||||||
 | 
						"zib": BigZiByte,
 | 
				
			||||||
 | 
						"zb":  BigZByte,
 | 
				
			||||||
 | 
						"yib": BigYiByte,
 | 
				
			||||||
 | 
						"yb":  BigYByte,
 | 
				
			||||||
 | 
						// Without suffix
 | 
				
			||||||
 | 
						"":   BigByte,
 | 
				
			||||||
 | 
						"ki": BigKiByte,
 | 
				
			||||||
 | 
						"k":  BigKByte,
 | 
				
			||||||
 | 
						"mi": BigMiByte,
 | 
				
			||||||
 | 
						"m":  BigMByte,
 | 
				
			||||||
 | 
						"gi": BigGiByte,
 | 
				
			||||||
 | 
						"g":  BigGByte,
 | 
				
			||||||
 | 
						"ti": BigTiByte,
 | 
				
			||||||
 | 
						"t":  BigTByte,
 | 
				
			||||||
 | 
						"pi": BigPiByte,
 | 
				
			||||||
 | 
						"p":  BigPByte,
 | 
				
			||||||
 | 
						"ei": BigEiByte,
 | 
				
			||||||
 | 
						"e":  BigEByte,
 | 
				
			||||||
 | 
						"z":  BigZByte,
 | 
				
			||||||
 | 
						"zi": BigZiByte,
 | 
				
			||||||
 | 
						"y":  BigYByte,
 | 
				
			||||||
 | 
						"yi": BigYiByte,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var ten = big.NewInt(10)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func humanateBigBytes(s, base *big.Int, sizes []string) string {
 | 
				
			||||||
 | 
						if s.Cmp(ten) < 0 {
 | 
				
			||||||
 | 
							return fmt.Sprintf("%d B", s)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						c := (&big.Int{}).Set(s)
 | 
				
			||||||
 | 
						val, mag := oomm(c, base, len(sizes)-1)
 | 
				
			||||||
 | 
						suffix := sizes[mag]
 | 
				
			||||||
 | 
						f := "%.0f %s"
 | 
				
			||||||
 | 
						if val < 10 {
 | 
				
			||||||
 | 
							f = "%.1f %s"
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return fmt.Sprintf(f, val, suffix)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// BigBytes produces a human readable representation of an SI size.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// See also: ParseBigBytes.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// BigBytes(82854982) -> 83 MB
 | 
				
			||||||
 | 
					func BigBytes(s *big.Int) string {
 | 
				
			||||||
 | 
						sizes := []string{"B", "kB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"}
 | 
				
			||||||
 | 
						return humanateBigBytes(s, bigSIExp, sizes)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// BigIBytes produces a human readable representation of an IEC size.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// See also: ParseBigBytes.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// BigIBytes(82854982) -> 79 MiB
 | 
				
			||||||
 | 
					func BigIBytes(s *big.Int) string {
 | 
				
			||||||
 | 
						sizes := []string{"B", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB", "YiB"}
 | 
				
			||||||
 | 
						return humanateBigBytes(s, bigIECExp, sizes)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ParseBigBytes parses a string representation of bytes into the number
 | 
				
			||||||
 | 
					// of bytes it represents.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// See also: BigBytes, BigIBytes.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// ParseBigBytes("42 MB") -> 42000000, nil
 | 
				
			||||||
 | 
					// ParseBigBytes("42 mib") -> 44040192, nil
 | 
				
			||||||
 | 
					func ParseBigBytes(s string) (*big.Int, error) {
 | 
				
			||||||
 | 
						lastDigit := 0
 | 
				
			||||||
 | 
						hasComma := false
 | 
				
			||||||
 | 
						for _, r := range s {
 | 
				
			||||||
 | 
							if !(unicode.IsDigit(r) || r == '.' || r == ',') {
 | 
				
			||||||
 | 
								break
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if r == ',' {
 | 
				
			||||||
 | 
								hasComma = true
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							lastDigit++
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						num := s[:lastDigit]
 | 
				
			||||||
 | 
						if hasComma {
 | 
				
			||||||
 | 
							num = strings.Replace(num, ",", "", -1)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						val := &big.Rat{}
 | 
				
			||||||
 | 
						_, err := fmt.Sscanf(num, "%f", val)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						extra := strings.ToLower(strings.TrimSpace(s[lastDigit:]))
 | 
				
			||||||
 | 
						if m, ok := bigBytesSizeTable[extra]; ok {
 | 
				
			||||||
 | 
							mv := (&big.Rat{}).SetInt(m)
 | 
				
			||||||
 | 
							val.Mul(val, mv)
 | 
				
			||||||
 | 
							rv := &big.Int{}
 | 
				
			||||||
 | 
							rv.Div(val.Num(), val.Denom())
 | 
				
			||||||
 | 
							return rv, nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return nil, fmt.Errorf("unhandled size name: %v", extra)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										143
									
								
								vendor/github.com/dustin/go-humanize/bytes.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										143
									
								
								vendor/github.com/dustin/go-humanize/bytes.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,143 @@
 | 
				
			|||||||
 | 
					package humanize
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
 | 
						"math"
 | 
				
			||||||
 | 
						"strconv"
 | 
				
			||||||
 | 
						"strings"
 | 
				
			||||||
 | 
						"unicode"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// IEC Sizes.
 | 
				
			||||||
 | 
					// kibis of bits
 | 
				
			||||||
 | 
					const (
 | 
				
			||||||
 | 
						Byte = 1 << (iota * 10)
 | 
				
			||||||
 | 
						KiByte
 | 
				
			||||||
 | 
						MiByte
 | 
				
			||||||
 | 
						GiByte
 | 
				
			||||||
 | 
						TiByte
 | 
				
			||||||
 | 
						PiByte
 | 
				
			||||||
 | 
						EiByte
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// SI Sizes.
 | 
				
			||||||
 | 
					const (
 | 
				
			||||||
 | 
						IByte = 1
 | 
				
			||||||
 | 
						KByte = IByte * 1000
 | 
				
			||||||
 | 
						MByte = KByte * 1000
 | 
				
			||||||
 | 
						GByte = MByte * 1000
 | 
				
			||||||
 | 
						TByte = GByte * 1000
 | 
				
			||||||
 | 
						PByte = TByte * 1000
 | 
				
			||||||
 | 
						EByte = PByte * 1000
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var bytesSizeTable = map[string]uint64{
 | 
				
			||||||
 | 
						"b":   Byte,
 | 
				
			||||||
 | 
						"kib": KiByte,
 | 
				
			||||||
 | 
						"kb":  KByte,
 | 
				
			||||||
 | 
						"mib": MiByte,
 | 
				
			||||||
 | 
						"mb":  MByte,
 | 
				
			||||||
 | 
						"gib": GiByte,
 | 
				
			||||||
 | 
						"gb":  GByte,
 | 
				
			||||||
 | 
						"tib": TiByte,
 | 
				
			||||||
 | 
						"tb":  TByte,
 | 
				
			||||||
 | 
						"pib": PiByte,
 | 
				
			||||||
 | 
						"pb":  PByte,
 | 
				
			||||||
 | 
						"eib": EiByte,
 | 
				
			||||||
 | 
						"eb":  EByte,
 | 
				
			||||||
 | 
						// Without suffix
 | 
				
			||||||
 | 
						"":   Byte,
 | 
				
			||||||
 | 
						"ki": KiByte,
 | 
				
			||||||
 | 
						"k":  KByte,
 | 
				
			||||||
 | 
						"mi": MiByte,
 | 
				
			||||||
 | 
						"m":  MByte,
 | 
				
			||||||
 | 
						"gi": GiByte,
 | 
				
			||||||
 | 
						"g":  GByte,
 | 
				
			||||||
 | 
						"ti": TiByte,
 | 
				
			||||||
 | 
						"t":  TByte,
 | 
				
			||||||
 | 
						"pi": PiByte,
 | 
				
			||||||
 | 
						"p":  PByte,
 | 
				
			||||||
 | 
						"ei": EiByte,
 | 
				
			||||||
 | 
						"e":  EByte,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func logn(n, b float64) float64 {
 | 
				
			||||||
 | 
						return math.Log(n) / math.Log(b)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func humanateBytes(s uint64, base float64, sizes []string) string {
 | 
				
			||||||
 | 
						if s < 10 {
 | 
				
			||||||
 | 
							return fmt.Sprintf("%d B", s)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						e := math.Floor(logn(float64(s), base))
 | 
				
			||||||
 | 
						suffix := sizes[int(e)]
 | 
				
			||||||
 | 
						val := math.Floor(float64(s)/math.Pow(base, e)*10+0.5) / 10
 | 
				
			||||||
 | 
						f := "%.0f %s"
 | 
				
			||||||
 | 
						if val < 10 {
 | 
				
			||||||
 | 
							f = "%.1f %s"
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return fmt.Sprintf(f, val, suffix)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Bytes produces a human readable representation of an SI size.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// See also: ParseBytes.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Bytes(82854982) -> 83 MB
 | 
				
			||||||
 | 
					func Bytes(s uint64) string {
 | 
				
			||||||
 | 
						sizes := []string{"B", "kB", "MB", "GB", "TB", "PB", "EB"}
 | 
				
			||||||
 | 
						return humanateBytes(s, 1000, sizes)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// IBytes produces a human readable representation of an IEC size.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// See also: ParseBytes.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// IBytes(82854982) -> 79 MiB
 | 
				
			||||||
 | 
					func IBytes(s uint64) string {
 | 
				
			||||||
 | 
						sizes := []string{"B", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB"}
 | 
				
			||||||
 | 
						return humanateBytes(s, 1024, sizes)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ParseBytes parses a string representation of bytes into the number
 | 
				
			||||||
 | 
					// of bytes it represents.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// See Also: Bytes, IBytes.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// ParseBytes("42 MB") -> 42000000, nil
 | 
				
			||||||
 | 
					// ParseBytes("42 mib") -> 44040192, nil
 | 
				
			||||||
 | 
					func ParseBytes(s string) (uint64, error) {
 | 
				
			||||||
 | 
						lastDigit := 0
 | 
				
			||||||
 | 
						hasComma := false
 | 
				
			||||||
 | 
						for _, r := range s {
 | 
				
			||||||
 | 
							if !(unicode.IsDigit(r) || r == '.' || r == ',') {
 | 
				
			||||||
 | 
								break
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if r == ',' {
 | 
				
			||||||
 | 
								hasComma = true
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							lastDigit++
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						num := s[:lastDigit]
 | 
				
			||||||
 | 
						if hasComma {
 | 
				
			||||||
 | 
							num = strings.Replace(num, ",", "", -1)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						f, err := strconv.ParseFloat(num, 64)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return 0, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						extra := strings.ToLower(strings.TrimSpace(s[lastDigit:]))
 | 
				
			||||||
 | 
						if m, ok := bytesSizeTable[extra]; ok {
 | 
				
			||||||
 | 
							f *= float64(m)
 | 
				
			||||||
 | 
							if f >= math.MaxUint64 {
 | 
				
			||||||
 | 
								return 0, fmt.Errorf("too large: %v", s)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return uint64(f), nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0, fmt.Errorf("unhandled size name: %v", extra)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										116
									
								
								vendor/github.com/dustin/go-humanize/comma.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										116
									
								
								vendor/github.com/dustin/go-humanize/comma.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,116 @@
 | 
				
			|||||||
 | 
					package humanize
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"bytes"
 | 
				
			||||||
 | 
						"math"
 | 
				
			||||||
 | 
						"math/big"
 | 
				
			||||||
 | 
						"strconv"
 | 
				
			||||||
 | 
						"strings"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Comma produces a string form of the given number in base 10 with
 | 
				
			||||||
 | 
					// commas after every three orders of magnitude.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// e.g. Comma(834142) -> 834,142
 | 
				
			||||||
 | 
					func Comma(v int64) string {
 | 
				
			||||||
 | 
						sign := ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Min int64 can't be negated to a usable value, so it has to be special cased.
 | 
				
			||||||
 | 
						if v == math.MinInt64 {
 | 
				
			||||||
 | 
							return "-9,223,372,036,854,775,808"
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if v < 0 {
 | 
				
			||||||
 | 
							sign = "-"
 | 
				
			||||||
 | 
							v = 0 - v
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						parts := []string{"", "", "", "", "", "", ""}
 | 
				
			||||||
 | 
						j := len(parts) - 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for v > 999 {
 | 
				
			||||||
 | 
							parts[j] = strconv.FormatInt(v%1000, 10)
 | 
				
			||||||
 | 
							switch len(parts[j]) {
 | 
				
			||||||
 | 
							case 2:
 | 
				
			||||||
 | 
								parts[j] = "0" + parts[j]
 | 
				
			||||||
 | 
							case 1:
 | 
				
			||||||
 | 
								parts[j] = "00" + parts[j]
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							v = v / 1000
 | 
				
			||||||
 | 
							j--
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						parts[j] = strconv.Itoa(int(v))
 | 
				
			||||||
 | 
						return sign + strings.Join(parts[j:], ",")
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Commaf produces a string form of the given number in base 10 with
 | 
				
			||||||
 | 
					// commas after every three orders of magnitude.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// e.g. Commaf(834142.32) -> 834,142.32
 | 
				
			||||||
 | 
					func Commaf(v float64) string {
 | 
				
			||||||
 | 
						buf := &bytes.Buffer{}
 | 
				
			||||||
 | 
						if v < 0 {
 | 
				
			||||||
 | 
							buf.Write([]byte{'-'})
 | 
				
			||||||
 | 
							v = 0 - v
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						comma := []byte{','}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						parts := strings.Split(strconv.FormatFloat(v, 'f', -1, 64), ".")
 | 
				
			||||||
 | 
						pos := 0
 | 
				
			||||||
 | 
						if len(parts[0])%3 != 0 {
 | 
				
			||||||
 | 
							pos += len(parts[0]) % 3
 | 
				
			||||||
 | 
							buf.WriteString(parts[0][:pos])
 | 
				
			||||||
 | 
							buf.Write(comma)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						for ; pos < len(parts[0]); pos += 3 {
 | 
				
			||||||
 | 
							buf.WriteString(parts[0][pos : pos+3])
 | 
				
			||||||
 | 
							buf.Write(comma)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						buf.Truncate(buf.Len() - 1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if len(parts) > 1 {
 | 
				
			||||||
 | 
							buf.Write([]byte{'.'})
 | 
				
			||||||
 | 
							buf.WriteString(parts[1])
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return buf.String()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// CommafWithDigits works like the Commaf but limits the resulting
 | 
				
			||||||
 | 
					// string to the given number of decimal places.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// e.g. CommafWithDigits(834142.32, 1) -> 834,142.3
 | 
				
			||||||
 | 
					func CommafWithDigits(f float64, decimals int) string {
 | 
				
			||||||
 | 
						return stripTrailingDigits(Commaf(f), decimals)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// BigComma produces a string form of the given big.Int in base 10
 | 
				
			||||||
 | 
					// with commas after every three orders of magnitude.
 | 
				
			||||||
 | 
					func BigComma(b *big.Int) string {
 | 
				
			||||||
 | 
						sign := ""
 | 
				
			||||||
 | 
						if b.Sign() < 0 {
 | 
				
			||||||
 | 
							sign = "-"
 | 
				
			||||||
 | 
							b.Abs(b)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						athousand := big.NewInt(1000)
 | 
				
			||||||
 | 
						c := (&big.Int{}).Set(b)
 | 
				
			||||||
 | 
						_, m := oom(c, athousand)
 | 
				
			||||||
 | 
						parts := make([]string, m+1)
 | 
				
			||||||
 | 
						j := len(parts) - 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						mod := &big.Int{}
 | 
				
			||||||
 | 
						for b.Cmp(athousand) >= 0 {
 | 
				
			||||||
 | 
							b.DivMod(b, athousand, mod)
 | 
				
			||||||
 | 
							parts[j] = strconv.FormatInt(mod.Int64(), 10)
 | 
				
			||||||
 | 
							switch len(parts[j]) {
 | 
				
			||||||
 | 
							case 2:
 | 
				
			||||||
 | 
								parts[j] = "0" + parts[j]
 | 
				
			||||||
 | 
							case 1:
 | 
				
			||||||
 | 
								parts[j] = "00" + parts[j]
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							j--
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						parts[j] = strconv.Itoa(int(b.Int64()))
 | 
				
			||||||
 | 
						return sign + strings.Join(parts[j:], ",")
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										40
									
								
								vendor/github.com/dustin/go-humanize/commaf.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								vendor/github.com/dustin/go-humanize/commaf.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,40 @@
 | 
				
			|||||||
 | 
					// +build go1.6
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package humanize
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"bytes"
 | 
				
			||||||
 | 
						"math/big"
 | 
				
			||||||
 | 
						"strings"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// BigCommaf produces a string form of the given big.Float in base 10
 | 
				
			||||||
 | 
					// with commas after every three orders of magnitude.
 | 
				
			||||||
 | 
					func BigCommaf(v *big.Float) string {
 | 
				
			||||||
 | 
						buf := &bytes.Buffer{}
 | 
				
			||||||
 | 
						if v.Sign() < 0 {
 | 
				
			||||||
 | 
							buf.Write([]byte{'-'})
 | 
				
			||||||
 | 
							v.Abs(v)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						comma := []byte{','}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						parts := strings.Split(v.Text('f', -1), ".")
 | 
				
			||||||
 | 
						pos := 0
 | 
				
			||||||
 | 
						if len(parts[0])%3 != 0 {
 | 
				
			||||||
 | 
							pos += len(parts[0]) % 3
 | 
				
			||||||
 | 
							buf.WriteString(parts[0][:pos])
 | 
				
			||||||
 | 
							buf.Write(comma)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						for ; pos < len(parts[0]); pos += 3 {
 | 
				
			||||||
 | 
							buf.WriteString(parts[0][pos : pos+3])
 | 
				
			||||||
 | 
							buf.Write(comma)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						buf.Truncate(buf.Len() - 1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if len(parts) > 1 {
 | 
				
			||||||
 | 
							buf.Write([]byte{'.'})
 | 
				
			||||||
 | 
							buf.WriteString(parts[1])
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return buf.String()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										46
									
								
								vendor/github.com/dustin/go-humanize/ftoa.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								vendor/github.com/dustin/go-humanize/ftoa.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,46 @@
 | 
				
			|||||||
 | 
					package humanize
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"strconv"
 | 
				
			||||||
 | 
						"strings"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func stripTrailingZeros(s string) string {
 | 
				
			||||||
 | 
						offset := len(s) - 1
 | 
				
			||||||
 | 
						for offset > 0 {
 | 
				
			||||||
 | 
							if s[offset] == '.' {
 | 
				
			||||||
 | 
								offset--
 | 
				
			||||||
 | 
								break
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if s[offset] != '0' {
 | 
				
			||||||
 | 
								break
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							offset--
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return s[:offset+1]
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func stripTrailingDigits(s string, digits int) string {
 | 
				
			||||||
 | 
						if i := strings.Index(s, "."); i >= 0 {
 | 
				
			||||||
 | 
							if digits <= 0 {
 | 
				
			||||||
 | 
								return s[:i]
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							i++
 | 
				
			||||||
 | 
							if i+digits >= len(s) {
 | 
				
			||||||
 | 
								return s
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return s[:i+digits]
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return s
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Ftoa converts a float to a string with no trailing zeros.
 | 
				
			||||||
 | 
					func Ftoa(num float64) string {
 | 
				
			||||||
 | 
						return stripTrailingZeros(strconv.FormatFloat(num, 'f', 6, 64))
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// FtoaWithDigits converts a float to a string but limits the resulting string
 | 
				
			||||||
 | 
					// to the given number of decimal places, and no trailing zeros.
 | 
				
			||||||
 | 
					func FtoaWithDigits(num float64, digits int) string {
 | 
				
			||||||
 | 
						return stripTrailingZeros(stripTrailingDigits(strconv.FormatFloat(num, 'f', 6, 64), digits))
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										8
									
								
								vendor/github.com/dustin/go-humanize/humanize.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								vendor/github.com/dustin/go-humanize/humanize.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,8 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					Package humanize converts boring ugly numbers to human-friendly strings and back.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Durations can be turned into strings such as "3 days ago", numbers
 | 
				
			||||||
 | 
					representing sizes like 82854982 into useful strings like, "83 MB" or
 | 
				
			||||||
 | 
					"79 MiB" (whichever you prefer).
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					package humanize
 | 
				
			||||||
							
								
								
									
										192
									
								
								vendor/github.com/dustin/go-humanize/number.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										192
									
								
								vendor/github.com/dustin/go-humanize/number.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,192 @@
 | 
				
			|||||||
 | 
					package humanize
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					Slightly adapted from the source to fit go-humanize.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Author: https://github.com/gorhill
 | 
				
			||||||
 | 
					Source: https://gist.github.com/gorhill/5285193
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"math"
 | 
				
			||||||
 | 
						"strconv"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var (
 | 
				
			||||||
 | 
						renderFloatPrecisionMultipliers = [...]float64{
 | 
				
			||||||
 | 
							1,
 | 
				
			||||||
 | 
							10,
 | 
				
			||||||
 | 
							100,
 | 
				
			||||||
 | 
							1000,
 | 
				
			||||||
 | 
							10000,
 | 
				
			||||||
 | 
							100000,
 | 
				
			||||||
 | 
							1000000,
 | 
				
			||||||
 | 
							10000000,
 | 
				
			||||||
 | 
							100000000,
 | 
				
			||||||
 | 
							1000000000,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						renderFloatPrecisionRounders = [...]float64{
 | 
				
			||||||
 | 
							0.5,
 | 
				
			||||||
 | 
							0.05,
 | 
				
			||||||
 | 
							0.005,
 | 
				
			||||||
 | 
							0.0005,
 | 
				
			||||||
 | 
							0.00005,
 | 
				
			||||||
 | 
							0.000005,
 | 
				
			||||||
 | 
							0.0000005,
 | 
				
			||||||
 | 
							0.00000005,
 | 
				
			||||||
 | 
							0.000000005,
 | 
				
			||||||
 | 
							0.0000000005,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// FormatFloat produces a formatted number as string based on the following user-specified criteria:
 | 
				
			||||||
 | 
					// * thousands separator
 | 
				
			||||||
 | 
					// * decimal separator
 | 
				
			||||||
 | 
					// * decimal precision
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Usage: s := RenderFloat(format, n)
 | 
				
			||||||
 | 
					// The format parameter tells how to render the number n.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// See examples: http://play.golang.org/p/LXc1Ddm1lJ
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Examples of format strings, given n = 12345.6789:
 | 
				
			||||||
 | 
					// "#,###.##" => "12,345.67"
 | 
				
			||||||
 | 
					// "#,###." => "12,345"
 | 
				
			||||||
 | 
					// "#,###" => "12345,678"
 | 
				
			||||||
 | 
					// "#\u202F###,##" => "12 345,68"
 | 
				
			||||||
 | 
					// "#.###,###### => 12.345,678900
 | 
				
			||||||
 | 
					// "" (aka default format) => 12,345.67
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// The highest precision allowed is 9 digits after the decimal symbol.
 | 
				
			||||||
 | 
					// There is also a version for integer number, FormatInteger(),
 | 
				
			||||||
 | 
					// which is convenient for calls within template.
 | 
				
			||||||
 | 
					func FormatFloat(format string, n float64) string {
 | 
				
			||||||
 | 
						// Special cases:
 | 
				
			||||||
 | 
						//   NaN = "NaN"
 | 
				
			||||||
 | 
						//   +Inf = "+Infinity"
 | 
				
			||||||
 | 
						//   -Inf = "-Infinity"
 | 
				
			||||||
 | 
						if math.IsNaN(n) {
 | 
				
			||||||
 | 
							return "NaN"
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if n > math.MaxFloat64 {
 | 
				
			||||||
 | 
							return "Infinity"
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if n < -math.MaxFloat64 {
 | 
				
			||||||
 | 
							return "-Infinity"
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// default format
 | 
				
			||||||
 | 
						precision := 2
 | 
				
			||||||
 | 
						decimalStr := "."
 | 
				
			||||||
 | 
						thousandStr := ","
 | 
				
			||||||
 | 
						positiveStr := ""
 | 
				
			||||||
 | 
						negativeStr := "-"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if len(format) > 0 {
 | 
				
			||||||
 | 
							format := []rune(format)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// If there is an explicit format directive,
 | 
				
			||||||
 | 
							// then default values are these:
 | 
				
			||||||
 | 
							precision = 9
 | 
				
			||||||
 | 
							thousandStr = ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// collect indices of meaningful formatting directives
 | 
				
			||||||
 | 
							formatIndx := []int{}
 | 
				
			||||||
 | 
							for i, char := range format {
 | 
				
			||||||
 | 
								if char != '#' && char != '0' {
 | 
				
			||||||
 | 
									formatIndx = append(formatIndx, i)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if len(formatIndx) > 0 {
 | 
				
			||||||
 | 
								// Directive at index 0:
 | 
				
			||||||
 | 
								//   Must be a '+'
 | 
				
			||||||
 | 
								//   Raise an error if not the case
 | 
				
			||||||
 | 
								// index: 0123456789
 | 
				
			||||||
 | 
								//        +0.000,000
 | 
				
			||||||
 | 
								//        +000,000.0
 | 
				
			||||||
 | 
								//        +0000.00
 | 
				
			||||||
 | 
								//        +0000
 | 
				
			||||||
 | 
								if formatIndx[0] == 0 {
 | 
				
			||||||
 | 
									if format[formatIndx[0]] != '+' {
 | 
				
			||||||
 | 
										panic("RenderFloat(): invalid positive sign directive")
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									positiveStr = "+"
 | 
				
			||||||
 | 
									formatIndx = formatIndx[1:]
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								// Two directives:
 | 
				
			||||||
 | 
								//   First is thousands separator
 | 
				
			||||||
 | 
								//   Raise an error if not followed by 3-digit
 | 
				
			||||||
 | 
								// 0123456789
 | 
				
			||||||
 | 
								// 0.000,000
 | 
				
			||||||
 | 
								// 000,000.00
 | 
				
			||||||
 | 
								if len(formatIndx) == 2 {
 | 
				
			||||||
 | 
									if (formatIndx[1] - formatIndx[0]) != 4 {
 | 
				
			||||||
 | 
										panic("RenderFloat(): thousands separator directive must be followed by 3 digit-specifiers")
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									thousandStr = string(format[formatIndx[0]])
 | 
				
			||||||
 | 
									formatIndx = formatIndx[1:]
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								// One directive:
 | 
				
			||||||
 | 
								//   Directive is decimal separator
 | 
				
			||||||
 | 
								//   The number of digit-specifier following the separator indicates wanted precision
 | 
				
			||||||
 | 
								// 0123456789
 | 
				
			||||||
 | 
								// 0.00
 | 
				
			||||||
 | 
								// 000,0000
 | 
				
			||||||
 | 
								if len(formatIndx) == 1 {
 | 
				
			||||||
 | 
									decimalStr = string(format[formatIndx[0]])
 | 
				
			||||||
 | 
									precision = len(format) - formatIndx[0] - 1
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// generate sign part
 | 
				
			||||||
 | 
						var signStr string
 | 
				
			||||||
 | 
						if n >= 0.000000001 {
 | 
				
			||||||
 | 
							signStr = positiveStr
 | 
				
			||||||
 | 
						} else if n <= -0.000000001 {
 | 
				
			||||||
 | 
							signStr = negativeStr
 | 
				
			||||||
 | 
							n = -n
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							signStr = ""
 | 
				
			||||||
 | 
							n = 0.0
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// split number into integer and fractional parts
 | 
				
			||||||
 | 
						intf, fracf := math.Modf(n + renderFloatPrecisionRounders[precision])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// generate integer part string
 | 
				
			||||||
 | 
						intStr := strconv.FormatInt(int64(intf), 10)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// add thousand separator if required
 | 
				
			||||||
 | 
						if len(thousandStr) > 0 {
 | 
				
			||||||
 | 
							for i := len(intStr); i > 3; {
 | 
				
			||||||
 | 
								i -= 3
 | 
				
			||||||
 | 
								intStr = intStr[:i] + thousandStr + intStr[i:]
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// no fractional part, we can leave now
 | 
				
			||||||
 | 
						if precision == 0 {
 | 
				
			||||||
 | 
							return signStr + intStr
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// generate fractional part
 | 
				
			||||||
 | 
						fracStr := strconv.Itoa(int(fracf * renderFloatPrecisionMultipliers[precision]))
 | 
				
			||||||
 | 
						// may need padding
 | 
				
			||||||
 | 
						if len(fracStr) < precision {
 | 
				
			||||||
 | 
							fracStr = "000000000000000"[:precision-len(fracStr)] + fracStr
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return signStr + intStr + decimalStr + fracStr
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// FormatInteger produces a formatted number as string.
 | 
				
			||||||
 | 
					// See FormatFloat.
 | 
				
			||||||
 | 
					func FormatInteger(format string, n int) string {
 | 
				
			||||||
 | 
						return FormatFloat(format, float64(n))
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										25
									
								
								vendor/github.com/dustin/go-humanize/ordinals.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								vendor/github.com/dustin/go-humanize/ordinals.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,25 @@
 | 
				
			|||||||
 | 
					package humanize
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import "strconv"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Ordinal gives you the input number in a rank/ordinal format.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Ordinal(3) -> 3rd
 | 
				
			||||||
 | 
					func Ordinal(x int) string {
 | 
				
			||||||
 | 
						suffix := "th"
 | 
				
			||||||
 | 
						switch x % 10 {
 | 
				
			||||||
 | 
						case 1:
 | 
				
			||||||
 | 
							if x%100 != 11 {
 | 
				
			||||||
 | 
								suffix = "st"
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						case 2:
 | 
				
			||||||
 | 
							if x%100 != 12 {
 | 
				
			||||||
 | 
								suffix = "nd"
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						case 3:
 | 
				
			||||||
 | 
							if x%100 != 13 {
 | 
				
			||||||
 | 
								suffix = "rd"
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return strconv.Itoa(x) + suffix
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										123
									
								
								vendor/github.com/dustin/go-humanize/si.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										123
									
								
								vendor/github.com/dustin/go-humanize/si.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,123 @@
 | 
				
			|||||||
 | 
					package humanize
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"errors"
 | 
				
			||||||
 | 
						"math"
 | 
				
			||||||
 | 
						"regexp"
 | 
				
			||||||
 | 
						"strconv"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var siPrefixTable = map[float64]string{
 | 
				
			||||||
 | 
						-24: "y", // yocto
 | 
				
			||||||
 | 
						-21: "z", // zepto
 | 
				
			||||||
 | 
						-18: "a", // atto
 | 
				
			||||||
 | 
						-15: "f", // femto
 | 
				
			||||||
 | 
						-12: "p", // pico
 | 
				
			||||||
 | 
						-9:  "n", // nano
 | 
				
			||||||
 | 
						-6:  "µ", // micro
 | 
				
			||||||
 | 
						-3:  "m", // milli
 | 
				
			||||||
 | 
						0:   "",
 | 
				
			||||||
 | 
						3:   "k", // kilo
 | 
				
			||||||
 | 
						6:   "M", // mega
 | 
				
			||||||
 | 
						9:   "G", // giga
 | 
				
			||||||
 | 
						12:  "T", // tera
 | 
				
			||||||
 | 
						15:  "P", // peta
 | 
				
			||||||
 | 
						18:  "E", // exa
 | 
				
			||||||
 | 
						21:  "Z", // zetta
 | 
				
			||||||
 | 
						24:  "Y", // yotta
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var revSIPrefixTable = revfmap(siPrefixTable)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// revfmap reverses the map and precomputes the power multiplier
 | 
				
			||||||
 | 
					func revfmap(in map[float64]string) map[string]float64 {
 | 
				
			||||||
 | 
						rv := map[string]float64{}
 | 
				
			||||||
 | 
						for k, v := range in {
 | 
				
			||||||
 | 
							rv[v] = math.Pow(10, k)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return rv
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var riParseRegex *regexp.Regexp
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func init() {
 | 
				
			||||||
 | 
						ri := `^([\-0-9.]+)\s?([`
 | 
				
			||||||
 | 
						for _, v := range siPrefixTable {
 | 
				
			||||||
 | 
							ri += v
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						ri += `]?)(.*)`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						riParseRegex = regexp.MustCompile(ri)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ComputeSI finds the most appropriate SI prefix for the given number
 | 
				
			||||||
 | 
					// and returns the prefix along with the value adjusted to be within
 | 
				
			||||||
 | 
					// that prefix.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// See also: SI, ParseSI.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// e.g. ComputeSI(2.2345e-12) -> (2.2345, "p")
 | 
				
			||||||
 | 
					func ComputeSI(input float64) (float64, string) {
 | 
				
			||||||
 | 
						if input == 0 {
 | 
				
			||||||
 | 
							return 0, ""
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						mag := math.Abs(input)
 | 
				
			||||||
 | 
						exponent := math.Floor(logn(mag, 10))
 | 
				
			||||||
 | 
						exponent = math.Floor(exponent/3) * 3
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						value := mag / math.Pow(10, exponent)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Handle special case where value is exactly 1000.0
 | 
				
			||||||
 | 
						// Should return 1 M instead of 1000 k
 | 
				
			||||||
 | 
						if value == 1000.0 {
 | 
				
			||||||
 | 
							exponent += 3
 | 
				
			||||||
 | 
							value = mag / math.Pow(10, exponent)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						value = math.Copysign(value, input)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						prefix := siPrefixTable[exponent]
 | 
				
			||||||
 | 
						return value, prefix
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// SI returns a string with default formatting.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// SI uses Ftoa to format float value, removing trailing zeros.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// See also: ComputeSI, ParseSI.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// e.g. SI(1000000, "B") -> 1 MB
 | 
				
			||||||
 | 
					// e.g. SI(2.2345e-12, "F") -> 2.2345 pF
 | 
				
			||||||
 | 
					func SI(input float64, unit string) string {
 | 
				
			||||||
 | 
						value, prefix := ComputeSI(input)
 | 
				
			||||||
 | 
						return Ftoa(value) + " " + prefix + unit
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// SIWithDigits works like SI but limits the resulting string to the
 | 
				
			||||||
 | 
					// given number of decimal places.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// e.g. SIWithDigits(1000000, 0, "B") -> 1 MB
 | 
				
			||||||
 | 
					// e.g. SIWithDigits(2.2345e-12, 2, "F") -> 2.23 pF
 | 
				
			||||||
 | 
					func SIWithDigits(input float64, decimals int, unit string) string {
 | 
				
			||||||
 | 
						value, prefix := ComputeSI(input)
 | 
				
			||||||
 | 
						return FtoaWithDigits(value, decimals) + " " + prefix + unit
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var errInvalid = errors.New("invalid input")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ParseSI parses an SI string back into the number and unit.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// See also: SI, ComputeSI.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// e.g. ParseSI("2.2345 pF") -> (2.2345e-12, "F", nil)
 | 
				
			||||||
 | 
					func ParseSI(input string) (float64, string, error) {
 | 
				
			||||||
 | 
						found := riParseRegex.FindStringSubmatch(input)
 | 
				
			||||||
 | 
						if len(found) != 4 {
 | 
				
			||||||
 | 
							return 0, "", errInvalid
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						mag := revSIPrefixTable[found[2]]
 | 
				
			||||||
 | 
						unit := found[3]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						base, err := strconv.ParseFloat(found[1], 64)
 | 
				
			||||||
 | 
						return base * mag, unit, err
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										117
									
								
								vendor/github.com/dustin/go-humanize/times.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										117
									
								
								vendor/github.com/dustin/go-humanize/times.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,117 @@
 | 
				
			|||||||
 | 
					package humanize
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
 | 
						"math"
 | 
				
			||||||
 | 
						"sort"
 | 
				
			||||||
 | 
						"time"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Seconds-based time units
 | 
				
			||||||
 | 
					const (
 | 
				
			||||||
 | 
						Day      = 24 * time.Hour
 | 
				
			||||||
 | 
						Week     = 7 * Day
 | 
				
			||||||
 | 
						Month    = 30 * Day
 | 
				
			||||||
 | 
						Year     = 12 * Month
 | 
				
			||||||
 | 
						LongTime = 37 * Year
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Time formats a time into a relative string.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Time(someT) -> "3 weeks ago"
 | 
				
			||||||
 | 
					func Time(then time.Time) string {
 | 
				
			||||||
 | 
						return RelTime(then, time.Now(), "ago", "from now")
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// A RelTimeMagnitude struct contains a relative time point at which
 | 
				
			||||||
 | 
					// the relative format of time will switch to a new format string.  A
 | 
				
			||||||
 | 
					// slice of these in ascending order by their "D" field is passed to
 | 
				
			||||||
 | 
					// CustomRelTime to format durations.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// The Format field is a string that may contain a "%s" which will be
 | 
				
			||||||
 | 
					// replaced with the appropriate signed label (e.g. "ago" or "from
 | 
				
			||||||
 | 
					// now") and a "%d" that will be replaced by the quantity.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// The DivBy field is the amount of time the time difference must be
 | 
				
			||||||
 | 
					// divided by in order to display correctly.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// e.g. if D is 2*time.Minute and you want to display "%d minutes %s"
 | 
				
			||||||
 | 
					// DivBy should be time.Minute so whatever the duration is will be
 | 
				
			||||||
 | 
					// expressed in minutes.
 | 
				
			||||||
 | 
					type RelTimeMagnitude struct {
 | 
				
			||||||
 | 
						D      time.Duration
 | 
				
			||||||
 | 
						Format string
 | 
				
			||||||
 | 
						DivBy  time.Duration
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var defaultMagnitudes = []RelTimeMagnitude{
 | 
				
			||||||
 | 
						{time.Second, "now", time.Second},
 | 
				
			||||||
 | 
						{2 * time.Second, "1 second %s", 1},
 | 
				
			||||||
 | 
						{time.Minute, "%d seconds %s", time.Second},
 | 
				
			||||||
 | 
						{2 * time.Minute, "1 minute %s", 1},
 | 
				
			||||||
 | 
						{time.Hour, "%d minutes %s", time.Minute},
 | 
				
			||||||
 | 
						{2 * time.Hour, "1 hour %s", 1},
 | 
				
			||||||
 | 
						{Day, "%d hours %s", time.Hour},
 | 
				
			||||||
 | 
						{2 * Day, "1 day %s", 1},
 | 
				
			||||||
 | 
						{Week, "%d days %s", Day},
 | 
				
			||||||
 | 
						{2 * Week, "1 week %s", 1},
 | 
				
			||||||
 | 
						{Month, "%d weeks %s", Week},
 | 
				
			||||||
 | 
						{2 * Month, "1 month %s", 1},
 | 
				
			||||||
 | 
						{Year, "%d months %s", Month},
 | 
				
			||||||
 | 
						{18 * Month, "1 year %s", 1},
 | 
				
			||||||
 | 
						{2 * Year, "2 years %s", 1},
 | 
				
			||||||
 | 
						{LongTime, "%d years %s", Year},
 | 
				
			||||||
 | 
						{math.MaxInt64, "a long while %s", 1},
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// RelTime formats a time into a relative string.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// It takes two times and two labels.  In addition to the generic time
 | 
				
			||||||
 | 
					// delta string (e.g. 5 minutes), the labels are used applied so that
 | 
				
			||||||
 | 
					// the label corresponding to the smaller time is applied.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// RelTime(timeInPast, timeInFuture, "earlier", "later") -> "3 weeks earlier"
 | 
				
			||||||
 | 
					func RelTime(a, b time.Time, albl, blbl string) string {
 | 
				
			||||||
 | 
						return CustomRelTime(a, b, albl, blbl, defaultMagnitudes)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// CustomRelTime formats a time into a relative string.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// It takes two times two labels and a table of relative time formats.
 | 
				
			||||||
 | 
					// In addition to the generic time delta string (e.g. 5 minutes), the
 | 
				
			||||||
 | 
					// labels are used applied so that the label corresponding to the
 | 
				
			||||||
 | 
					// smaller time is applied.
 | 
				
			||||||
 | 
					func CustomRelTime(a, b time.Time, albl, blbl string, magnitudes []RelTimeMagnitude) string {
 | 
				
			||||||
 | 
						lbl := albl
 | 
				
			||||||
 | 
						diff := b.Sub(a)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if a.After(b) {
 | 
				
			||||||
 | 
							lbl = blbl
 | 
				
			||||||
 | 
							diff = a.Sub(b)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						n := sort.Search(len(magnitudes), func(i int) bool {
 | 
				
			||||||
 | 
							return magnitudes[i].D > diff
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if n >= len(magnitudes) {
 | 
				
			||||||
 | 
							n = len(magnitudes) - 1
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						mag := magnitudes[n]
 | 
				
			||||||
 | 
						args := []interface{}{}
 | 
				
			||||||
 | 
						escaped := false
 | 
				
			||||||
 | 
						for _, ch := range mag.Format {
 | 
				
			||||||
 | 
							if escaped {
 | 
				
			||||||
 | 
								switch ch {
 | 
				
			||||||
 | 
								case 's':
 | 
				
			||||||
 | 
									args = append(args, lbl)
 | 
				
			||||||
 | 
								case 'd':
 | 
				
			||||||
 | 
									args = append(args, diff/mag.DivBy)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								escaped = false
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								escaped = ch == '%'
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return fmt.Sprintf(mag.Format, args...)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										2
									
								
								vendor/modules.txt
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								vendor/modules.txt
									
									
									
									
										vendored
									
									
								
							@@ -121,6 +121,8 @@ github.com/denisenkom/go-mssqldb/internal/decimal
 | 
				
			|||||||
github.com/denisenkom/go-mssqldb/internal/querytext
 | 
					github.com/denisenkom/go-mssqldb/internal/querytext
 | 
				
			||||||
# github.com/dgrijalva/jwt-go v3.2.0+incompatible
 | 
					# github.com/dgrijalva/jwt-go v3.2.0+incompatible
 | 
				
			||||||
github.com/dgrijalva/jwt-go
 | 
					github.com/dgrijalva/jwt-go
 | 
				
			||||||
 | 
					# github.com/dustin/go-humanize v1.0.0
 | 
				
			||||||
 | 
					github.com/dustin/go-humanize
 | 
				
			||||||
# github.com/editorconfig/editorconfig-core-go/v2 v2.1.1
 | 
					# github.com/editorconfig/editorconfig-core-go/v2 v2.1.1
 | 
				
			||||||
github.com/editorconfig/editorconfig-core-go/v2
 | 
					github.com/editorconfig/editorconfig-core-go/v2
 | 
				
			||||||
# github.com/edsrzf/mmap-go v1.0.0
 | 
					# github.com/edsrzf/mmap-go v1.0.0
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1631,6 +1631,10 @@
 | 
				
			|||||||
                                padding-top: 8px;
 | 
					                                padding-top: 8px;
 | 
				
			||||||
                                padding-bottom: 8px;
 | 
					                                padding-bottom: 8px;
 | 
				
			||||||
                                border-bottom: 1px solid #eeeeee;
 | 
					                                border-bottom: 1px solid #eeeeee;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                                a > .text.right {
 | 
				
			||||||
 | 
					                                    margin-right: 5px;
 | 
				
			||||||
 | 
					                                }
 | 
				
			||||||
                            }
 | 
					                            }
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user