X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=reprap-play.git;a=blobdiff_plain;f=commitid.scad.pl;h=3b20d6275ec4a11a25f4b01e85cc0386141b1664;hp=375d2eb0a8db87eadd5c60d6a2db6bb6dc6dbf89;hb=ec68479632e04d4675682e9bdc1b87d6b720a705;hpb=f23591aac0b82855fd9d049f06bd2dc284a99c71 diff --git a/commitid.scad.pl b/commitid.scad.pl index 375d2eb..3b20d62 100755 --- a/commitid.scad.pl +++ b/commitid.scad.pl @@ -4,60 +4,184 @@ use strict; $SIG{__WARN__} = sub { die @_; }; # xxx much of the comment below is TODO - -# We generate a physical indication of which commit was used. # -# We provide for a scaling factor +# Usage: +# +# .../commitid.scad.pl [OPTION...] [STRING...] >commitid.scad.new \ +# && mv -f commitid.scad.new commitid.scad +# +# Options: +# +# --git generate git commit indications, as shown below +# (this is the default if no strings are requested with -t) +# +# --git=object +# generate git commit indication based on commit object only +# (ie avoid counting commits) +# +# -i do not generate `+' if git-untracked files are present # -# $Commitid_pixelsz = 0.4; -# $Commitid_depth = 1.5; // in pixels +# [-t[FORM]] TEXT +# generate a form FORM containing TEXT +# TEXT can contain newlines (final newline usually undesirable) +# if FORM not specified, generates Arg0 Arg1 Arg2 in sequence +# character set is SPC 0-9 a-f + * +# +# We generate a physical indication of which commit was used. +# +# We provide for scaling factors with dynamic variables: +# $Commitid_pixelsz if not set, we use 0.8 } multiplied +# $Commitid_scale if not set, we use 1.0 } together +# $Commitid_depth if not set, we use xy pixel size from above / 2 +# $Commitid_depth_scale if not set, we use 1.0 (multiplies depth above) +# $Commitid_max_best_scale if not set, we use 2.0 (max mult of xy in Best) # # For each form we have # -# module Commitid_Form_2D(pixelsz=0.4) -# module Commitid_Form(pixelsz=0.4, depth=pixelsz) +# module Commitid_Form_2D() { ... } +# module Commitid_Form() { ... } +# function Commitid_Form_sz() => [ x, y ] # -# function Commitid_Form_size(pixelsz=$Commitid_pixelsz) => [ xsz, ysz ] -# +# These have their origin in the bottom left corner. The 3D model +# is a positive, has its origin halfway through, and is twice the +# depth in height, so it can be added or subtracted. +# +# And we provide +# +# function Commitid_pixelsz() // $Commitid_pixelsz * $Commitid_scale +# function Commitid_depth() // see above # # We can generate these forms: # -# Tiny3: -# Tiny4: -# Tiny5: -# Tiny6: -# Tiny7: -# Tiny8: +# In each case: +# if tree is dirty, * is suffixed or prefixed to count or commitid +# if tree has untracked files, + is added +# (where it is added depends on the Form; in any case it does not +# change the size, but steals space from digits) +# +# Small2 Small3 ... Small10: # git rev-list --first-parent --count HEAD # typically 3-4 characters but we allow for up to 6 -# eg -# Tiny4 1070 -# -# Tiny4Q: -# Tiny6Q: -# Tiny9Q: -# same but in two lines eg -# Tiny4Q 10 -# 70 -# -# Git4 -# Git6 -# Git8 -# git-rev-parse HEAD -# eg -# Git6 82f2a2 +# padded with zeroes; if too long we reduce mod 10^n +# eg if the count is 123456 +# Small5 3456* +# Small8 _*123456 (where _ are spaces) +# the git objectid is included if it will fit +# unambiguously and usefully eg +# Small9 ab*123456 +# +# Small2S Small4S ... Small10S: +# Small3T Small9T: +# same but split into two lines (S) or three lines (T) eg +# Small4S 45 Small6T _3 +# 6* 45 +# 6* +# +# Git2 Git3 ... Git10: +# Git4S Git6S ... Git10S: +# Git6T Git9T: +# git-rev-parse HEAD (prefix of requested length) +# eg if the commitid is abcdef0123... +# Git5 abcd* -# Small4 -# Small6 -# Small8 +# Full4 Full6 ... Full20: # git-rev-list --first-parent --count HEAD # git-rev-parse HEAD +# (all on two lines) # eg -# Small6 1070 -# 82f2a2 +# Full6 abcdef Full8 abcdef01 +# 23456* _123456* +# +# Full6T Full9T ... Full30T +# as Full but commit is split over two lines +# for a 3-line message; eg +# Full9T abc +# de* +# 456 +# +# FontDemo +# +# Arg0, Arg1, ... +# Strings passed on command line sub p { print @_ or die $!; } +p <<'END'; +// *** AUTOGENERATED - DO NOT EDIT *** // +function Commitid_pixelsz() = + ($Commitid_pixelsz ? $Commitid_pixelsz : 0.8) * + ($Commitid_scale ? $Commitid_scale : 1.0); +function Commitid_depth() = + ($Commitid_depth ? $Commitid_depth : Commitid_pixelsz()/2) * + ($Commitid_depth_scale ? $Commitid_depth_scale : 1.0); +function Commitid__scale() = + Commitid_pixelsz() / 0.2; +END + +sub chrmodname ($) { + my ($chr) = @_; + my $chrx = sprintf '%#x', ord $chr; + return "Commitid__chr_$chrx"; +} + +our $gtm_demo_i = -1; +our $gtm_demo_j; +our @gtm_demo_o; + +sub gentextmodule_demo_start_batch () { + $gtm_demo_j = 0; + $gtm_demo_i++; +} + +sub gen3dmodule ($@) { + my ($modb,@argl) = (@_); + p "module ${modb}(".(join ', ', @argl)."){\n"; + p " d=Commitid_depth();\n"; + p " translate([0,0,-d]) linear_extrude(height=d*2)\n"; + p " ${modb}_2D(".(join ',', map { m/=/ ? $` : $_ } @argl).");\n"; + p "}\n"; +} + +sub gentextmodule ($@) { + my ($form, @lines) = @_; + my $modb = "Commitid_$form"; + p "module ${modb}_2D(){\n"; + p " // |$_|\n" foreach @lines; + p " scale(Commitid__scale()){\n"; + my $y = @lines; + my $cols = 1; + foreach my $line (@lines) { + $y--; + my $x = 0; + foreach my $chr (split //, $line) { + p sprintf " translate([%d * 0.8, %d * 1.2]) %s();\n", + $x, $y, chrmodname $chr + if $chr =~ m/\S/; + $x++; + } + $cols = $x if $x > $cols; + } + p " }\n"; + p "}\n"; + gen3dmodule($modb); + + p sprintf "function %s_sz() = Commitid__scale() * 0.1 * [ %d, %d ];\n", + $modb, 2 * ($cols * 4 - 1), 2 * (@lines * 6 - 1); + + push @gtm_demo_o, <) { next unless m/\S/; + chomp; my @chrs = split / /, $_; !~ m/\S/ or die; foreach my $row (reverse 0..4) { @@ -92,8 +217,8 @@ sub parsefont () { } elsif (s{^\S}{}) { my $f = $cellmap{$&}; die unless $f; - $f =~ s/\b\d/ sprintf '%05d', $col*4000 + $&*2050 /ge; - $f =~ s/\d\b/ sprintf '%05d', $row*4000 + $&*2050 /ge; + $f =~ s/\b\d/ sprintf '%05d', $col*2000 + $&*1025 /ge; + $f =~ s/\d\b/ sprintf '%05d', $row*2000 + $&*1025 /ge; push @{ $chrpolys{$chr} }, [ split / /, $f ]; } else { die "$_ ?"; @@ -104,11 +229,10 @@ sub parsefont () { } } - my @demo; + my $demo = ''; my $democols = 6; foreach my $chr (sort keys %chrpolys) { - my $chrx = sprintf '%#x', ord $chr; - my $mod = "Commitid__chr_$chrx"; + my $mod = chrmodname $chr; p "module $mod () {\n"; foreach my $poly (@{ $chrpolys{$chr} }) { p " polygon(["; @@ -123,21 +247,258 @@ sub parsefont () { p "]);\n"; } p "}\n"; - my $px = @demo % $democols; - my $py = int(@demo / $democols); - push @demo, " translate([$px * 1.600, $py * 2.400]) $mod ();\n"; + $demo .= $chr; + } + @demo = reverse $demo =~ m{.{1,$democols}}go; +} + +parsefont(); + +our $do_git; # contains may chars 'c' (count) and/or 'o' (object) +our $do_git_untracked = 1; +our $argcounter; + +our @forms; + +sub rjustt ($$;$) { # right justify and truncate (ie, pad and truncate at left) + # always includes prefix + my ($sz, $whole, $prefix) = @_; + $prefix //= ''; + my $lw = length $whole; + my $spare = $sz - $lw - (length $prefix); + return + ($spare > 0 ? (' ' x $spare) : ''). + $prefix. + substr($whole, ($spare < 0 ? -$spare : 0)); +} + +sub ljustt ($$;$) { + my ($sz, $whole, $suffix) = @_; + $suffix //= ''; + $sz -= length $suffix; + return sprintf "%-${sz}.${sz}s%s", $whole, $suffix; +} + +sub genform ($@) { + my ($form, @lines) = @_; + gentextmodule($form, @lines); + my $f = { + Form => $form, + Chars => (length join '', @lines), + Lines => (scalar @lines), + Ambiguous => ($form =~ m/Full/ && !grep { m/\W/ } @lines), + }; + push @forms, $f; +} + +sub genform_q ($$$) { + my ($form, $s, $lines) = @_; + $gtm_demo_j++; + my $l = length $s; + return if $l % $lines; + my $e = $l/$lines; + return if $e < 2; + $gtm_demo_j--; + genform($form, $s =~ m/.{$e}/g); +} + +sub genform_plusq ($$) { + my ($form, $s) = @_; + genform($form, $s); + genform_q("${form}S", $s, 2); + genform_q("${form}T", $s, 3); +} + +our @gcmd; + +sub gitrun_start () { + open F, "-|", @gcmd or die "$gcmd[0]: start: $!"; +} + +sub gitrun_done (;$) { + my ($errok) = @_; + $?=0; $!=0; + return if close F; + return if $errok; + die $! if $!; + die "@gcmd failed ($?)\n"; +} + +sub gitoutput (@) { + (@gcmd) = (qw(git), @_); + gitrun_start; + $_ = ; + gitrun_done; + defined or die "@gcmd produced no output"; + chomp or die "@gcmd produced no final newline"; + $_; +} + +sub do_git () { + return unless $do_git; + + @gcmd = qw(git status --porcelain); + push @gcmd, qw(--untracked=no) unless $do_git_untracked; + + my $git_dirty = ''; + gitrun_start; + while () { + if (m/^\?\?/ && $do_git_untracked) { + $git_dirty = '+'; + next; + } + $git_dirty = '*'; + last; + } + gitrun_done($git_dirty eq '*'); + + my $git_count; + my $git_object; + + if ($do_git =~ m/c/) { + $git_count = gitoutput qw(rev-list --first-parent --count HEAD); + } + if ($do_git =~ m/o/) { + $git_object = gitoutput qw(rev-parse HEAD); } - p "module Commitid_FontDemo(){\n"; - p $_ foreach @demo; + + foreach my $sz (2..10) { + gentextmodule_demo_start_batch(); + + if (defined($git_count)) { + my $smallstr = rjustt($sz, $git_count, $git_dirty); + if (defined($git_object) && $sz >= length($git_count) + 3) { + $smallstr = $git_object; + $smallstr .= ($git_dirty || ' '); + $smallstr .= $git_count; + $smallstr = rjustt($sz, $smallstr); + } + genform_plusq("Small$sz", $smallstr); + } + + genform_plusq("Git$sz", ljustt($sz, $git_object, $git_dirty)) + if defined $git_object; + + if (defined $git_count && defined $git_object) { + genform("Full".($sz*2), + ljustt($sz, $git_object), + rjustt($sz, $git_count, $git_dirty)); + + my $e = $sz; + genform("Full".($e*3)."T", + ljustt($e*2, $git_object, $git_dirty) + =~ m/.{$e}/g, + rjustt($e, $git_count)); + } + } +} + +sub do_some_best ($$) { + my ($modname, $formre) = @_; + my $fullmodname = "Commitid_${modname}_2D"; + my @argl = qw(max_sz margin=Commitid_pixelsz()); + p "module $fullmodname(".(join ', ', @argl).") {\n"; + my $mbs = '$Commitid_max_best_scale'; + p " sc_max = $mbs ? $mbs : 2;\n"; + p " sz = max_sz - 2*[margin,margin];\n"; + my @do; + foreach my $f ( + sort { + $b->{Chars} <=> $a->{Chars} or + $a->{Lines} <=> $b->{Chars} + } + grep { + $_->{Form} =~ m/$formre/ && + !$_->{Ambiguous} + } + @forms + ) { + my $form = $f->{Form}; + p " sz_$form = Commitid_${form}_sz();\n"; + foreach my $rot (qw(0 1)) { + my $id = "${form}_r${rot}"; + p " sc_$id = min(sc_max"; + foreach my $xy (qw(0 1)) { + p ",sz[$xy]/sz_$form","[",(($xy xor $rot)+0),"]"; + } + p ");\n"; + push @do, " if (sc_$id >= 1.0"; + push @do, " && sc_$id >= sc_${form}_r1" if !$rot; + push @do, ") {\n"; + push @do, " translate([margin,margin]) scale(sc_$id)\n"; + push @do, " rotate(90) translate([0,-sz_$form"."[1]])\n" if $rot; + push @do, " Commitid_${form}_2D();\n"; + push @do, " } else"; + } + } + push @do, <#< \## +# # # /#/ ##< \## ##\ ##\ // >#< \## # # # # # # # # # # # # # \#/ /#\ ### ##/ # ##/ \#/ # \#/ ##/ a b c d e f # # /## -/## ##\ /## /## /#\ # -# # # # # # # #r/ ### + # /## # /#\ # +/## ##\ # /## #r# ### # # # # # # # #/ # \## ##/ \## \## \#/ # ++ * + + # # + # \#/ +### ### + # /#\ + # #