Splux Linux

source-based Linux using SPS

splux-site · log · files · refs · tags · releases · people · languages · GitHub · file

tools/git-lang.awk


Awk

4393 bytes at 4c4f12c · GitHub

# Detect a file's GitHub Linguist language from tools/linguist.map.
# mode=detect  -v path= -v shebang=   print name, type, color, group
# mode=count   stdin: size TAB path TAB shebang
#              print group TAB bytes TAB color  (programming+markup only)
# map file: kind key name type color group

function loadmap(    line, f, k) {
	while ((getline line < mapfile) > 0) {
		split(line, f, "\t")
		if (f[1] == "ext") {
			k = tolower(f[2])
			if (!(k in extname)) {
				extname[k] = f[3]
				exttype[k] = f[4]
				extcolor[k] = f[5]
				extgroup[k] = f[6]
			}
		} else if (f[1] == "filename") {
			if (!(f[2] in fnname)) {
				fnname[f[2]] = f[3]
				fntype[f[2]] = f[4]
				fncolor[f[2]] = f[5]
				fngroup[f[2]] = f[6]
			}
		} else if (f[1] == "interpreter") {
			if (!(f[2] in intname)) {
				intname[f[2]] = f[3]
				inttype[f[2]] = f[4]
				intcolor[f[2]] = f[5]
				intgroup[f[2]] = f[6]
			}
		} else if (f[1] == "lang") {
			langtype[f[3]] = f[4]
			langcolor[f[3]] = f[5]
			langgroup[f[3]] = f[6]
		}
	}
	close(mapfile)
	# Linguist heuristics default these ambiguous extensions.
	prefer(".md", "Markdown")
	prefer(".markdown", "Markdown")
	prefer(".scm", "Scheme")
	fnname["recipe"] = "Shell"
	fntype["recipe"] = "programming"
	fncolor["recipe"] = "#89e051"
	fngroup["recipe"] = "Shell"
	fnname["Recipe"] = "Shell"
	fntype["Recipe"] = "programming"
	fncolor["Recipe"] = "#89e051"
	fngroup["Recipe"] = "Shell"
}

function prefer(ext, lang) {
	ext = tolower(ext)
	if (!(lang in langtype))
		return
	extname[ext] = lang
	exttype[ext] = langtype[lang]
	extcolor[ext] = langcolor[lang]
	extgroup[ext] = (langgroup[lang] != "") ? langgroup[lang] : lang
}

function skip_stats(p) {
	return p ~ /(^|\/)(vendor|third_party|node_modules|dist|docs|doc|man|manpages|documentation)\//
}

function interpreter_of(line,    s, n, a, i, cmd) {
	s = line
	sub(/\r$/, "", s)
	if (s !~ /^#!/)
		return ""
	sub(/^#![ \t]*/, "", s)
	n = split(s, a, /[ \t]+/)
	if (n < 1)
		return ""
	cmd = a[1]
	sub(/^.*\//, "", cmd)
	if (cmd == "env" && n >= 2) {
		i = 2
		while (i <= n && a[i] ~ /^-/)
			i++
		if (i <= n)
			cmd = a[i]
		sub(/^.*\//, "", cmd)
	}
	sub(/[0-9]+$/, "", cmd)
	return cmd
}

function detect(path, shebang,    base, interp, p, ext, i, n, parts) {
	d_name = ""
	d_type = ""
	d_color = ""
	d_group = ""
	base = path
	sub(/^.*\//, "", base)

	if (base != "" && (base in fnname)) {
		d_name = fnname[base]
		d_type = fntype[base]
		d_color = fncolor[base]
		d_group = fngroup[base]
		return
	}

	interp = interpreter_of(shebang)
	if (interp != "" && (interp in intname)) {
		d_name = intname[interp]
		d_type = inttype[interp]
		d_color = intcolor[interp]
		d_group = intgroup[interp]
		return
	}

	p = tolower(base)
	n = split(p, parts, /\./)
	if (n >= 2) {
		ext = ""
		for (i = 2; i <= n; i++) {
			if (ext != "")
				ext = ext "."
			ext = ext parts[i]
			key = "." ext
			if (key in extname) {
				d_name = extname[key]
				d_type = exttype[key]
				d_color = extcolor[key]
				d_group = extgroup[key]
			}
		}
		if (d_name != "")
			return
	}

	p = tolower(path)
	n = split(p, parts, /\./)
	if (n >= 2) {
		ext = "." parts[n]
		if (ext in extname) {
			d_name = extname[ext]
			d_type = exttype[ext]
			d_color = extcolor[ext]
			d_group = extgroup[ext]
		}
	}
}

BEGIN {
	FS = "\t"
	OFS = "\t"
	if (mapfile == "")
		mapfile = "tools/linguist.map"
	loadmap()
	if (mode == "count" && filelang != "") {
		printf "" > filelang
		close(filelang)
	}
	if (mode == "detect") {
		detect(path, shebang)
		if (d_name != "")
			print d_name, d_type, d_color, d_group
		exit
	}
}

mode == "count" {
	detect($2, $3)
	if (filelang != "") {
		g = (d_group != "") ? d_group : d_name
		print $2 "\t" d_name "\t" d_type "\t" d_color "\t" $1 "\t" g >> filelang
	}
	if (skip_stats($2))
		next
	if (d_type != "programming" && d_type != "markup")
		next
	g = (d_group != "") ? d_group : d_name
	if (g == "")
		next
	bytes[g] += $1 + 0
	if (!(g in color) && d_color != "")
		color[g] = d_color
}

END {
	if (mode != "count")
		exit
	n = 0
	for (g in bytes) {
		n++
		names[n] = g
		vals[n] = bytes[g]
	}
	# sort by bytes descending
	for (i = 1; i <= n; i++) {
		for (j = i + 1; j <= n; j++) {
			if (vals[j] > vals[i]) {
				t = vals[i]; vals[i] = vals[j]; vals[j] = t
				t = names[i]; names[i] = names[j]; names[j] = t
			}
		}
	}
	for (i = 1; i <= n; i++)
		print names[i], vals[i], color[names[i]]
}