Bike 1.4 Preview (67) “Rich Text”

  • Added scripting access to rich text with html content
  • Added warning when editing rich text in unsupported document formats
  • Disable text formatting if the file format can’t save it
  • Changed block mode selection color
  • Improving overall styling performance
  • Fixed rich text typing attributes to work like standard macOS
  • Fixed rich text commands in outline mode
  • Fixed selection drawing

Scripting support for text formatting looks like this:

tell front document of application "Bike"
	set html content of first row to "<p><strong>Hello</strong> world</p>"
end tell

This API is nice because it’s simple to implement and maps directly to Bike’s file format behavior. It’s also very convent for setting a rows text.

It’s less convenient for editing an existing rows text … because to do it right (might be able to fake with simple string manipulation for many cases) you’ll need to parse existing html content make updates to DOM, serialize back to string, and then set new html content. If this is makes things to hard I’ll look at additional scripting API.


I think this version is feature complete for what I want from “Rich text” right now. I would like to release this soon, though I still need updated documentation, screenshots, etc. Please check for bugs and let me know what needs to be done before this release exits preview status.


To get preview releases through Bike’s software update select: Bike > Preferences > General > Include “preview” releases.

3 Likes

Is code formatting supposed to be different? It doesn’t seem to do anything.

code formatting

At display level it adopts a monospaced font.

For JavaScript for Automation, this kind of thing, FWIW, also parses successfully:

$.NSXMLDocument.alloc.initWithXMLStringOptionsError(
    html, 0, error
)

for example:

Expand disclosure triangle to view JS Source
(() => {
    "use strict";

    // HTML parsing example
    
    // Rob Trew @2020

    // main :: IO ()
    const main = () =>
        // Just drop the tags and extract the text leaves,
        // in this case.
        htmlForest(
            "<p><strong>Hello</strong> world</p>"
        )
        .map(
            foldTree(
                x => xs => (
                    Boolean(x.content) ? (
                        [x.content]
                    ) : []
                ).concat(xs.flat())
            )
        );

    // ------------------- PARSED HTML -------------------

    // htmlForest :: HTML String ->
    // [Tree {name::String, content::String}]
    const htmlForest = html =>
        either(() => [])(x => x.nest)(
            dictFromHTML(html)
        );


    // dictFromHTML :: String -> Either String Tree Dict
    const dictFromHTML = html => {
        const
            error = $(),
            node = $.NSXMLDocument.alloc
            .initWithXMLStringOptionsError(
                html, 0, error
            );

        return Boolean(error.code) ? (
            Left("Not parseable as XML: " + (
                `${html}`
            ))
        ) : Right(xmlNodeDict(node));
    };


    // xmlNodeDict :: NSXMLNode -> Node Dict
    const xmlNodeDict = xmlNode => {
        const
            unWrap = ObjC.unwrap,
            blnChiln = parseInt(
                xmlNode.childCount, 10
            ) > 0;

        return Node({
            name: unWrap(xmlNode.name),
            content: blnChiln ? (
                undefined
            ) : unWrap(xmlNode.stringValue)
        })(
            blnChiln ? (
                unWrap(xmlNode.children)
                .reduce(
                    (a, x) => a.concat(xmlNodeDict(x)),
                    []
                )
            ) : []
        );
    };


    // --------------------- GENERIC ---------------------

    // Left :: a -> Either a b
    const Left = x => ({
        type: "Either",
        Left: x
    });


    // Node :: a -> [Tree a] -> Tree a
    const Node = v =>
    // Constructor for a Tree node which connects a
    // value of some kind to a list of zero or
    // more child trees.
        xs => ({
            type: "Node",
            root: v,
            nest: xs || []
        });


    // Right :: b -> Either a b
    const Right = x => ({
        type: "Either",
        Right: x
    });


    // either :: (a -> c) -> (b -> c) -> Either a b -> c
    const either = fl =>
        // Application of the function fl to the
        // contents of any Left value in e, or
        // the application of fr to its Right value.
        fr => e => e.Left ? (
            fl(e.Left)
        ) : fr(e.Right);


    // foldTree :: (a -> [b] -> b) -> Tree a -> b
    const foldTree = f => {
    // The catamorphism on trees. A summary
    // value obtained by a depth-first fold.
        const go = tree => f(
            tree.root
        )(
            tree.nest.map(go)
        );

        return go;
    };


    // sj :: a -> String
    const sj = (...args) =>
    // Abbreviation of showJSON for quick testing.
    // Default indent size is two, which can be
    // overriden by any integer supplied as the
    // first argument of more than one.
        JSON.stringify.apply(
            null,
            1 < args.length && !isNaN(args[0]) ? [
                args[1], null, args[0]
            ] : [args[0], null, 2]
        );

    return sj(main());
})();
Expand disclosure triangle to view post-processed parse result
[
  [
    "Hello",
    " world"
  ]
]
Expand disclosure triangle to view full parse result
[
  {
    "type": "Node",
    "root": {
      "name": "p"
    },
    "nest": [
      {
        "type": "Node",
        "root": {
          "name": "strong"
        },
        "nest": [
          {
            "type": "Node",
            "root": {
              "content": "Hello"
            },
            "nest": []
          }
        ]
      },
      {
        "type": "Node",
        "root": {
          "content": " world"
        },
        "nest": []
      }
    ]
  }
]
1 Like

