Hi Hugh,

> It started off just getting Claude to generate these directly from the
> csv, but by the time I’d done a couple of them it made sense to get it
> into a simple program. All told it’s about half a day of work. Claude
> did all the program architecture, wrote all the code, wrote the docs,
> managed the repo and pushed to my GitHub.

Thanks for making that available.  I was curious so here's some
comments.


When looking at the HTML produced for the example, I was puzzled why
clicking each of the ‘Bootlace ferrule’ wires in turn switched the
highlight to them except for ‘TL-GND (power meter’ which cancelled the
highlight.

It's because clicking the text doesn't ‘pick’; clicking the rectangle
the text sits in is needed.  ‘TL-GND (power meter’ is the longest piece
of text so when I ran the mouse down vertically, it happened to be over
text for just that one wire.

I think the text should pick too, e.g. ‘13 Mode change’.


I looked just at the start of wd/parser.py:

    5   # Flexible column name aliases (all lowercase, spaces normalised)
    6   COLUMN_ALIASES: dict[str, list[str]] = {
    7       "signal":      ["signal", "signal name", "name", "wire", "wire 
name"],
    8       "left_conn":   ["left connector", "left conn", "from connector", 
"from",
    9                       "source connector", "source"],
   10       "left_pin":    ["left pin", "from pin", "source pin", "pin (left)", 
"left pin no"],
   11       "right_conn":  ["right connector", "right conn", "to connector", 
"to",
   12                       "dest connector", "destination connector", 
"destination",
   13                       "termination", "termination type"],
   14       "right_pin":   ["right pin", "to pin", "dest pin", "destination 
pin",
   15                       "pin (right)", "right pin no"],
   16       "colour":      ["wire colour", "wire color", "colour", "color", 
"wire col"],
   17       "warning":     ["warning", "note", "notes", "annotation", "remark"],
   18       "pair":        ["pair", "twisted pair", "tp", "pair group", "cable 
group"],
   19       "length":      ["length", "wire length", "len"],
   20   }

COLUMN_ALIASES is only currently used by parser.py so perhaps it could
be better hidden from importers.

That the value is a list suggests to me, trying to understand its
purpose, that it may be modified, but it isn't.  A tuple avoids this.

It would be nice if the first string in the list of values was
consistently the same as the key.  Then I wouldn't need to hunt to see
if that was true each time, as it is.

   23   def _norm(h: str) -> str:
   24       return h.strip().lower().replace("_", " ").replace("-", " ")

This smells wrong: stripping spaces only to then turn some characters
into spaces.

   27   def _map_headers(headers: list[str]) -> dict[str, int]:
   28       norm = {_norm(h): i for i, h in enumerate(headers)}
   29       result: dict[str, int] = {}
   30       for field, aliases in COLUMN_ALIASES.items():
   31           for alias in aliases:
   32               if alias in norm:
   33                   result[field] = norm[alias]
   34                   break
   35       return result

I haven't looked at the calls of this so it might not be possible, and
if it is possible it may not matter, but headers[] may be mapped onto
a norm{} which has fewer keys than len(headers).  The last one wins,
having its index, ‘i’, stored.  This might confuse the user.

And if a normalised header element isn't found in the aliases, which
include the key itself, then it is silently dropped by not appearing in
result[].

The example CSV could show that blank lines and comments are allowed,
that spaces can be used within fields to create columns, and notes may
be given.

-- 
Cheers, Ralph.

-- 
  Next meeting: Online, Jitsi, Tuesday, 2026-06-02 20:00
  Check to whom you are replying
  Meetings, mailing list, IRC, ...  https://dorset.lug.org.uk
  New thread, don't hijack:  mailto:[email protected]

Reply via email to