{"id":26364923,"url":"https://github.com/romforth/twf","last_synced_at":"2025-08-02T23:08:27.046Z","repository":{"id":282047827,"uuid":"927379850","full_name":"romforth/twf","owner":"romforth","description":"Tree Walk Format (twf) to describe family trees in a flat file format","archived":false,"fork":false,"pushed_at":"2025-03-12T13:54:18.000Z","size":21,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-07-21T03:30:28.472Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Perl","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"agpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/romforth.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2025-02-04T21:23:29.000Z","updated_at":"2025-03-12T13:54:21.000Z","dependencies_parsed_at":"2025-03-12T14:56:00.630Z","dependency_job_id":null,"html_url":"https://github.com/romforth/twf","commit_stats":null,"previous_names":["romforth/twf"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/romforth/twf","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/romforth%2Ftwf","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/romforth%2Ftwf/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/romforth%2Ftwf/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/romforth%2Ftwf/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/romforth","download_url":"https://codeload.github.com/romforth/twf/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/romforth%2Ftwf/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":268470799,"owners_count":24255391,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-08-02T02:00:12.353Z","response_time":74,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-03-16T19:28:44.074Z","updated_at":"2025-08-02T23:08:27.025Z","avatar_url":"https://github.com/romforth.png","language":"Perl","readme":"`twf` is a Perl script that can turn a family tree (documented using what I'll\ncall a _tree walk format_ flat file) into a `groff/dot` diagram. The groff/dot\noutput generated by `twf` can then be post processed (using `dot` or any of the\nother tools in the `groff` tool set) to generate output in other/more human\nreadable formats, say, for example, pdf, which can show the relationships within\na family tree in a more diagrammatic/pictorial form.\n\nAn example file (`abe.twf`) shows the input format used by the `twf` script and\nit depicts the relationships documented in the Book of Genesis in the Bible\nstarting from ~~Abraham~~ Adam.\n\nRunning `make` in this directory will generate a pdf file which uses `abe.twf`\nas the input file and documents a ~~minimal~~ long linkage from Adam all the way\nto Abraham's family tree as per the Book of Genesis in the Bible.\n\nAn informal grammar that describes the _tree walk format_ using something that\nresembles YACC/Bison (while borrowing some additional functionality such as the\n'%%' delimiter and \"rule\" notation from Perl6/Raku) is shown below:\n\n```\n// a \"tree walk format\"/twf input file consists of ...\ntwf\t: ( family '\\n' )+\t// ... one or more families, listed one per line\nfamily\t: ( person %% '|')+\t// a family consists of persons delimited by '|'\nfamily\t: include filename.twf\t// pull data from the named file (in twf format)\nperson\t: name ( ',' age )? op\t// a person has a name and an optional age\nperson\t: '?'\t\t\t// a person's name may be unknown\nperson\t: '-'\t\t\t// birth order of remaining children is unknown\nage\t: '?' | number '?'?\t// the age of the person may be unknown ...\n\t\t// ... which is denoted by a '?' or it could be a known number\n\t\t// which may be suffixed with a '?' to denote if it is doubtful\nnumber\t: [0-9]+\t\t// age (at time of death) is just a whole number\nname\t: realname ( \\s '(' nickname ')' )?\t// a person may have a different\n\t\t\t\t// optional earlier name and/or a nickname\nrealname: [^\\,\\(\\#\\|]+\t\t// names can have anything including spaces ...\nnickname: [^\\,\\(\\#\\|\\)]+\t// .. except some special characters\nop\t: [\\.\\!\\^]?\t\t// the '.' operator denotes no descendants\n\t\t\t\t// a cut/'!' operator indicates a back reference\n\t\t\t\t// a forward pointer/'^' operator indicates that\n\t\t\t\t// the person is resolved later, not immediately\n```\n\nNote that while doing genealogy research, the age of the deceased may be\nunknown (and sometimes disputed/unbelievable, such as the ones listed for\nAbraham and his family) and these can be denoted using '?'.\n\nWhen a marriage between relatives occurs (for example, when Isaac marries\nhis cousin Rebekah), mathematically, a family \"tree\" becomes a connected graph.\nTo handle such cases, the cut/'!' operator provides a means of denoting that\nthe current referent may be already embedded in the stack due to an earlier\nreference in the tree. The cut/'!' operator resolves the looping that can thus\nresult from this, and yes, the cut/'!' operator is \"borrowed\" from Prolog\nalthough there is no backtracking involved here so it is not used in quite the\nsame sense as it is used in Prolog.\n\nIn some cases, relationships can be complicated enough (for example, see Lot's\nfamily tree) that the cut /'!' operator needs a paired forward pointer/'^'\nreference operator as well. This operator just postpones the lookup of the\nperson in the immediately following family entry and defers it until a later\ncut/'!' operator resolves it in the stack.\n\nTurning the `twf` format into the more well known `GEDCOM` format is left as\nan exercise for the reader. The primary (only?) advantage of `twf` over `GEDCOM`\nis that it is meant to be hand editable using any text editor of your choice.\n\nSome background and context regarding the creation of this file format is at:\nhttps://ces.mataroa.blog/blog/twf_ftwmd\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fromforth%2Ftwf","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fromforth%2Ftwf","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fromforth%2Ftwf/lists"}