Aha, unless you change the editor font in the preferences. I changed mine to Charter, and apply code formatting did nothing. I was expecting it to shift to Menlo or another monospace font as it does when using the system font.

2 Likes

ditto here:

I’m also finding that:

  • Code-tagged spans are no longer displayed in a monospaced font when the main font is set to something other than System
  • as soon as we revert to using the System font (with Reset Typography in Preferences) any code-tagged spans immediately become monospaced (and thus visibly distinct) again.
1 Like
  • Changed block mode selection color

Love the green for the outline editing!

1 Like

As one of the users that voted for the Rich Text feature, I wanted to try it out but it looks like it requires a license first. Should I wait to try it out once it’s released?

thank you

Rich text editing will require a license.

If you buy a license from Hog Bay Software website you’ll get a year of free updates. So you can buy a license now and try the preview, and also get the preview.

Alternatively once the rich text release is ready I’ll post it to the Mac App Store. Then you can try out the rich text by getting a $2.99 monthly subscription. That gives you a cheaper way to try it, and then you can cancel after one month and get a longer term license if you want.

Sorry if this is a duplicate report, but I searched around and didn’t see anyone talking about this. Maybe it’s the font I use?

When I insert text into an existing line, all the text after it appears tiny until I stop typing.

d4270079-54a6-491a-988d-f680ad68e95b

1 Like

Good find! I’m not sure, but I don’t think this is related to your font (I guess try changing to “System” to see). I think I must have hard coded the UI scale somewhere. Are you using a non retina display or have some non default display scaling?

(Also what version of Bike are you using?)

Ah, you’re right, it’s the display! I’m using a Retina MBP with the lid closed, connected to an Acer X34 monitor at 3440x1440, and the problem disappears if I unplug the external display and use the built-in one.

Bike 1.4 Preview (67).

(And just to rule it out, I also “Reset Typography” and restarted Bike, but it didn’t fix anything.)

Or the dumb Bike programmer who didn’t account for the display! :slight_smile: Working on it now!

1 Like

Are you likely to add text colour as a rich text attribute? If not could this be set up via script, targeting selected text?

No I don’t think so.

I’m trying to add attributes that have a meaning behind them (and ideally map nicely to an HTML attribute). Specific text colors are also problematic when switching between light and dark mode.

Can you describe a little more what you are trying to do?

I do think that eventually Bike will enable what you want. It won’t add ability to set a specific text color, instead it will (I think) allow you to set a specific text attribute that you define (for example maybe priority1, priority2, priority3) and then in your stylesheet you could set a separate color for each priority level).

I don’t have a timeline yet for custom stylesheets. I’ve done a lot of work on them already for the rich text support, but there’s also a big chunk of work that remains to make them user editable. And I’m likely to be working on other features for a while before I get to them.

It seems this may be a bit of a specialist request, but it is something that is always uppermost in my mind when evaluating writing tools. I use colour a lot as a way of visually coding the significance of words, clauses or sections of text. For instance in writing comparative listings of software I will colour advantages of a particular app in green and disadvantages in red. Other significance codings may be broader, using up to 5 or 6 colours. I like how visually immediate such colouring is, turning the text into a form of infographic—or adding a visual layer to the layer of meaning contained within the text. (It is possible that being synasthetic makes this particularly attractive to me.) I prefer using text colour to highlighting since I find highlighting too visually emphatic.

I hope that explains the need. The process is less significant to me. I have used tags to style colours in TaskPaper for a long time, and while I’d prefer to dispense with the inline tags just to create styles, I’d be happy to use scripts or anything else that could be mapped to a keyboard shortcut, so long as the resulting (colour) styles could coexist with bold/italic etc.

I hope this answer to your question is not too wordy for this topic. Feel free to hive it off to its own topic.
Thanks, Nick

1 Like

Perhaps, in that that context, this application might look like a variety of highlighter pen colors (e.g. perhaps orange, green in addition to yellow), and take the form, for the stylesheet, of distinct classes for the <mark> tag ?

<mark class="xyz">

etc ?

Any chance we can have Bike use the OS’s designated highlight color or accent color?

I don’t think that will work. Highlight color is already used for selection highlight color, so it would be confusing to use for Bike’s highlight too.

I’m starting to think that at some point I’ll add a fixed set of highlight color options that are part of the underlying model, similar to how finder has a set of colors for tagging items. Probably this is a future feature, instead of one that I’ll add this release.

1 Like

I don’t see it any more in release 69. Thanks. :slight_smile:

1 Like