├── .gitignore
├── COPYING
├── Makefile
├── ONEFETCH.md
├── README.md
├── img
├── default-light.png
├── git-light-large.png
├── git-light.png
├── onefetch-gfe-light.png
└── onefetch-light.png
├── lib
├── human.sh
└── util.sh
├── src
├── ascii.sh
├── authors.sh
├── commits.sh
├── created.sh
├── defconfig.sh
├── gitver.sh
├── head.sh
├── languages.sh
├── latest.sh
├── loc.sh
├── main.sh
├── project.sh
├── showinfo.sh
├── srcsize.sh
├── upstream.sh
├── user.sh
└── version.sh
└── tests
├── lib.sh
└── main.sh
/.gitignore:
--------------------------------------------------------------------------------
1 | bin/
2 | tmp/
3 |
4 | **/*.*.sw[po]
5 |
--------------------------------------------------------------------------------
/COPYING:
--------------------------------------------------------------------------------
1 | MIT License
2 | ===========
3 |
4 | - Copyright © 2020 Kiëd Llaentenn
5 |
6 | Permission is hereby granted, free of charge, to any person obtaining a copy
7 | of this software and associated documentation files (the "Software"), to deal
8 | in the Software without restriction, including without limitation the rights to
9 | (mis)use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | copies of the Software, and to permit persons to whom the Software is furnished
11 | to do so, subject to the following conditions:
12 |
13 | - The above copyright notice and this permission notice shall be included in all
14 | copies or substantial portions of the Software.
15 |
16 | THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | THE SOFTWARE.
23 |
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | #
2 | # gfe: git fetch script
3 | # https://github.com/lptstr/gfe
4 | #
5 | # (c) Kiëd Llaentenn
6 | # See the COPYING file for more information
7 | #
8 |
9 | .POSIX:
10 |
11 | CMD =
12 |
13 | PREFIX = /usr/local
14 | DESTDIR =
15 |
16 | BIN = gfe
17 | OBJDIR = bin
18 |
19 | CAT = $(shell which cat)
20 | CHMOD = $(shell which chmod)
21 | RM = $(shell which rm)
22 | INSTALL = $(shell which install)
23 |
24 | SRC = lib/human.sh lib/util.sh \
25 | src/commits.sh src/created.sh src/head.sh \
26 | src/latest.sh src/authors.sh src/gitver.sh \
27 | src/project.sh src/srcsize.sh src/user.sh \
28 | src/upstream.sh src/version.sh src/languages.sh \
29 | src/loc.sh \
30 | src/defconfig.sh src/showinfo.sh src/ascii.sh \
31 | src/main.sh
32 |
33 | all: bin/$(BIN)
34 |
35 | clean:
36 | $(CMD)$(RM) -rf $(OBJDIR)
37 |
38 | $(OBJDIR):
39 | $(CMD)mkdir -p $(OBJDIR)
40 |
41 | $(OBJDIR)/$(BIN): $(OBJDIR) $(SRC)
42 | $(CMD)printf "#!/bin/sh\n# gfe: git fetch\n\n" | \
43 | $(CAT) - $(SRC) > $(OBJDIR)/$(BIN)
44 | $(CMD)$(CHMOD) +x $(OBJDIR)/$(BIN)
45 |
46 | run:
47 | @$(OBJDIR)/$(BIN)
48 |
49 | install: $(OBJDIR)/$(BIN)
50 | $(CMD)$(INSTALL) -Dm755 $(OBJDIR)/$(BIN) \
51 | $(DESTDIR)/$(PREFIX)/bin/$(BIN)
52 |
53 | uninstall:
54 | $(CMD)$(RM) -f $(DESTDIR)/$(PREFIX)/bin/$(BIN)
55 |
56 | check: tests/main.sh
57 | $(CMD)tests/main.sh
58 |
59 | .PHONY: all clean $(OBJDIR)/$(BIN) run install uninstall check
60 |
--------------------------------------------------------------------------------
/ONEFETCH.md:
--------------------------------------------------------------------------------
1 | # onefetch vs gfetch
2 |
3 | > NOTE: if you think any comparison here is unfair in the least to Onefetch,
4 | > submit an issue and I will remove it.
5 |
6 | ## design
7 |
8 | It's probably only me, but when I first started using Onefetch, I began to feel
9 | as if Onefetch was designed only for pretty screenshots. Huge ASCII art that
10 | can't be disabled, a strange license field, a *colorblocks* field (how on earth
11 | does the terminal's colorscheme relate to Git), written in Rust, slow for large
12 | projects.
13 |
14 |
16 |
17 | Again, it's probably only me, but I don't really like the fact that it's written
18 | in Rust. I've worked on a fetch tool in Rust myself [1](#f1) ,
19 | and I've come to the conclusion that Rust is *probably* not the best tool for a
20 | fetch program. Shell is a great language for a fetch tool, because all a fetch
21 | tool really does is extract text from commands and various files. And the fact
22 | that they're all in a hundred different formats doesn't matter either, because
23 | you can easily utilize `awk` and `sed` to massage it into the format you want.
24 |
25 |
27 |
28 | Onefetch solves the problem of text extraction by using various libraries (e.g.
29 | the `git2` crate) instead of running commands. [2](#f2)
30 | Again, probably only me, but I don't like that either. I like to see what
31 | commands my fetch tool is running, if only for the education.
32 |
33 | On the other hand, `gfetch` was designed for fetching information. I don't want
34 | you to wait while the you fetches all the information before printing
35 | it, I want it now! And when you do, I don't want a huge 40-column ASCII art with
36 | the logo of the language I'm using. I already know what language it's written
37 | in, and even if I didn't, the `Language` field is quite enough. And BTW, let me
38 | display my *own* info fields when I want to. The default ASCII can be ugly, I
39 | don't care, because I want to see the info, not the art.
40 |
41 |
42 | #### *This document is a work in progress.*
43 |
44 | 1. See [rsfetch](https://github.com/rsfetch/rsfetch)
45 | [↩](#a1)
46 | 2. Note, I only did a very cursory examination of the Onefetch
47 | source, so I'm probably a bit off there. [↩](#a2)
48 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
gfetch
2 | what? | where? | how? | why? | faq | license
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 | `gfetch` is a tiny, lightweight Git fetch script that can be used as an alternative
18 | to [`onefetch`](https://github.com/o2sh/onefetch).
19 |
20 | ## what?
21 |
22 | `gfetch` runs a various commands (e.g. `git rev-list --count --all`) to
23 | retrieve some statistics (e.g. current branch) for the current project.
24 | It's just a little convenience utility to prevent having to run ten
25 | different commands and parsing with grep or sed.
26 |
27 | Compared to Onefetch, `gfetch` is
28 |
29 | - **small**: the entire script is less than 300 lines of code (not counting
30 | comments).
31 | - **fast**: shows information for the `git` repository in just a few seconds.
32 | - **POSIX**: runs on just about any modern POSIX shell: `bash`, `dash`, `mksh`,
33 | `loksh`, anything short of `tcsh` or `mksh`.
34 | - **less distracting**. `gfetch` does not have and never will have
35 | huge, ridiculous ASCII art that takes up half the screen.
36 | - **configurable**. This fetch script was designed from the ground up to be
37 | completely configurable, down to the order of the information fields. Every
38 | single field -- even the (small) ASCII art -- can be disabled.
39 |
40 | Note that `gfetch` is still in very early stages. Expect bugs, incorrect
41 | information, and lots of missing features.
42 |
43 | ## where?
44 |
45 | You will need:
46 |
47 | - a Unix-like system (Windows support is planned)
48 | - a fairly modern version of Git (duh)
49 | - a POSIX-compliant shell. (so no fish, tcsh, etc)
50 | - GNU sed and GNU awk (other sed/awk implementations *might* work, but are
51 | untested.)
52 | - GNU Make (the Makefile is incompatible with `bmake`)
53 | - SCC (optional, only required for language detection and LOC count)
54 |
55 | Then, simply grab a release tarball from the GitHub releases, extract, and run:
56 |
57 | ```
58 | $ make clean all
59 | # make install
60 | ```
61 |
62 | NOTE: ensure that the `/usr/local/bin` path is directory is in your path first,
63 | since that's where it's installed by default. If you want to install to a
64 | different location (e.g. `/usr/bin`) you can run `make PREFIX=/usr install`
65 | instead.
66 |
67 | ## how?
68 |
69 | Ensure that the `gfe` script is in your path, then execute it.
70 |
71 | **Configuration** is done by editing the shell script at
72 | `~/.config/gfe/config.sh`, which is created by default if it doesn't exist.
73 | It is then `source`d by `gfe` on startup.
74 |
75 | The configuration file consists of some environment variable definitions,
76 | which are only set if they are empty. This allows them to be overridden at
77 | runtime.
78 |
79 | The list of environment variables is as follows:
80 |
81 | ```
82 | # ensure that you use the
83 | # form GFE_VALUE=\${GFE_VALUE:-othervalue}
84 | # to ensure that it can be overridden on
85 | # the command line!!
86 | #
87 | # GFE_LOGO: path to file with ASCII art.
88 | # if it\'s value is not a valid file, then
89 | # it is treated as ASCII art itself.
90 | GFE_LOGO=\"\${GFE_LOGO:-}\"
91 |
92 | # GFE_ALIGN: number of spaces for padding between
93 | # name and info columnds
94 | GFE_ALIGN=\"\${GFE_ALIGN:-13}\"
95 |
96 | # GFE_COL1: color for the first column (the
97 | # name column). possible values: 1-7
98 | GFE_COL1=\"\${GFE_COL1:-1}\"
99 |
100 | # GFE_COL2: color for the second column (the
101 | # info column). possible values: 1-7
102 | GFE_COL2=\"\${GFE_COL2:-7}\"
103 |
104 | # GFE_COL3: color for the header/title.
105 | # possible values: 1-7
106 | GFE_COL3=\"\${GFE_COL3:-1}\"
107 |
108 | # GFE_SEP: character or text to separate each name
109 | # and info line.
110 | # e.g. using the value ':' would become 'name: info'
111 | # in output.
112 | GFE_SEP=\"\${GFE_SEP:-}\"
113 |
114 | # GFE_DIR: directory/repository for gfetch to cd
115 | # into.
116 | GFE_DIR=\"\${GFE_DIR:-}\"
117 |
118 | # GFE_AUTHOR_MAX: maximum number of authors for the
119 | # AUTHORS gfe field.
120 | GFE_AUTHORS_MAX=\"\${GFE_AUTHORS_MAX:-2}\"
121 |
122 | # GFE_LANG_MAX: maximum number of languages for the
123 | # LANGUAGES gfe field.
124 | GFE_LANG_MAX=\"\${GFE_LANG_MAX:-2}\"
125 | ```
126 |
127 | The config file also contains `gfe_info()` function, which is executed
128 | by `gfe` to show the information. It looks something like this:
129 |
130 | ```
131 | gfe_info() {
132 | # print a newline.
133 | printf ''
134 |
135 | # print the default ASCII art.
136 | # note that the show_ascii() function must be
137 | # the FIRST if it is used.
138 | show_ascii
139 |
140 | # print a Onefetch-esque header, with the
141 | # Git username and Git version.
142 | # usage: showheader
143 | showheader "$(get_user)" "$(get_gitver)" " ~ "
144 |
145 | # Each showinfo call prints one row of info.
146 | # By default, all available info is printed.
147 | # each command inside the "$()" is a gfetch
148 | # function to get information.
149 | #
150 | # if you wish, you can even display your own text
151 | # with the showinfo function.
152 | # e.g. showinfo "$(hostname)" "HOSTNAME"
153 |
154 | # usage: showinfo
155 | showinfo "$(get_project_name)" 'PROJECT'
156 |
157 | # note: get_head_long() shows the branch name
158 | # as well as latest commit. if you want to see
159 | # only the latest commit, you can use the
160 | # get_head() function instead.
161 | showinfo "$(get_head_long)" 'HEAD'
162 |
163 | showinfo "$(get_version)" 'VERSION'
164 | showinfo "$(get_created)" 'CREATED'
165 | showinfo "$(get_languages)" 'LANGUAGES'
166 | showinfo "$(get_authors)" 'AUTHORS'
167 | showinfo "$(get_latest)" 'LAST CHANGE'
168 | showinfo "$(get_upstream)" 'UPSTREAM'
169 | showinfo "$(get_commit_count)" 'COMMITS'
170 | showinfo "$(get_loc)" 'LOC'
171 | showinfo "$(get_srcsize)" 'SOURCE SIZE'
172 |
173 | # print a newline.
174 | printf ''
175 | }
176 | ```
177 |
178 | By default, all available information is printed.
179 |
180 | ## why?
181 |
182 | See [ONEFETCH.md](ONEFETCH.md) for a Onefetch vs gfetch comparison.
183 |
184 | ## faq
185 |
186 | - **Q**: Why is a lambda the default ASCII art?
187 | - **A**: well, it's supposed to be a branch. (you know,
188 | `git branch`?) If you think you can do better, feel free to submit an
189 | issue with your ASCII art :)
190 | - **Q**: Are there any plans to add language-specific ASCII art (as in Onefetch)?
191 | - **A**: Eventually. The goal is to first add other missing info fields
192 | and further optimize the code.
193 |
194 | ## license
195 |
196 | `gfetch` is licensed under the MIT license. See [COPYING](COPYING) for
197 | more information.
198 |
--------------------------------------------------------------------------------
/img/default-light.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kiedtl/gfetch/554242d2240072fba57ee4e948e136813accee89/img/default-light.png
--------------------------------------------------------------------------------
/img/git-light-large.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kiedtl/gfetch/554242d2240072fba57ee4e948e136813accee89/img/git-light-large.png
--------------------------------------------------------------------------------
/img/git-light.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kiedtl/gfetch/554242d2240072fba57ee4e948e136813accee89/img/git-light.png
--------------------------------------------------------------------------------
/img/onefetch-gfe-light.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kiedtl/gfetch/554242d2240072fba57ee4e948e136813accee89/img/onefetch-gfe-light.png
--------------------------------------------------------------------------------
/img/onefetch-light.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kiedtl/gfetch/554242d2240072fba57ee4e948e136813accee89/img/onefetch-light.png
--------------------------------------------------------------------------------
/lib/human.sh:
--------------------------------------------------------------------------------
1 | # human.sh - convert sizes to human-readable sizes
2 | # (c) Kiëd Llaentenn
3 | # See the COPYING file for copyright information.
4 |
5 | human() {
6 | cat | awk \
7 | 'function human(x) {
8 | if (x<1000) {return x} else {x/=1024}
9 | s="kMGTEPZY";
10 | while (x>=1000 && length(s)>1)
11 | {x/=1024; s=substr(s,2)}
12 | return int(x+0.5) substr(s,1,1)
13 | }
14 | {sub(/^[0-9]+/, human($1)); print}'
15 | }
16 |
--------------------------------------------------------------------------------
/lib/util.sh:
--------------------------------------------------------------------------------
1 | # util.sh: random stuff
2 | # (c) Kiëd Llaentenn
3 | # See the COPYING file for copyright information.
4 |
5 | get_sccdata() {
6 | # get outta here if this function
7 | # was already called
8 | [ -z "$scc_data" ] || return
9 |
10 | # although tokei is faster, many distros don't
11 | # have binaries compiled with the JSON feature.
12 | # (to be specific, my distro, Void.)
13 | # so we're using scc instead.
14 |
15 | # since we use scc to count lines of code, we
16 | # first check if it's in $PATH
17 | if ! command -v scc 2>/dev/null >&2
18 | then
19 | scc_data="unknown (scc not found)"
20 | return
21 | fi
22 |
23 | scc_data="$(scc -fcsv)"
24 | }
25 |
--------------------------------------------------------------------------------
/src/ascii.sh:
--------------------------------------------------------------------------------
1 | # ascii.sh - (gfe module) handle ASCII art
2 | # (c) Kiëd Llaentenn
3 | # See the COPYING file for copyright information.
4 |
5 |
6 | show_ascii() {
7 |
8 | # set color variables
9 | #
10 | # disable warning about unused variables
11 | # and warning about using ${} when expanding
12 | # arrays.
13 | #
14 | # shellcheck disable=1087,2034
15 | {
16 | esc="$(printf '\033')"
17 | c1="$esc[31m"
18 | c2="$esc[32m"
19 | c3="$esc[33m"
20 | c4="$esc[34m"
21 | c5="$esc[35m"
22 | c6="$esc[36m"
23 | c7="$esc[37m"
24 | c8="$esc[38m"
25 | revert="$esc[7m"
26 | reset="$esc[0m"
27 | }
28 |
29 | # set the default ASCII art.
30 | # FIXME: better default Git art.
31 | default_ascii=$(cat <<-EOF
32 | ${c1}${revert} ${reset}
33 | ${c1}${revert} \ ${reset}
34 | ${c1}${revert} o ${reset}
35 | ${c1}${revert} / \ ${reset}
36 | ${c1}${revert} / \ ${reset}
37 | ${c1}${revert} o o ${reset}
38 | ${c1}${revert} ${reset}
39 | EOF
40 | )
41 |
42 | # check if user-defined variable is a file
43 | # if it is not, treat it like raw ascii art
44 | if [ -n "$GFE_LOGO" ]
45 | then
46 | if [ -f "$GFE_LOGO" ]
47 | then
48 | case $(file "$GFE_LOGO") in
49 | *PNG*|*JPEG*)
50 | if ! command -v chafa 2>/dev/null >&2
51 | then
52 | echo "error: chafa not found."
53 | return
54 | fi
55 |
56 | ascii="$(chafa -s 25 "$GFE_LOGO")"
57 | ascii_width=25
58 | ;;
59 | *)
60 | ascii="$(cat "$GFE_LOGO")"
61 | ;;
62 | esac
63 | else
64 | ascii="$GFE_LOGO"
65 | fi
66 | else
67 | ascii="$default_ascii"
68 | fi
69 |
70 | # set the width of the ASCII art for the
71 | # showinfo function if it wasn't already set
72 | # before
73 | if [ -z "$ascii_width" ]
74 | then
75 | while read -r line
76 | do
77 | [ "${#line}" -gt "${ascii_width:-0}" ] &&
78 | ascii_width="${#line}"
79 | done <<-EOF
80 | $(printf '%s' "$ascii" | sed "s/\x1b\[.m//g")
81 | EOF
82 | fi
83 |
84 | # draw ASCII art and move cursor up again.
85 | printf "$ascii\033[%sA\033[%sD" \
86 | "$(printf '%s' "$ascii" | wc -l)" "$ascii_width"
87 |
88 | # add some padding to ascii_width
89 | ascii_width=$((ascii_width+3))
90 | }
91 |
--------------------------------------------------------------------------------
/src/authors.sh:
--------------------------------------------------------------------------------
1 | # user.sh - (gfe module) retrieve git username
2 | # (c) Kiëd Llaentenn
3 | # See the COPYING file for copyright information.
4 |
5 | get_authors() {
6 | # get total amount of commits
7 | total="$(git rev-list --count --all)"
8 |
9 | # get list of all commits, listing authors only.
10 | # group like authors together, then use uniq -c
11 | # to get the number of commits per author.
12 | # Once that is done, we can sort again by
13 | # commit count and simply conver the commit count
14 | # to a percentage.
15 | git --no-pager log --format="%aN" | \
16 | sort | \
17 | uniq -c | \
18 | sort -bnr | \
19 | while read -r commits author
20 | do
21 | percentage="$(((commits*100)/total))"
22 | echo "$percentage% $author $commits"
23 | done | \
24 | head -n "$GFE_AUTHORS_MAX"
25 | }
26 |
--------------------------------------------------------------------------------
/src/commits.sh:
--------------------------------------------------------------------------------
1 | # commits.sh - (gfe module) retrieve number of commits
2 | # (c) Kiëd Llaentenn
3 | # See the COPYING file for copyright information.
4 |
5 | get_commit_count() {
6 | git rev-list --count --all
7 | }
8 |
--------------------------------------------------------------------------------
/src/created.sh:
--------------------------------------------------------------------------------
1 | # created.sh - (gfe module) retrieve date of "first" commit
2 | # (c) Kiëd Llaentenn
3 | # See the COPYING file for copyright information.
4 |
5 | get_created() {
6 | git log \
7 | --reverse \
8 | --format="%ar" | sed 1q
9 | }
10 |
--------------------------------------------------------------------------------
/src/defconfig.sh:
--------------------------------------------------------------------------------
1 | # defconfig.sh - (gfe resource) default configuration
2 | # (c) Kiëd Llaentenn
3 | # see COPYING for more details
4 |
5 | # disable shellcheck warnings about
6 | # unused variables.
7 | #
8 | # shellcheck disable=2034
9 | defconfig="
10 | # gfetch configuration
11 | #
12 | # ensure that you use the
13 | # form GFE_VALUE=\${GFE_VALUE:-othervalue}
14 | # to ensure that it can be overridden on
15 | # the command line!!
16 | #
17 | # GFE_LOGO: path to file with ASCII art.
18 | # if it\'s value is not a valid file, then
19 | # it is treated as ASCII art itself.
20 | GFE_LOGO=\"\${GFE_LOGO:-}\"
21 |
22 | # GFE_ALIGN: number of spaces for padding between
23 | # name and info columnds
24 | GFE_ALIGN=\"\${GFE_ALIGN:-13}\"
25 |
26 | # GFE_COL1: color for the first column (the
27 | # name column). possible values: 1-7
28 | GFE_COL1=\"\${GFE_COL1:-1}\"
29 |
30 | # GFE_COL2: color for the second column (the
31 | # info column). possible values: 1-7
32 | GFE_COL2=\"\${GFE_COL2:-7}\"
33 |
34 | # GFE_COL3: color for the header/title.
35 | # possible values: 1-7
36 | GFE_COL3=\"\${GFE_COL3:-1}\"
37 |
38 | # GFE_SEP: character or text to separate each name
39 | # and info line.
40 | # e.g. using the value ':' would become 'name: info'
41 | # in output.
42 | GFE_SEP=\"\${GFE_SEP:-}\"
43 |
44 | # GFE_DIR: directory/repository for gfetch to cd
45 | # into.
46 | GFE_DIR=\"\${GFE_DIR:-}\"
47 |
48 | # GFE_AUTHOR_MAX: maximum number of authors for the
49 | # AUTHORS gfe field.
50 | GFE_AUTHORS_MAX=\"\${GFE_AUTHORS_MAX:-2}\"
51 |
52 | # GFE_LANG_MAX: maximum number of languages for the
53 | # LANGUAGES gfe field.
54 | GFE_LANG_MAX=\"\${GFE_LANG_MAX:-2}\"
55 |
56 | # main configuration. gfetch will simply execute
57 | # the gfe_info function on startup.
58 | #
59 | # each showinfo() call displays an info field.
60 | # showinfo usage: showinfo
61 | #
62 | # if you wish, you can even display your own text
63 | # with the showinfo function.
64 | # e.g. showinfo \"\$(git --version)\" \"GIT\"
65 | #
66 | # to display a header/title, use the showheader function.
67 | # showheader usage: showheader
68 | #
69 | # to display ASCII art, use the show_ascii
70 | # function without any parameters.
71 | #
72 | # NOTE: if the show_ascii function is used, it MUST
73 | # be the first item.
74 | gfe_info() {
75 | printf '\n'
76 | show_ascii
77 | showheader \"\$(get_user)\" \"\$(get_gitver)\" \" ~ \"
78 | showinfo \"\$(get_project_name)\" 'PROJECT'
79 | showinfo \"\$(get_head_long)\" 'HEAD'
80 | showinfo \"\$(get_version)\" 'VERSION'
81 | showinfo \"\$(get_created)\" 'CREATED'
82 | showinfo \"\$(get_languages)\" 'LANGUAGES'
83 | showinfo \"\$(get_authors)\" 'AUTHORS'
84 | showinfo \"\$(get_latest)\" 'LAST CHANGE'
85 | showinfo \"\$(get_upstream)\" 'UPSTREAM'
86 | showinfo \"\$(get_commit_count)\" 'COMMITS'
87 | showinfo \"\$(get_loc)\" 'LOC'
88 | showinfo \"\$(get_srcsize)\" 'SOURCE SIZE'
89 | printf '\n'
90 | }
91 | "
92 |
--------------------------------------------------------------------------------
/src/gitver.sh:
--------------------------------------------------------------------------------
1 | # gitver.sh - (gfe module) get git version.
2 | # (c) Kiëd Llaentenn
3 | # See the COPYING file for copyright information.
4 |
5 | get_gitver() {
6 | ver=$(git --version | awk '{ print $3 }')
7 | printf "git v%s" "$ver"
8 | }
9 |
--------------------------------------------------------------------------------
/src/head.sh:
--------------------------------------------------------------------------------
1 | # head.sh - (gfe module) retrieve latest commit sha
2 | # (c) Kiëd Llaentenn
3 | # See the COPYING file for copyright information.
4 |
5 | get_head() {
6 | git log -1 --format="%h"
7 | }
8 |
9 | # show branch in addition to HEAD
10 | get_head_long() {
11 | # retrieve branch, printing "detached"
12 | # if in detached HEAD state
13 | branch="$(git branch --show-current)"
14 | branch="${branch:-detached}"
15 |
16 | printf '%s (%s)' "$(get_head)" "$branch"
17 | }
18 |
--------------------------------------------------------------------------------
/src/languages.sh:
--------------------------------------------------------------------------------
1 | # languages - (gfe module) grab list of languages.
2 | # (c) Kiëd Llaentenn
3 | # See the COPYING file for copyright information.
4 |
5 | get_languages() {
6 | get_sccdata
7 |
8 | # sort -fcsv: get CSV data, listing LOC for each file
9 | # awk -F, ...: convert it to a list of LOC per language
10 | # sort -rn -t, ...: sort list by LOC in ascending order
11 | # awk -F, ...: remove LOC column
12 | # head -n$GFE_LANG_MAX: get only two first languages
13 | # tr '\n' ' ': finally, transform newlines to spaces
14 | # shellcheck disable=2154
15 | echo "$scc_data" | \
16 | awk -F, -v CONVFMT=%.2g \
17 | '
18 | {
19 | c[$1]+=$5;
20 | total+=$5
21 | }
22 |
23 | END {
24 | for (i in c) {
25 | p=(c[i]*100)/total;
26 | print i "," c[i] ",(" p " %)"
27 | }
28 | }' | \
29 | sort -rn -t, -k2 | \
30 | awk -F, '{ print $1 " " $3 }' | \
31 | head -n"$GFE_LANG_MAX" | \
32 | tr '\n' ' '
33 | }
34 |
--------------------------------------------------------------------------------
/src/latest.sh:
--------------------------------------------------------------------------------
1 | # latest.sh - (gfe module) get date of last commit
2 | # (c) Kiëd Llaentenn
3 | # See the COPYING file for copyright information.
4 |
5 | get_latest() {
6 | git log --format="%ar" | head -n1
7 | }
8 |
--------------------------------------------------------------------------------
/src/loc.sh:
--------------------------------------------------------------------------------
1 | # loc.sh - (gfe module) get lines of code.
2 | # (c) Kiëd Llaentenn
3 | # See the COPYING file for copyright information.
4 |
5 | get_loc() {
6 | get_sccdata
7 |
8 | # the sed command is used to add thousands-
9 | # separators to the number.
10 | # unix.stackexchange.com/questions/113795/add-thousands-separator-in-a-number
11 | #
12 | # disable warning about undefined
13 | # '$scc_data', since it's already defined
14 | # in lib/util.sh
15 | # shellcheck disable=2154
16 | loc="$(echo "$scc_data" | \
17 | awk -F, '{ loc+=$5 } END { print loc }' | \
18 | sed ':a;s/\B[0-9]\{3\}\>/,&/;ta')"
19 | printf '%s lines' "$loc"
20 | }
21 |
--------------------------------------------------------------------------------
/src/main.sh:
--------------------------------------------------------------------------------
1 | main() {
2 | # ensure that git, sed, and awk are installed
3 | if ! command -v git 2>/dev/null >&2
4 | then
5 | printf 'error: git not found.\n'
6 | return;
7 | fi
8 |
9 | if ! command -v sed 2>/dev/null >&2
10 | then
11 | printf 'error: sed not found.\n'
12 | return;
13 | fi
14 |
15 | if ! command -v awk 2>/dev/null >&2
16 | then
17 | printf 'error: awk not found.\n'
18 | return;
19 | fi
20 |
21 | # find project's root directory and cd there.
22 | if [ -z "$GFE_DIR" ]
23 | then
24 | cd "$(git rev-parse --show-toplevel)" || exit 1
25 | else
26 | cd "$GFE_DIR" || exit 1
27 | fi
28 |
29 | # check if configuration file exists, otherwise
30 | # write default configuration.
31 | configdir="${XDG_CONFIG_HOME}/gfe"
32 | [ ! -d "$configdir" ] && mkdir -p "$configdir"
33 | config="$configdir/config.sh"
34 |
35 | # disable warnings about undefined variable
36 | # shellcheck disable=2154
37 | [ ! -f "$config" ] && echo "$defconfig" > "$config"
38 |
39 | # execute configuration
40 | # shellcheck disable=1090
41 | . "$config"
42 | gfe_info
43 | }
44 |
45 | main "$@"
46 |
--------------------------------------------------------------------------------
/src/project.sh:
--------------------------------------------------------------------------------
1 | # project.sh - (gfe module) retrieve project name
2 | # (c) Kiëd Llaentenn
3 | # See the COPYING file for copyright information.
4 |
5 | # TODO: scrape actual project name
6 | # out of git origin or README
7 | get_project_name() {
8 | basename "$(pwd)"
9 | }
10 |
--------------------------------------------------------------------------------
/src/showinfo.sh:
--------------------------------------------------------------------------------
1 | # showinfo - gfe module: print information
2 | # (c) Kied Llaentenn
3 | # see the COPYING file for more information.
4 |
5 | showinfo() {
6 | # return if no information found
7 | # TODO: print error message instead of silently
8 | # failing
9 | val="$1"
10 | [ -z "$val" ] && return
11 |
12 | key=$2
13 |
14 | # move cursor right beyond ascii art
15 | #
16 | # disable warning about undefined ascii_width
17 | # shellcheck disable=2154
18 | printf "\033[%sC" "$ascii_width"
19 |
20 | # print key and separator
21 | printf "\033[1;3%sm%-${GFE_ALIGN}s\033[0m%s" \
22 | "$GFE_COL1" "$key" "$GFE_SEP"
23 |
24 | # print information, one line at a time
25 | echo "$val" | while read -r line
26 | do
27 | printf '\033[3%sm%s\033[0m' "$GFE_COL2" "$line"
28 |
29 | # WORKAROUND: move cursor forward again
30 | # just in case this info field has multiple lines.
31 | # this is so that multi-lined info fields are
32 | # aligned properly.
33 | printf '\n\033[%sC' "$((ascii_width+GFE_ALIGN))"
34 | done
35 |
36 | # WORKAROUND: move cursor back, so that next
37 | # info field isn't misaligned.
38 | printf '\033[%sD' "$((ascii_width+GFE_ALIGN))"
39 | }
40 |
41 | showheader() {
42 | e="$(printf '\033')"
43 |
44 | # shellcheck disable=1087
45 | showinfo " " \
46 | "$e[1;3${GFE_COL3}m$1$e[0m$3$e[1;3${GFE_COL3}m$2$e[0m"
47 | }
48 |
--------------------------------------------------------------------------------
/src/srcsize.sh:
--------------------------------------------------------------------------------
1 | # srcsize.sh - (gfe module) retreive size of source code
2 | # (c) Kiëd Llaentenn
3 | # See the COPYING file for copyright information.
4 |
5 | get_srcsize() {
6 | # get a list of files that are tracked by git.
7 | files="$(git ls-files)"
8 | count="$(echo "$files" | wc -l)"
9 |
10 | # disable warning about globbing, since it's
11 | # intended.
12 | # shellcheck disable=2086
13 | size="$(du -sb $files 2>/dev/null | \
14 | awk '{ sz+=$1 } END { print sz }')"
15 |
16 | # convert to human-readable format.
17 | hsize=$(echo "$size" | human)
18 |
19 | printf '%s (%s files)' "$hsize" "$count"
20 | }
21 |
--------------------------------------------------------------------------------
/src/upstream.sh:
--------------------------------------------------------------------------------
1 | # upstream.sh - (gfe module) get upstream url
2 | # (c) Kiëd Llaentenn
3 | # See the COPYING file for copyright information.
4 |
5 | get_upstream() {
6 | # get current remote for current branch
7 | remote=$(git branch -lvv | \
8 | awk '/*/ { print $4 }' | \
9 | sed 's/[]\[]//g;y|/| |;s/ .*$//g')
10 |
11 | # get url for remote
12 | git remote get-url "$remote" --push
13 | }
14 |
--------------------------------------------------------------------------------
/src/user.sh:
--------------------------------------------------------------------------------
1 | # user.sh - (gfe module) retrieve git username
2 | # (c) Kiëd Llaentenn
3 | # See the COPYING file for copyright information.
4 |
5 | get_user() {
6 | git config --get user.name
7 | }
8 |
--------------------------------------------------------------------------------
/src/version.sh:
--------------------------------------------------------------------------------
1 | # version.sh - (gfe module) get latest tag name
2 | # (c) Kiëd Llaentenn
3 | # See the COPYING file for copyright information.
4 |
5 | get_version() {
6 | # list tags, sorting by tag date
7 | # then remove empty lines and
8 | # show only last line
9 | git tag --list \
10 | --sort=taggerdate | \
11 | tail -n1
12 | }
13 |
--------------------------------------------------------------------------------
/tests/lib.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | #
3 | # (c) Kiëd Llaentenn
4 | # See the COPYING file for copyright information.
5 |
6 | PASSED=0
7 | FAILED=0
8 |
9 | header() {
10 | printf '\n== %s\n' "$1"
11 | }
12 |
13 | # usage: test_command
14 | test_command() {
15 | if $1 2>/dev/null >&2
16 | then
17 | printf '✔ | %s\n' "$2"
18 | PASSED=$((PASSED+1))
19 | else
20 | printf '✖ | %s\n' "$2"
21 | FAILED=$((FAILED+1))
22 | fi
23 | }
24 |
25 | end() {
26 | printf '\n'
27 | printf '== completed %s tests. %s passed, %s failed.\n' \
28 | "$((PASSED+FAILED))" "$PASSED" "$FAILED"
29 | }
30 |
--------------------------------------------------------------------------------
/tests/main.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | #
3 | # (c) Kiëd Llaentenn
4 | # See the COPYING file for copyright information.
5 |
6 | . tests/lib.sh
7 |
8 | # run shellcheck
9 | header "testing for shellcheck"
10 | test_command "command -v shellcheck 2>/dev/null >&2" \
11 | "Shellcheck installed"
12 |
13 | header "linting source files"
14 | for file in src/*
15 | do
16 | test_command "shellcheck -e2148 $file" \
17 | "Passed shellcheck: '$file'"
18 | done
19 |
20 | header "linting tests files"
21 | test_command "shellcheck tests/main.sh tests/lib.sh" \
22 | "Passed shellcheck: tests/main.sh tests/lib.sh"
23 |
24 | end
25 |
--------------------------------------------------------------------------------