X-Authentication-Warning: delorie.com: mail set sender to geda-user-bounces using -f X-Recipient: geda-user AT delorie DOT com X-Original-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=mime-version:from:date:message-id:subject:to; bh=2zwhFOW9Mm3X1R3e5l+2mSGPrKT/gBeSFrizIMcCyQY=; b=b5Tc+ibeUlZl9BQlgWtY1hOP49PGn6j5JEEg5JAHMMU85LhvPUqIvwpPpHlMc5+EwH Hp9FPMTvO6bHNKII5wuv6+LeJq2yymtWWv4VYl01PAfoJTldY9jSJTI26Zh26V+sTp2K TI2vBHMgko+v9GfNNb4qHqxhlqXAuRsglX/z0jI952CsmeNvOIACHhbHsbSkom65VFY0 3Cl96R/Wj18BMPEEQMkjh+EhQwTyBtbRQNO3vz4KryerbbgY1oT39PCpX3X/lA6/D86y DCnn2rrP6A9+XLVnd/vCZZeE/LDyVfY5glrEFw7FTJaIHQPOO4UCo2y1yRQi9sZkjeuN 3GJg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:mime-version:from:date:message-id:subject:to; bh=2zwhFOW9Mm3X1R3e5l+2mSGPrKT/gBeSFrizIMcCyQY=; b=kbZJem2K6Td/ZkPGKh9+Fz2nac0oaXVLU1KzpMgf9nqI8kBUoSm5QOSxEhW0T3oOtK BgFpFVpTKaGXIQ9YdnSQ6DJnWckqhCw1n7j2tgPORLETIqQosHIaPLjvN5CcDtoM2UEO wDSP5itlHo7ZKsIZhQmgabFcopM7vXOpYwJji8HzdV/Lv2fhqyVCXUbV2EBKFZTZ39ku qgzbLCXqNMxczedBiE8fhJpuck8OXD4Lp/LW4hr+FI8tV5HGqvEfUZ3tFfht1K0HOqFW my7+5swysXO6XA2gVaMo3kQDXm3uO7IPGobOYAsbPmQsUfEoaQD0ODIyphhKr1Zu7FF6 nldA== X-Gm-Message-State: ALyK8tJITYTWwIYo3D7JXvLlWQcKzqzbpYJZk7wzUSmtr2YN9cXNf7ZoKsWwa8EJtoHMorsZ5Cv4Ar3x7LAzSA== X-Received: by 10.31.166.20 with SMTP id p20mr19762723vke.2.1468915199475; Tue, 19 Jul 2016 00:59:59 -0700 (PDT) MIME-Version: 1.0 From: "Vladimir Zhbanov (vzhbanov AT gmail DOT com) [via geda-user AT delorie DOT com]" Date: Tue, 19 Jul 2016 10:59:58 +0300 Message-ID: Subject: [geda-user] Easy sophisticated partlist creation To: geda-user Content-Type: multipart/mixed; boundary=001a11416d80ab95460537f8787e Note-from-DJ: This may be spam Reply-To: geda-user AT delorie DOT com --001a11416d80ab95460537f8787e Content-Type: text/plain; charset=UTF-8 Hi dear gEDA users, Inspired by discussion on the list about half a year ago I decided to write a Scheme function for creating sophisticated partlists. The discussion started due to a bug in the backend partslist3 reported by Karl Hammar (thank you, Karl!). It took a while to understand what I want and how to do this, but now you can try to write a small custom partlist backend yourself. Now, a little introduction. I have started rewriting things as reusable Scheme modules accompanied with unit testing provided in the standard Scheme unit testing framework module (srfi srfi-64). Look at the last couple of patches in the geda-gaf repository, if you want to know more. -------------------------------->8-------------------------------- $ gnetlist -i test.sch ... Enter `,help' for help. gnetlist> ,use (gnetlist partlist) gnetlist> (help partlist->string) `partlist->string' is a procedure in the (gnetlist partlist) module. Takes PART-LIST and outputs a string representing a table of attribute values of the list. The following optional arguments may be used: GROUP-BY is a name of the attribute by which the part list is grouped. SORT-ORDER may be an alist consisting of attribute names with corresponding sorting functions, or just a list of attribute names in which case the parts are sorted using default functions defined for corresponding attributes. If no sorting function is defined for an attribute name, the case insenstive string sorting function stringstring. There are also two comparison functions in the module (gnetlist attrib compare): refdes8-------------------------------- 1) Define header (later you can read it from a file): --------------------------------8<-------------------------------- (define document-header "\\documentclass[a4paper,11pt]{letter} \\usepackage[utf8x]{inputenc} \\usepackage{lscape} \\usepackage{longtable} \\begin{document} \\pagestyle{empty} \\noindent\\begin{longtable}{p{.3\\linewidth}|p{.3\\linewidth}|p{.4\\linewidth}} \\hline ") -------------------------------->8-------------------------------- 2) Define footer: --------------------------------8<-------------------------------- (define document-footer " \\end{longtable} \\end{document} ") -------------------------------->8-------------------------------- 3) Define the function itself: --------------------------------8<-------------------------------- (define (custom-partlist output-filename) (display (partlist->string (make-partlist '(device value footprint refdes)) #:group-by 'refdes #:sort-order '(refdes footprint device) #:output-order '(device footprint refdes) #:header document-header #:footer document-footer #:prepend-names? #f #:reduce? #t #:row-separator " \\\\\n" #:column-separator " & " #:group-separator "; " #:subgroup-separator "--" #:transpose? #f ) (gnetlist:output-port output-filename))) -------------------------------->8-------------------------------- Now create a directory for your gnetlist backends, say ~/custom, save the file as ~/custom/gnet-custom-partlist.scm and give it a try: --------------------------------8<-------------------------------- $ cd my-project-directory $ gnetlist -L ~/custom/ -g custom-partlist -o "-" test.sch \documentclass[a4paper,11pt]{letter} \usepackage[utf8x]{inputenc} \usepackage{lscape} \usepackage{longtable} \begin{document} \pagestyle{empty} \noindent\begin{longtable}{p{.3\linewidth}|p{.3\linewidth}|p{.4\linewidth}} \hline resistor & m1608_a.fp & R7 \\ Resistor & m1608_a.fp & R8; Rb1 \\ resistor & m1608_a.fp & R13 \end{longtable} \end{document} -------------------------------->8-------------------------------- Use `-o partlist.tex' to redirect output to a file, then pdflatex, and that's all. Your PDF is ready. Ah, stop. Why resistors are not properly grouped?! Obviously, their devices have different cases, though I don't understand yet, why two lowercase 'resistor's aren't grouped? Let's add the keyword letter-case: --------------------------------8<-------------------------------- ... #:transpose? #f #:letter-case '((device . smart)) ) ... -------------------------------->8-------------------------------- Now we have (I keep only important part removing header and footer): --------------------------------8<-------------------------------- RESISTOR & m1608_a.fp & R7 \\ RESISTOR & m1608_a.fp & R8; Rb1 \\ RESISTOR & m1608_a.fp & R13 -------------------------------->8-------------------------------- Hey, they aren't grouped as I wanted?!? Ah, I see, I use 'value' here --------------------------------8<-------------------------------- (make-partlist '(device value footprint refdes)) -------------------------------->8-------------------------------- but don't output it. OK, let's add it --------------------------------8<-------------------------------- #:sort-order '(footprint device refdes value) #:output-order '(device footprint refdes value) -------------------------------->8-------------------------------- If you don't add it to #:sort-order, it will throw an error. Now we have: --------------------------------8<-------------------------------- RESISTOR & m1608_a.fp & R7 & 330 \\ RESISTOR & m1608_a.fp & R8; Rb1 & 10k \\ RESISTOR & m1608_a.fp & R13 & 1k -------------------------------->8-------------------------------- OK, now I see why they are different. Let's remove 'value' all over and try again: --------------------------------8<-------------------------------- RESISTOR & m1608_a.fp & R7; R8; R13; Rb1 -------------------------------->8-------------------------------- Hurray! This is what I wanted! OK, output it to a file and make a pdf file: --------------------------------8<-------------------------------- $ gnetlist -L ~/custom/ -g custom-partlist -o partlist.tex test.sch $ pdflatex partlist.tex ... ! Missing $ inserted. $ l.10 RESISTOR & m1608_ a.fp & R7; R8; R13; Rb1 ? -------------------------------->8-------------------------------- Brr, what's wrong? Ah, I see, underscore is a special symbol in LaTeX and must be escaped. Then we need the module (ice-9 regex) and substitute its function 'regexp-substitute/global' for 'display'. It has another order of arguments, and their quantity, so the main function slightly changes. --------------------------------8<-------------------------------- v(define (custom-partlist output-filename) (regexp-substitute/global (gnetlist:output-port output-filename) "_" (partlist->string ... skip keywords here for clarity ) 'pre "\\_" 'post)) -------------------------------->8-------------------------------- Yes, I just escaped underscores for LaTeX, and escaped the backslash itself for Scheme. Now, do some cosmetic changes (add \hline at the end of the output table) and run gnetlist and pdflatex once again. The resulting backend is attached. Enjoy! -- Vladimir --001a11416d80ab95460537f8787e Content-Type: application/octet-stream; name="gnet-custom-partlist.scm" Content-Disposition: attachment; filename="gnet-custom-partlist.scm" Content-Transfer-Encoding: base64 X-Attachment-Id: file0 Cih1c2UtbW9kdWxlcyAoZ25ldGxpc3QgcGFydGxpc3QpCiAgICAgICAgICAgICAoZ25ldGxpc3Qg cGFydGxpc3QgY29tbW9uKQogICAgICAgICAgICAgKGljZS05IHJlZ2V4KSkKCihkZWZpbmUgZG9j dW1lbnQtaGVhZGVyICJcXGRvY3VtZW50Y2xhc3NbYTRwYXBlciwxMXB0XXtsZXR0ZXJ9ClxcdXNl cGFja2FnZVt1dGY4eF17aW5wdXRlbmN9ClxcdXNlcGFja2FnZXtsc2NhcGV9ClxcdXNlcGFja2Fn ZXtsb25ndGFibGV9CgpcXGJlZ2lue2RvY3VtZW50fQpcXHBhZ2VzdHlsZXtlbXB0eX0KXFxub2lu ZGVudFxcYmVnaW57bG9uZ3RhYmxlfXtwey4zXFxsaW5ld2lkdGh9fHB7LjNcXGxpbmV3aWR0aH18 cHsuNFxcbGluZXdpZHRofX0KXFxobGluZQoiKQoKKGRlZmluZSBkb2N1bWVudC1mb290ZXIgIiBc XFxcXG4KXFxobGluZQpcXGVuZHtsb25ndGFibGV9CgpcXGVuZHtkb2N1bWVudH0KIikKCihkZWZp bmUgKGN1c3RvbS1wYXJ0bGlzdCBvdXRwdXQtZmlsZW5hbWUpCiAgKHJlZ2V4cC1zdWJzdGl0dXRl L2dsb2JhbAogICAoZ25ldGxpc3Q6b3V0cHV0LXBvcnQgb3V0cHV0LWZpbGVuYW1lKSAiXyIKICAg KHBhcnRsaXN0LT5zdHJpbmcKICAgIChtYWtlLXBhcnRsaXN0ICcoZGV2aWNlIGZvb3RwcmludCBy ZWZkZXMpKQogICAgIzpncm91cC1ieSAncmVmZGVzCiAgICAjOnNvcnQtb3JkZXIgJyhmb290cHJp bnQgZGV2aWNlIHJlZmRlcykKICAgICM6b3V0cHV0LW9yZGVyICcoZGV2aWNlIGZvb3RwcmludCBy ZWZkZXMpCiAgICAjOmhlYWRlciBkb2N1bWVudC1oZWFkZXIKICAgICM6Zm9vdGVyIGRvY3VtZW50 LWZvb3RlcgogICAgIzpwcmVwZW5kLW5hbWVzPyAjZgogICAgIzpyZWR1Y2U/ICN0CiAgICAjOnJv dy1zZXBhcmF0b3IgIiBcXFxcXG4iCiAgICAjOmNvbHVtbi1zZXBhcmF0b3IgIiAmICIKICAgICM6 Z3JvdXAtc2VwYXJhdG9yICI7ICIKICAgICM6c3ViZ3JvdXAtc2VwYXJhdG9yICItLSIKICAgICM6 dHJhbnNwb3NlPyAjZgogICAgIzpsZXR0ZXItY2FzZSAnKChkZXZpY2UgLiBzbWFydCkpCiAgICAp CiAgICdwcmUgIlxcXyIgJ3Bvc3QpKQo= --001a11416d80ab95460537f8787e--