{"id":22375867,"url":"https://github.com/stylewarning/illogical-pathnames","last_synced_at":"2026-03-19T22:37:31.202Z","repository":{"id":236852841,"uuid":"625691842","full_name":"stylewarning/illogical-pathnames","owner":"stylewarning","description":null,"archived":false,"fork":false,"pushed_at":"2023-04-09T22:20:32.000Z","size":10,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-03-25T23:34:10.501Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Common Lisp","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/stylewarning.png","metadata":{"files":{"readme":"README.txt","changelog":null,"contributing":null,"funding":null,"license":null,"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":"2023-04-09T22:07:54.000Z","updated_at":"2023-04-11T06:39:14.000Z","dependencies_parsed_at":"2024-04-29T00:08:21.358Z","dependency_job_id":"d8d06d81-8c6d-49d6-8d69-2390ad076b3b","html_url":"https://github.com/stylewarning/illogical-pathnames","commit_stats":null,"previous_names":["stylewarning/illogical-pathnames"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stylewarning%2Fillogical-pathnames","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stylewarning%2Fillogical-pathnames/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stylewarning%2Fillogical-pathnames/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stylewarning%2Fillogical-pathnames/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/stylewarning","download_url":"https://codeload.github.com/stylewarning/illogical-pathnames/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245708990,"owners_count":20659625,"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","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":"2024-12-04T21:28:02.766Z","updated_at":"2026-01-06T13:37:10.460Z","avatar_url":"https://github.com/stylewarning.png","language":"Common Lisp","funding_links":[],"categories":[],"sub_categories":[],"readme":"                         ILLOGICAL PATHNAMES\n                         ===================\n\n                           By Robert Smith\n\n\nPurpose\n-------\n\nThe purpose of this library is to allow one to specify pathnames in\nsource files whose syntax mostly doesn't depend on a physical path\nlocation. To put it simply, one can write\n\n    #P(:HOME (\".emacs.d\") \"foo.el\")\n\ninstead of\n\n    #P\"/home/me/.emacs.d/foo.el\".\n\nSomewhere, :HOME---a so-called \"illogical host\"---has to be\nspecified. This is done by associating it with a directory via the\nmacro DEFINE-ILLOGICAL-HOST. They can be redefined, which won't affect\nevaluated uses of #P(...) syntax.\n\nThe former syntax isn't actually an \"illogical pathname\"; it evaluates\nto a physical pathname. (See the example below and the FAQ.) However,\nit does involve objects of the type ILLOGICAL-PATHNAME under the hood.\n\nUsing illogical pathnames allows one to easily write code whose\npathnames are relative to a few known base directories. When the\nprogram is moved, or perhaps an executable is created, one only has to\nredefine the set of illogical hosts. Using the power of\n*LOAD-TRUENAME* and others, one can make mostly portable applications\nthat don't depend on physical filesystem location at all.\n\n\nName\n----\n\nBefore this library, I attempted to solve the same problem by defining\nlogical hosts with wildcard translations. This worked relatively well\nwith Clozure CL, due to their more flexible implementation of logical\npathnames. However, more ANSI compliant systems (with respect to\nlogical pathnames) didn't work with the same code. As such, in my\nmind, I made \"logical pathnames that solve the 95% case\" and called\nthem \"illogical pathnames\", a play on the fact that they were supposed\nto be \"logical logical pathnames\". (A double positive makes a\nnegative, right?)\n\nDespite the name and the reasoning behind the name, these aren't a\nreplacement for logical pathnames and are not \"better\" than logical\npathnames; they just solve a different problem than that which logical\nhosts solve on modern machines.\n\n\nExample\n-------\n\nNote that normal pathname syntax isn't changed.\n\n    \u003e #P\"/foo/bar\"\n    #P\"/foo/bar\"\n\nLet's define an illogical host that points to my home directory.\n\n    \u003e (ipath:define-illogical-host :home \"/home/me/\")\n    :HOME\n\nLet's use the extended pathname syntax to refer to a file in my home\ndirectory.\n\n    \u003e #P(:home (\"Scratch\") \"new.txt\")\n    #P\"/home/me/Scratch/new.txt\"\n\nWe see that #P(...) isn't truly a literal for an illogical\npathname. It returned a physical pathname. What does #P(...) really\nexpand into then?\n\n    \u003e '#P(:home (\"Scratch\") \"new.txt\")\n    (ILLOGICAL-PATHNAMES:TRANSLATE-ILLOGICAL-PATHNAME\n      #S(ILLOGICAL-PATHNAMES:ILLOGICAL-PATHNAME\n          :HOST :HOME\n          :DIRECTORY (\"Scratch\")\n          :NAME \"new\"\n          :TYPE \"txt\"))\n\nJust an unevaluated translation of an illogical pathname object.\n\nLet's define another illogical host referring to my scratch space\ndirectory in my home directory.\n\n    \u003e (ipath:define-illogical-host :scratch #P(:home (\"Scratch\")))\n    :SCRATCH\n\nLet's open a new file and write to it in my scratch space.\n\n    \u003e (with-open-file (s #P(:scratch nil \"test.txt\") :direction ':output\n                                                     :if-does-not-exist ':create)\n        (write-string \"testing, 1 2 3\" s))\n    \"testing, 1 2 3\"\n\nAnd finally, let's read it back.\n\n    \u003e (with-open-file (s #P(:scratch nil \"test.txt\") :direction ':input)\n        (read-line s))\n    \"testing, 1 2 3\"\n     T\n\nThat is basically it.\n\n\nFrequently Asked Questions\n--------------------------\n\nQ. Why doesn't #P(...) specify a literal illogical pathname object?\n\nThis was a pragmatic choice. If Common Lisp had a generic function\ncalled, say, TRANSLATE-TO-PATHNAME which all relevant Common Lisp\nfunctions knew about, we could indeed use illogical pathname objects\nby creating a method of that generic function. However, since we don't\nhave that functionality, yet we want to relatively transparently be\nable to specify illogical pathnames in the places they're used, we do\nthe translation within the expansion of #P(...).\n\n\nQ. My system needs to be bootstrapped, and I can't rely on Quicklisp\n   or ASDF, but I want to use illogical pathnames.\n\nNo problem. The file \"illogical-pathnames.lisp\" is self-contained. You\ncan load it as-is.\n\n\nQ. ANSI logical pathnames can solve this problem. I tried it and\n   it works fine!\n   \nThe ANSI spec requires that strings in logical pathnames must be uppercase,\nand the system should convert them to uppercase when pathnames are created:\n\n\"Logical pathname words are restricted to non-case-sensitive letters,\ndigits, and hyphens to avoid creating problems with real file systems\nthat support limited character sets for file naming. (If logical pathnames\nwere case-sensitive, it would be very difficult to map them into a file\nsystem that is not sensitive to case in its file names.)\"\n\nhttps://www.cs.cmu.edu/Groups/AI/html/cltl/clm/node213.html\n\nThe phrase in parentheses above is precisely the opposite of the truth.\nA fully ANSI-conforming logical pathname implementation cannot generally\nbe used on a case-sensitive file system such as that typically used in Linux\nor Unix.\n\nIf you are not seeing this problem with your CL implementation, it is either because\nyou are using a case-insensitive file system like MacOSX, or because\nyour implementation (e.g., Clozure CL or Franz) sanely nixed the ANSI idea\nof logical pathnames and made them case-preserving.\nUnfortunately, that is not ANSI conforming.\n\n\nQ. Why didn't you just make a DEFINE-* macro and a function?\n\nPathnames need to be convenient, and specifying functions in full is\nnot syntactically convenient. If one doesn't like the #P syntax, they\nmay opt to create ILLOGICAL-PATHNAME objects and call\nTRANSLATE-ILLOGICAL-PATHNAME at will.\n\n       \u003e (ipath:define-illogical-host :home \"/Users/me/\")\n       :HOME\n       \u003e (ipath:make-illogical-pathname\n          :host ':home\n          :directory '(\"foo\" \"bar\")\n          :name \"test\"\n          :type \"txt\")\n       #S(ILLOGICAL-PATHNAMES:ILLOGICAL-PATHNAME :HOST :HOME :DIRECTORY (\"foo\" \"bar\") :NAME \"test\" :TYPE \"txt\")\n       \u003e (ipath:translate-illogical-pathname *)\n       #P\"/Users/me/foo/bar/test.txt\"\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstylewarning%2Fillogical-pathnames","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fstylewarning%2Fillogical-pathnames","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstylewarning%2Fillogical-pathnames/lists"}