Threads for thangalin

  1. 1

    This is good timing - I’m working on my thesis right now. It’s ridiculous how little of Vimtex I’ve been using! It turns out almost all of the manual LaTeX work I’ve been performing can be done via the plugin; I got forward and backward search practically for free. The only thing is, the “real time” claim is a little bit impossible - for documents like mine, there’s a 2-3 second delay between saving and re-rendering. I think that’s a limitation of LaTeX though, and one I’ll have to live with.

    1. 2

      I think that’s a limitation of LaTeX though, and one I’ll have to live with.

      KeenWrite, my plain text editor, can preview 1,000 simple TeX formulas in about 500 milliseconds on modern hardware. The Knuth-Plass Line Breaking Algorithm, which drives most TeX implementations, slows down rendering. KeenWrite uses an HTML previewer and inlines the math as SVG so that the math pops up instantly:

      https://github.com/DaveJarvis/keenwrite/blob/master/docs/screenshots.md#equations

      KeenWwrite typesets to PDF using ConTeXt, rather than LaTeX, because ConTeXt makes separating content from presentation much easier. The idea is to focus on the content, then muck with the formatting and layout when the content is finished.

      https://wiki.contextgarden.net/Main_Page

      Here’s an example of a Markdown document I wrote along with its bibliography. Both were typeset using ConTeXt:

    1. 1

      KeenWrite is my text editor that takes a slightly different approach than MDX. Rather than include variable definitions within documents, variables are defined in an external file. I find that when variables are embedded into documents, those variables often include controls for presentation logic. To me, any presentation logic meant to affect a plain text document’s appearance does not belong in the document itself. Part 8 of my Typesetting Markdown series shows the power of separating content from presentation by leveraging pandoc’s annotation syntax.

      Annotated Markdown is sufficiently powerful to produce a wide variety of different styles. Here are a few such Markdown documents typeset using ConTeXt:

      What’s bothersome is how some companies are setting de facto Markdown standards without considering the greater ecosystem. GitHub has done this by introducing the “``` mermaid” syntax, which creates some problems.

      1. 14

        The PersonnelRecord isn’t OOP and exhibits a widespread misunderstanding:

        class PersonnelRecord {
        public:
          char* employeeName() const;
          int   employeeSocialSecurityNumber() const;
          char* employeeDepartment() const;
        protected:
          char  name[100];
          int   socialSecurityNumber;
          char  department[10];
          float salary;
        }
        

        As written, the PersonnelRecord class will inevitably lead to code duplication, tightly coupled classes, and other maintainability issues. An improvement that’s still not OOP, but exposes a more flexible contract, resembles:

        class Employee {
        public:
          Name name() const;
          SocialSecurityNumber socialSecurityNumber() const;
          Department department() const;
        private:
          Name name;
          SocialSecurityNumber socialSecurityNumber;
          Department department;
          Salary salary;
        }
        

        OOP is more about the actionable messages that objects understand to carry out tasks on behalf of other objects. Wrapping immutable data exposed via accessors reaps few benefits. Rather, OOP strives to model behaviours that relate to the problem domain:

        class Employee {
        public:
          void hire();
          void fire();
          void kill();
          void raise( float percentage );
          void promote( Position position );
          void transfer( Department department );
        private:
          Name name;
          SocialSecurityNumber socialSecurityNumber;
          Department department;
          Salary salary;
        }
        

        This allows for writing the following code:

        employee.transfer( department );
        

        I don’t know how to “transfer” an employee given the code from the article, but it would not be nearly as elegant.

        1. 29

          Re: https://github.com/github/markup/issues/533

          I’m the main author of KeenWrite (see screenshots), a type of desktop Markdown editor that supports diagrams. It’s encouraging to see that Mermaid diagrams are being supported in GitHub. There are a few drawbacks on the syntax and implications of using MermaidJS.

          First, only browser-based SVG renderers can correctly parse Mermaid diagrams. I’ve tested Apache Batik, svgSalamander, resvg, rsvg-convert, svglib, CairoSVG, ConTeXt, and QtSVG. See issue 2485. This implies that typesetting Mermaid diagrams is not currently possible. In effect, by including Mermaid diagrams, many documents will be restricted to web-based output, excluding the possibility of producing PDF documents based on GitHub markdown documents (for the foreseeable future).

          Second, there are numerous text-to-diagram facilities available beyond Mermaid. The server at https://kroki.io/ supports Mermaid, PlantUML, Graphviz, byte fields, and many more. While including MermaidJS is a great step forward, supporting Kroki diagrams would allow a much greater variety. (Most diagrams produced in MermaidJS can also be crafted in Graphviz, albeit with less terse syntax.)

          Third, see the CommonMark discussion thread referring to a syntax for diagrams. It’s unfortunate that a standard “namespace” concept was not proposed.

          Fourth, KeenWrite integrates Kroki. To do so, it uses a variation on the syntax:

          ``` diagram-mermaid
          ```
          
          ``` diagram-graphviz
          ```
          
          ``` diagram-plantuml
          ```
          

          The diagram- prefix tells KeenWrite that the content is a diagram. The prefix is necessary to allow using any diagram supported by a Kroki server without having to hard-code the supported diagram type within KeenWrite. Otherwise, there is no simple way to allow a user to mark up a code block with their own text style that may coincide with an existing diagram type name.

          Fifth, if ever someone wants to invent a programming language named Mermaid (see MeLa), then it precludes the possibility of using the following de facto syntax highlighting:

          ``` mermaid
          ```
          

          My feature request is to add support for Kroki and the diagram- prefix syntax. That is:

          ``` diagram-mermaid
          ```
          

          And deprecate the following syntax:

          ``` mermaid
          ```
          

          And, later, introduce the language- prefix for defining code blocks that highlight syntax. That is, further deprecate:

          ``` java
          ```
          

          With the following:

          ``` language-java
          ```
          

          That would provide a “namespace” of sorts to avoid naming conflicts in the future.

          1. 10

            I don’t think moving the existing stuff to language- is necessary, however I agree that diagram-mermaid is a better option – especially if one wants syntax highlighting for the syntax of the Mermaid diagramming language, to describe how to write such diagrams.

            1. 1

              First, only browser-based SVG renderers can correctly parse Mermaid diagrams. I’ve tested Apache Batik, svgSalamander, resvg, rsvg-convert, svglib, CairoSVG, ConTeXt, and QtSVG. See issue 2485

              Do you mean the output of mermaid.js? Besides that these SVG parsers should be fixed if they are broken and maybe mermaid.js could get a workaround, surely a typset system could read the mermaid syntax directly and not the output of a for-web implementation of it?

              1. 2

                If you look at the issue, there’s a fairly extensive list of renderers affected. This suggests that the core problem is that mermaid uses some feature(s) which are not widely supported.

                1. 1

                  Besides that these SVG parsers should be fixed if they are broken

                  Not sure if they are broken per se. The EchoSVG project aims to support custom properties, which would give it the ability to render Mermaid diagrams. From that thread, you can see supporting SVG diagrams that use custom properties is no small effort. Multiply that effort by all the renderers listed and we’re probably looking at around ten years’ worth of developer hours.

                  surely a typset system could read the mermaid syntax directly and not the output of a for-web implementation of it

                  Yes. It’s not for free, though. Graphviz generates graphs on par with the complexity of Mermaid graphs and its output can be rendered with all software libraries I tried. IMO, changing Mermaid to avoid custom properties would take far less effort than developing custom property renderers at least eight times over.

                  1. 2

                    IMO, changing Mermaid to avoid custom properties would take far less effort than developing custom property renderers at least eight times over.

                    Sure, but as I said the ideal would be neither of those, but to just typeset the mermaid syntax directly and not rely on the JS or the SVG at all.

              1. 13

                I agree with part of the premise, but this is way, way overengineered. My main problem with logs is they can clutter the code, making the code itself harder to understand at a glance. For that, having a simple function that abstracts the log into a nice compact name, something like LogExternalDependencyResponse() solves all of my problems.

                Why would I introduce all this machinery for logging? To decouple logging code from application logic? Logging code is one of the most clear examples of application logic.

                1. 15

                  Isn’t it a Java principle that any problem can be solved by adding more interfaces to the program, and requiring more rituals around everyday tasks?

                  1. 2

                    The machinery needed to do this can be scaled up and down to your needs. For example, all events can be written to a file as JSON, where another process can be used to subscribe to the events. This key difference between events and logging is that each kind of event has a name and possibly some structure, whereas a log is typically unstructured text.

                    1. 1

                      What is another use for this?

                      1. 3

                        Another use for this is to do any sort of async processing based on events. For example, if you have an InviteCreatedEvent, then you can have something else listening for that event that sends out the invite email. The point is that you can get more out of your logs by pulling them into the application layer a tiny bit.

                        1. 2

                          Unit testing. Verifying that a particular log message has been written to the system log is cumbersome (in Java). Using events makes validating the application behaviour trivial: execute the production code under test and block until the event is received. Presuming that the event machinery is solid, there’s no need to add any extra code to scan the system log file for updates.

                          1. 1

                            Not at all cumbersome if you use something like SLF4J-test as noted in my article https://www.jvt.me/posts/2019/09/22/testing-slf4j-logs/

                            1. 1

                              That’s neat, thank you for sharing. An advantage of the event method remains checking types and avoiding checking log message text except when validating the actual text of the message, which would be a test of the string representation or specific message owned by the event. Looking at the log output is one way to do it but that’s always felt brittle to me, esp. in a high change velocity codebase with multiple contributors having their own opinions of how things should be worded. At least the tests would catch that someone hasn’t deleted a log emission! slf4j-testing seems like a much cleaner way to look for log output than capturing stdout yourself, though!

                    1. 5

                      Studies have shown both positive and negative impacts on duplicating source code, with findings weighted towards detrimental effects [..]

                      The premise of the entire article, but no links to such studies.

                        1. 2

                          This is excellent stuff. Many thanks

                      1. 1

                        A noteworthy Java-based implementation of SymSpell:

                        It’s used in KeenWrite to check all the words in a plain text paragraph:

                        The spell check algorithm is insanely fast.

                        Note that the lexicon for the reference implementation is missing about 18,000 words, at time of writing. The author is aware. For the impatient, grab en.txt from the repo:

                        1. 4

                          Kroki is a REST service that can render mermaid and many other plain text diagrams. KeenWrite is my plain text editor that can embed text-based diagrams, which are then rendered by Kroki in near real-time. See the screenshots for details.

                          1. 7

                            Bash can also employ a kind of function pointer, which can greatly simplify command-line argument parsing. Consider the following simplified example:

                            ARG_ARCH="amd64"
                            
                            ARGUMENTS+=(
                              "ARG_ARCH,a,arch,Target operating system architecture (${ARG_ARCH})"
                              "log=utile_log,V,verbose,Log messages while processing"
                            )
                            
                            utile_log() { echo "$1" }
                            
                            noop()      { return 1 }
                            
                            log=noop
                            

                            By creating a comma-delimited list of command-line arguments, the parsing logic and control flow can be influenced from a single location in the code base. The trick is to eval-uate “log=utile_log” when the “-V” command-line argument is provided (or assign ARG_ARCH to the user-supplied value after “-a”). Using the $log variable invokes the function, such as in:

                            preprocess() {
                              $log "Preprocess"
                            }
                            

                            If “-V” isn’t supplied, then every invocation of $log simply returns without printing a message. The upshot is a reduction in conditional statements. Function pointers FTW. I wrote about this technique in my Typesetting Markdown series.

                            Here’s a rudimentary implementation and example usage to wet your whistle:

                            1. 7

                              There’s already a no-op builtin: :

                              test_var_fnref (){
                                log=noop
                                noop()      { return 0; }
                                for x in {1..100000}; do
                                  $log "Preprocess"
                                done
                              }
                              
                              test_var_builtinref (){
                                log=:
                                noop()      { return 0; }
                                for x in {1..100000}; do
                                  $log "Preprocess"
                                done
                              }
                              

                              It’ll save you the function call overhead when you aren’t printing the messages:

                              $ test_var_fnref
                              Sun Oct 31 2021 19:07:49 (1.15s)
                              
                              $ test_var_builtinref
                              Sun Oct 31 2021 19:07:55 (553ms)
                              

                              If it’s a hot loop, it’s also worth knowing that aliases get ~inlined at definition time, so you can do something like:

                              shopt -s expand_aliases
                              alias log=:
                              
                              test_alias_ref(){
                                for x in {1..100000}; do
                                  log "Preprocess"
                                done
                              }
                              

                              And wring a little more performance out:

                              $ declare -f test_alias_ref
                              test_alias_ref () 
                              { 
                                  for x in {1..100000};
                                  do
                                      : "Preprocess";
                                  done
                              }
                              
                              $ test_alias_ref
                              Sun Oct 31 2021 19:08:04 (543ms)
                              
                            1. 9

                              This is nice. Though, you could do some of the same things with XPath. For example, the first two examples could be done using xmllint:

                              $ curl -s https://www.rust-lang.org/ | xmllint --html --xpath "//*[@id='get-help']" -
                              $ curl -s https://www.rust-lang.org/ | xmllint --html --xpath "//@href" -
                              

                              Unfortunately xmllint doesn’t support html5, and complains about the <header> and <main> tags in the above example.

                              1. 5

                                XPath is really powerful, but it’s also really hard to grok (because it was designed for a much more powerful use case). I wonder if something that used the JQuery selector format wouldn’t be more appreciated :)

                                  1. 2

                                    Hxselect is super handy

                                    1. 2

                                      This tool is great, and already in Debian. Interesting that you need to give it XML syntax, but it comes with tools hxclean and hxnormalize -x that solve that for you.

                                      1. 1

                                        Wow! Fantastic, thanks!

                                  1. 1

                                    My text editor, KeenWrite, provides the ability to reference externally defined variables. Those variables can be added to diagrams. Kroki is called by KeenWrite, meaning numerous text-based diagramming formats can be embedded into Markdown documents, including PlantUML, Graphviz, Mermaid, and many more:

                                    https://github.com/DaveJarvis/keenwrite/blob/master/docs/screenshots.md

                                    1. 26

                                      These are all valid criticisms of certain patterns in software engineering, but I wouldn’t really say they’re about OOP.

                                      This paper goes into some of the distinctions of OOP and ADTs, but the summary is basically this:

                                      • ADTs allow complex functions that operate on many data abstractions – so the Player.hits(Monster) example might be rewritten in ADT-style as hit(Player, Monster[, Weapon]).
                                      • Objects, on the other hand, allow interface-based polymorphism – so you might have some kind of interface Character { position: Coordinates, hp: int, name: String }, which Player and Monster both implement.

                                      Now, interface-based polymorphism is an interesting thing to think about and criticise in its own right. It requires some kind of dynamic dispatch (or monomorphization), and hinders optimization across interface boundaries. But the critique of OOP presented in the OP is nothing to do with interfaces or polymorphism.

                                      The author just dislikes using classes to hold data, but a class that doesn’t implement an interface is basically the same as an ADT. And yet one of the first recommendations in the article is to design your data structures well up-front!

                                      1. 15

                                        The main problem I have with these “X is dead” type article is they are almost always straw man arguments setup in a way to prove a point. The other issue I have is the definition or interpretation of OOP is so varied that I don’t think you can in good faith just say OOP as a whole is bad and be at all clear to the reader. As an industry I actually think we need to get past these self constructed camps of OOP vs Functional because to me they are disingenuous and the truth, as it always does, lies in the middle.

                                        Personally, coming mainly from a Ruby/Rails environment, use ActiveRecord/Class to almost exclusively encapsulate data and abstract the interaction with the database transformations and then move logic into a place where it really only cares about data in and data out. Is that OOP or Functional? I would argue a combination of both and I think the power lies in the middle not one versus the other as most articles stipulate. But a middle ground approach doesnt get the clicks i guess so here we are

                                        1. 4

                                          the definition or interpretation of OOP is so varied that I don’t think you can in good faith just say OOP as a whole is bad and be at all clear to the reader

                                          Wholly agreed.

                                          The main problem I have with these “X is dead” type article is they are almost always straw man arguments setup in a way to prove a point.

                                          For a term that evokes such strong emotions, it really is poorly defined (as you observed). Are these straw man arguments, or is the author responding to a set of pro-OOP arguments which don’t represent the pro-OOP arguments with which you’re familiar?

                                          Just like these criticisms of OOP feel like straw men to you, I imagine all of the “but that’s not real OOP!” responses that follow any criticism of OOP must feel a lot like disingenuous No-True-Scotsman arguments to critics of OOP.

                                          Personally, I’m a critic, and the only way I know how to navigate the “not true OOP” dodges is to ask what features distinguish OOP from other paradigms in the opinion of the OOP proponent and then debate whether that feature really is unique to OOP or whether it’s pervasive in other paradigms as well and once in a while a feature will actually pass through that filter such that we can debate its merits (e.g., inheritance).

                                          1. 4

                                            I imagine all of the “but that’s not real OOP!” responses that follow any criticism of OOP must feel a lot like disingenuous No-True-Scotsman arguments to critics of OOP.

                                            One thing I have observed about OOP is how protean it is: whenever there’s a good idea around, it absorbs it then pretend it is an inherent part of it. Then it deflects criticism by crying “strawman”, or, if we point out the shapes and animals that are taught for real in school, they’ll point out that “proper” OOP is hard, and provide little to no help in how to design an actual program.

                                            Here’s what I think: in its current form, OOP won’t last, same as previous form of OOP didn’t last. Just don’t be surprised if whatever follows ends up being called “OOP” as well.

                                        2. 8

                                          The model presented for monsters and players can itself be considered an OO design that misses the overarching problem in such domains. Here’s a well-reasoned, in-depth article on why it is folly. Part five has the riveting conclusion:

                                          Of course, your point isn’t about OOP-based RPGs, but how the article fails to critique OOP.

                                          After Alan Kay coined OOP, he realized, in retrospect, that the term would have been better as message-oriented programming. Too many people fixate on objects, rather than the messages passed betwixt. Recall that the inspiration for OOP was based upon how messages pass between biological cells. Put another way, when you move your finger: messages from the brain pass to the motor neurons, neurons release a chemical (a type of message), muscles receive those chemical impulses, then muscle fibers react, and so forth. At no point does any information about the brain’s state leak into other systems; your fingers know nothing about your brain, although they can pass messages back (e.g., pain signals).

                                          (This is the main reason why get and set accessors are often frowned upon: they break encapsulation, they break modularity, they leak data between components.)

                                          Many critique OOP, but few seem to study its origins and how—through nature-inspired modularity—it allowed systems to increase in complexity by an order of magnitude over its procedural programming predecessor. There are so many critiques of OOP that don’t pick apart actual message-oriented code that beats at the heart of OOP’s origins.

                                          1. 1

                                            Many critique OOP, but few seem to study its origins and how—through nature-inspired modularity—it allowed systems to increase in complexity by an order of magnitude over its procedural programming predecessor.

                                            Of note, modularity requires neither objects nor message passing!

                                            For example, the Modula programming language was procedural. Modula came out around the same time as Smalltalk, and introduced the concept of first-class modules (with the data hiding feature that Smalltalk objects had, except at the module level instead of the object level) that practically every modern programming language has adopted today - including both OO and non-OO languages.

                                          2. 5

                                            I have to say, after read the first few paragraphs, I skipped to ‘What to do Instead’. I am aware of many limitations of OOP and have no issue with the idea of learning something new so, hit me with it. Then the article is like ’hmm well datastores are nice. The end.”

                                            The irony is that I feel like I learned more from your comment than from the whole article so thanks for that. While reading the Player.hits(Monster) example I was hoping for the same example reformulated in a non-OOP way. No luck.

                                            If anyone has actual suggestions for how I could move away from OOP in a practical and achievable way within the areas of software I am active in (game prototypes, e.g. Godot or Unity, Windows desktop applications to pay the bills), I am certainly listening.

                                            1. 2

                                              If you haven’t already, I highly recommend watching Mike Acton’s 2014 talk on Data Oriented Design: https://youtu.be/rX0ItVEVjHc

                                              Rather than focusing on debunking OOP, it focuses on developing the ideal model for software development from first principles.

                                              1. 1

                                                Glad I was helpful! I’d really recommend reading the article I linked and summarised – it took me a few goes to get through it (and I had to skip a few sections), but it changed my thinking a lot.

                                              2. 3

                                                [interface-based polymorphism] requires some kind of dynamic dispatch (or monomorphization), and hinders optimization across interface boundaries

                                                You needed to do dispatch anyway, though; if you wanted to treat players and monsters homogenously in some context and then discriminate, then you need to branch on the discriminant.

                                                Objects, on the other hand, allow interface-based polymorphism – so you might have some kind of interface […] which Player and Monster both implement

                                                Typeclasses are haskell’s answer to this; notably, while they do enable interface-based polymorphism, they do not natively admit inheritance or other (arguably—I will not touch these aspects of the present discussion) malaise aspects of OOP.

                                                1. 1

                                                  You needed to do dispatch anyway, though; if you wanted to treat players and monsters homogenously in some context and then discriminate, then you need to branch on the discriminant.

                                                  Yes, this is a good point. So it’s not like you’re saving any performance by doing the dispatch in ADT handling code rather than in a method polymorphism kind of way. I guess that still leaves the stylistic argument against polymorphism though.

                                                2. 2

                                                  Just to emphasize your point on Cook’s paper, here is a juicy bit from the paper.

                                                  Any time an object is passed as a value, or returned as a value, the object-oriented program is passing functions as values and returning functions as values. The fact that the functions are collected into records and called methods is irrelevant. As a result, the typical object-oriented program makes far more use of higher-order values than many functional programs.

                                                  1. 2

                                                    Now, interface-based polymorphism is an interesting thing to think about and criticise in its own right. It requires some kind of dynamic dispatch (or monomorphization), and hinders optimization across interface boundaries.

                                                    After coming from java/python where essentially dynamic dispatch and methods go hand in hand I found go’s approach, which clearly differentiates between regular methods and interface methods, really opened my eyes to overuse of dynamic dispatch in designing OO apis. Extreme late binding is super cool and all… but so is static analysis and jump to definition.

                                                  1. 1

                                                    This might be an odd question, but it looks as if this is written in JavaFX. What’s the status of it these days? I had been under the impression Oracle killed it, but it seems maybe to be limping along?

                                                    1. 4

                                                      it seems maybe to be limping along?

                                                      JavaFX is being actively developed. Java’s undergoing some growing pains as it transitions to modular applications. One of those changes was to remove JavaFX from the distributions. Modular Java applications, using tools like jlink and jpackage, have a couple things going for them. First, the ability to create small self-contained executables. Second, a tighter security model to prevent reflective access to functionality that was never meant to be used (e.g., internal Sun classes). A strike against this modular shift is that, with heavy irony, there’s no simple way to cross-compile those binaries into an installer-less application.

                                                      Some folks have suggested that JavaFX never should have been bundled with Java in the first place, which makes sense from various perspectives: like why include three different windowing kits (AWT, Swing, and JavaFX)?

                                                      JavaFX has a great programming model for modern, null-hostile, OOP/functional-hybrid desktop applications. If starting over, I’d have opted for a different tech stack because it’s so buggy. Some examples: pressing Alt+Tab to switch applications activates the menu’s mnemonics and doesn’t release upon returning to the app; the default platform file chooser dialog doesn’t return focus to the application in all cases; there’s no way to implement highly accurate synchronized scrolling using the WebView component API; and SwingNodes—a bridge between Swing and JavaFX—are blurry, but only on Windows. Except for the last issue, they’ve all been worked around, but it shreds time that I’d’ve rather spent building features.

                                                      1. 4

                                                        I recently took over a few JavaFX apps at work and am in the process of migrating them from Java 8 (bundled JavaFX) to Java 11 (external dep). I’ve not done GUI stuff in Java in a long time and I’m actually positively surprised how nice it is. Feels a lot better than Swing for sure, but my experience here is now measured in weeks, not months.

                                                    1. 2

                                                      Since last October, a number of new features have been added, including support for typesetting Markdown documents as PDF files; see the screenshots for more details.

                                                      Your thoughts and feedback?

                                                      1. 1

                                                        Working on integrating the ConTeXt typesetting software into my text editor, KeenWrite. TeX output is splendid, but (writing documents in) LaTeX is not my cup of code. I prefer to write in plain text—Markdown—then generate a PDF file. ConTeXt allows its users to completely separate of content and presentation, making it a fine fit for formatting plain text. At present, KeenWrite checks to see if ConTeXt is installed, but doesn’t yet invoke it:

                                                        https://i.ibb.co/0j6p5Cr/export-pdf.png

                                                        Nearly everything is wired up. This has been about five years in the making, so I’m super-excited to reach this milestone.

                                                        1. 3

                                                          If stars align, I plan to update KeenWrite to export as PDF using ConTeXt. At present, I use the ecosystem explained in my Typesetting Markdown series to transform Markdown documents into PDFs. This week I added support for Pandoc’s extended fenced div syntax, which I hope will dovetail nicely into generating PDFs from XHTML.

                                                          1. 3

                                                            Vollkorn (SIL) is an especially nice typeface to my eye, though it appears to have a few issues with ligatures at the moment. I used it in my Typesetting Markdown series to automatically typeset Jekyll & Hyde, Les Mis, Pride & Prejudice, and others using ConTeXt. I’ve also used it in the preview pane of the text editor I’m developing (demo).

                                                            1. 5

                                                              This is very cool. It’s unfortunate that the very first example is the Lena image, though. :-(

                                                              1. 7

                                                                I wish people would stop using that image as an example. Not because of its content—though that part isn’t ideal either—but because the source file is so old and mediocre that it isn’t remotely representative of the images we routinely handle today. Worst of all the extreme colour cast makes it useless for judging skin tones.

                                                                1. 4

                                                                  The author doesn’t seem to be from the US, and the last commit appears to be from 2016.

                                                                  1. 3
                                                                    1. 3

                                                                      I find very unfortunate that there are people who find this unfortunate. You are literally spreading cancer culture.

                                                                      1. 5

                                                                        I agree, the whole “Losing Lena” movement was a total beat-up of what is really just a small number of people using this image essentially as a in-group meme. The cropped version (the only one I’ve ever seen used in the past 20+ years) is ridiculously tame compared to images that continuously bombard us in contemporary media, especially marketing targeted at women.

                                                                        That’s not to say we should continue using the image. We shouldn’t. We should stop using it because it’s grossly unrepresentative of photographic depictions of human skin. We should stop using it because the image is horrifically poor in quality. We should also stop using it because there’s no reason to use something with even a jot of sexual content.

                                                                        1. 4

                                                                          No one is being cancelled, though?

                                                                          1. 3

                                                                            I mean… I’m pretty skeptical of a lot of this stuff, but afaik Lena has personally asked people to stop doing it. It’s not some “hypothetically she might be upset”, it’s “the subject of this picture has requested that you find an alternative”.

                                                                            1. 3

                                                                              Do you have a reference on Lena asking people to stop using it? I couldn’t find anything in that Wikipedia article, and it would change the situation considerably.

                                                                              I mean, regardless of whether she actually said anything or not, I think I would be on the side of “maybe we shouldn’t be using that image everywhere”. A lot of my work involves working with raw pixel data, and I find the tool at https://rawpixels.net super useful. However, it uses the Lena image as a default/placeholder image, and looking at very obviously sensual pictures of women, who show no signs of having clothes on, on a 28” display at work, in an open office space, is pretty awkward.

                                                                              1. 10

                                                                                I’m Lena. I retired from modeling a long time ago. It’s time I retired from tech too.

                                                                                https://vimeo.com/372265771

                                                                                1. 0

                                                                                  Do you have a reference on Lena asking people to stop using it? I couldn’t find anything in that Wikipedia article, and it would change the situation considerably.

                                                                                  Hrm. I recalled it was when she went to the “Conference of the Society for Imaging Science in Technology”. I’ve gone and dug up what she actually said, and it would take a real effort to twist it to the interpretation I’d heard. Sounded to me more like she’s bemused by the popularity of the image than upset.

                                                                                  Deliberately not reposting what she said here as I’m disinterested in a long thread of people dissecting it.

                                                                                  1. 4

                                                                                    She does ask for folks to stop using her photo for this purpose in the video at https://www.losinglena.com/.

                                                                                    1. 0

                                                                                      Ah. I didn’t watch it because I dislike getting info via video and they’ve declined to offer any other format.

                                                                                      Can you suggest a timestamp to make checking easy?

                                                                          1. 1

                                                                            It might be useful to replace "$0" with "$(which "$0")", so that if you’re executing the script from the PATH it will still get the help correctly.

                                                                            1. 4

                                                                              $0 is the full command path, even if it’s executed from PATH. At least it is on my system under Dash 0.5.10.2 and Bash 5.0.17.

                                                                              1. 2

                                                                                Also the case on OpenBSD ksh.

                                                                              2. 1

                                                                                Another possibility is to create some constants:

                                                                                readonly SCRIPT_SRC="$(dirname "${BASH_SOURCE[${#BASH_SOURCE[@]} - 1]}")"
                                                                                readonly SCRIPT_DIR="$(cd "${SCRIPT_SRC}" >/dev/null 2>&1 && pwd)"
                                                                                readonly SCRIPT_NAME=$(basename "$0")
                                                                                
                                                                              1. 2

                                                                                Here’s another variation on shell scripts presenting help information:

                                                                                ARGUMENTS+=(
                                                                                  "a,arch,Target operating system architecture (amd64)"
                                                                                  "b,build,Suppress building application"
                                                                                  "o,os,Target operating system (linux, windows, mac)"
                                                                                  "u,update,Java update version number (${ARG_JRE_UPDATE})"
                                                                                  "v,version,Full Java version (${ARG_JRE_VERSION})"
                                                                                )
                                                                                

                                                                                The lines are machine-readable and alignment is computed by a bash build script template:

                                                                                https://github.com/DaveJarvis/scrivenvar/blob/master/build-template#L186

                                                                                When the installer script’s help is requested, the following is produced:

                                                                                $ ./installer -h
                                                                                Usage: installer [OPTIONS...]
                                                                                
                                                                                  -V, --verbose  Log messages while processing
                                                                                  -h, --help     Show this help message then exit
                                                                                  -a, --arch     Target operating system architecture (amd64)
                                                                                  -b, --build    Suppress building application
                                                                                  -o, --os       Target operating system (linux, windows, mac)
                                                                                  -u, --update   Java update version number (8)
                                                                                  -v, --version  Full Java version (14.0.1)
                                                                                

                                                                                Using an array reduces some duplication, though more can be eliminated. Scripts typically have two places where the arguments are referenced: help and switch statements. The switch statements resemble:

                                                                                https://github.com/DaveJarvis/scrivenvar/blob/master/installer#L191

                                                                                Quite often argument parsing entails either assigning a variable or (not) performing an action later. Introducing another convention would allow hoisting the switch statement out of the installer script, up into the template. Off the cuff, this could resemble:

                                                                                ARGUMENTS+=(
                                                                                  "ARG_ARCH,a,arch,Target operating system architecture (amd64)"
                                                                                  "do_build=noop,b,build,Suppress building application"
                                                                                  "ARG_JRE_OS,o,os,Target operating system (linux, windows, mac)"
                                                                                  "ARG_JRE_UPDATE,u,update,Java update version number (${ARG_JRE_UPDATE})"
                                                                                  "ARG_JRE_VERSION,v,version,Full Java version (${ARG_JRE_VERSION})"
                                                                                )
                                                                                

                                                                                The instructions to execute when arguments are parsed are thus associated with the arguments themselves, in a quasi-FP style. This approach, not including the FP convention, is discussed at length in my Typesetting Markdown series.