Explorar el Código

Add basic language display

This needs to be cleaned up a bit still, the stats need to move into the
`#repo` element.
Lucas Stadler %!s(int64=8) %!d(string=hace) años
padre
commit
93c17ab476
Se han modificado 1 ficheros con 181 adiciones y 9 borrados
  1. 181 9
      quit.go

+ 181 - 9
quit.go

@ -6,10 +6,12 @@ import (
6 6
	"html/template"
7 7
	"io"
8 8
	"log"
9
	"math"
9 10
	"net/http"
10 11
	"os"
11 12
	"path"
12 13
	"path/filepath"
14
	"sort"
13 15
	"strings"
14 16
	"time"
15 17
@ -52,11 +54,12 @@ func main() {
52 54
}
53 55
54 56
type FancyRepo struct {
55
	repo         *git.Repository
56
	commit       *FancyCommit
57
	commitCount  int
58
	branches     []*git.Branch
59
	contributors []*git.Signature
57
	repo          *git.Repository
58
	commit        *FancyCommit
59
	commitCount   int
60
	branches      []*git.Branch
61
	contributors  []*git.Signature
62
	languageStats *LanguageStats
60 63
}
61 64
62 65
func NewFancyRepo(repo *git.Repository) *FancyRepo {
@ -166,6 +169,134 @@ func (fr *FancyRepo) Tags() ([]string, error) {
166 169
	return fr.repo.Tags.List()
167 170
}
168 171
172
var languageSuffixes = map[string]string{
173
	".c":            "C",
174
	".h":            "C",
175
	".cpp":          "C++",
176
	"CMakeList.txt": "CMake",
177
	".css":          "CSS",
178
	".go":           "Go",
179
	".html":         "HTML",
180
	".js":           "JavaScript",
181
	".java":         "Java",
182
	"Makefile":      "Makefile",
183
	".py":           "Python",
184
	".rb":           "Ruby",
185
	".rs":           "Rust",
186
	".sh":           "Shell",
187
	".bash":         "Shell",
188
}
189
190
var languageColors = map[string]string{
191
	"C":   "#555555",
192
	"C++": "#f34b7d",
193
	//"CMake": "",
194
	"CSS":        "#563d7c",
195
	"Go":         "#375eab",
196
	"HTML":       "#e34c26",
197
	"JavaScript": "#f1e05a",
198
	"Java":       "#b07219",
199
	"Makefile":   "#427819",
200
	"Python":     "#3572A5",
201
	"Ruby":       "#701516",
202
	"Rust":       "#dea584",
203
	"Shell":      "#89e051",
204
}
205
206
func fileToLanguage(filename string) string {
207
	filename = strings.ToLower(filename)
208
	for suffix, lang := range languageSuffixes {
209
		if strings.HasSuffix(filename, suffix) {
210
			return lang
211
		}
212
	}
213
	return ""
214
}
215
216
type LanguageStats struct {
217
	percentages map[string]float64
218
	Languages   []*LanguageInfo
219
}
220
221
type LanguageInfo struct {
222
	Language   string
223
	Percentage float64
224
}
225
226
func (li *LanguageInfo) String() string {
227
	return fmt.Sprintf("%s (%.2f%%)", li.Language, li.Percentage)
228
}
229
230
type languageByPercent []*LanguageInfo
231
232
func (l languageByPercent) Len() int           { return len(l) }
233
func (l languageByPercent) Less(i, j int) bool { return l[i].Percentage < l[j].Percentage }
234
func (l languageByPercent) Swap(i, j int)      { l[i], l[j] = l[j], l[i] }
235
236
func NewLanguageStats(percentages map[string]float64) *LanguageStats {
237
	for lang, percentage := range percentages {
238
		if percentage < 0.001 {
239
			delete(percentages, lang)
240
			continue
241
		}
242
243
		percentage = math.Trunc(percentage*10000) / 100
244
		percentages[lang] = percentage
245
	}
246
247
	languages := make([]*LanguageInfo, 0, len(percentages))
248
	for lang, percentage := range percentages {
249
		languages = append(languages, &LanguageInfo{Language: lang, Percentage: percentage})
250
	}
251
	sort.Sort(sort.Reverse(languageByPercent(languages)))
252
253
	return &LanguageStats{
254
		percentages: percentages,
255
		Languages:   languages,
256
	}
257
}
258
259
func (li *LanguageStats) String() string {
260
	return fmt.Sprintf("%v", li.percentages)
261
}
262
263
func (fr *FancyRepo) LanguageStats() (*LanguageStats, error) {
264
	if fr.languageStats == nil {
265
		commit, err := fr.Commit()
266
		if err != nil {
267
			return nil, err
268
		}
269
270
		files, err := commit.Files(true)
271
		if err != nil {
272
			return nil, err
273
		}
274
275
		total := 0
276
		languages := make(map[string]int)
277
		for _, f := range files {
278
			if f.entry.Type != git.ObjectBlob {
279
				continue
280
			}
281
282
			lang := fileToLanguage(f.Name())
283
			if lang == "" {
284
				continue
285
			}
286
			total += 1
287
			languages[lang] += 1
288
289
		}
290
291
		percentages := make(map[string]float64)
292
		for lang, count := range languages {
293
			percentages[lang] = float64(count) / float64(total)
294
		}
295
		fr.languageStats = NewLanguageStats(percentages)
296
	}
297
	return fr.languageStats, nil
298
}
299
169 300
type FancyCommit struct {
170 301
	commit     *git.Commit
171 302
	files      []*FancyFile
@ -227,16 +358,20 @@ func (fc *FancyCommit) Description() string {
227 358
	return fc.commit.Message()
228 359
}
229 360
230
func (fc *FancyCommit) Files() ([]*FancyFile, error) {
361
func (fc *FancyCommit) Files(recursive bool) ([]*FancyFile, error) {
231 362
	if fc.files == nil {
232 363
		tree, err := fc.commit.Tree()
233 364
		if err != nil {
234 365
			return nil, err
235 366
		}
236 367
368
		recurse := 1
369
		if recursive {
370
			recurse = 0
371
		}
237 372
		err = tree.Walk(func(s string, entry *git.TreeEntry) int {
238 373
			fc.files = append(fc.files, NewFancyFile(fc.commit.Owner(), entry))
239
			return 1
374
			return recurse
240 375
		})
241 376
		if err != nil {
242 377
			return nil, err
@ -331,7 +466,16 @@ func (fc *FancyFile) Contents() (template.HTML, error) {
331 466
	return template.HTML(buf.String()), nil
332 467
}
333 468
334
var repoTmpl = template.Must(template.New("").Parse(`<!doctype html>
469
var repoFuncs = template.FuncMap{
470
	"languageToColor": func(l string) string {
471
		c, ok := languageColors[l]
472
		if !ok {
473
			return "black"
474
		}
475
		return c
476
	},
477
}
478
var repoTmpl = template.Must(template.New("").Funcs(repoFuncs).Parse(`<!doctype html>
335 479
<html>
336 480
	<head>
337 481
		<meta charset="utf-8" />
@ -347,6 +491,23 @@ var repoTmpl = template.Must(template.New("").Parse(`<!doctype html>
347 491
			<a id="contributors" class="repo-stat" href="#"><span class="icon">👥</span><span class="count">{{ len .Repo.Contributors }}</span> contributors</a>
348 492
		</section>
349 493
494
		<div id="languages">
495
			<ol class="language-list">
496
			{{ range $language := .Repo.LanguageStats.Languages }}
497
				<li>
498
					<span class="language">{{ $language.Language }}</span>
499
					<span class="percentage">{{ $language.Percentage }}%</span>
500
				</li>
501
			{{ end }}
502
			</ol>
503
504
			<div id="language-bar">
505
			{{ range $language := .Repo.LanguageStats.Languages }}
506
				<span class="language" title="{{ $language }}" style="width: {{ $language.Percentage }}%; background-color: {{ languageToColor $language.Language }}"><!--{{ $language.Language }}--></span>
507
			{{ end }}
508
			</div>
509
		</div>
510
350 511
		<section id="commit" class="commit-info">
351 512
			<div class="commit-author">{{ .Repo.Commit.Author }}</div>
352 513
			<div class="commit-summary" title="{{ .Repo.Commit.Description }}">{{ .Repo.Commit.Summary }}</div>
@ -355,7 +516,7 @@ var repoTmpl = template.Must(template.New("").Parse(`<!doctype html>
355 516
		</section>
356 517
357 518
		<table id="files">
358
			{{ range $file := .Repo.Commit.Files }}
519
			{{ range $file := .Repo.Commit.Files false }}
359 520
			<tr class="file">
360 521
				<td class="file-name file-type-{{ $file.Type }}">{{ $file.Name }}</td>
361 522
			</tr>
@ -416,6 +577,17 @@ body {
416 577
	padding-right: 0.2em;
417 578
}
418 579
580
.language-list {
581
  display: none;
582
}
583
584
#language-bar {
585
  display: flex;
586
  width: 70vw;
587
  height: 0.5em;
588
  margin: -1em 0 1em;
589
}
590
419 591
#commit {
420 592
  display: flex;
421 593
  justify-content: space-between;