RSS Feed

Author Archives: Catalina Feloneous

What PicoCMS deleted – How to write Macros

The following was written by Lloyd Sargent as part of a contribution to the PicoCMS wiki. The contribution was deleted without reason and without notice. It is reprinted here because information, even information you didn’t create, should never be deleted.

Minor edits were made to the original (Sorry, Lloyd!)

I had no issues with PicoCMS until I needed to put onmousedown in an img. Try as I might, nothing worked. It was an intractable problem. I was about to resort to Javascript when I realized that I could do it using Twig. What’s more, once I started doing this, I realized I could avoid putting HTML into my Markdown files! A big win!  

What are we making?

Technically, what we are creating are stupid simple macros with Twig. Could we not use Twig macros? From what I understand (noob at Twig!) the answer is no. Twig macros are designed to work in Twig. I wanted the macros to work within my Markdown files. The goal is to have our Markdown files evaluated by Twig and make substitutions when it encounters our macros.  

How complex are these macros?

Basically, they are stupid simple. Quite literally, we replace all the macros with the target text. For example:

[img_url] assets/2018/IMG_4026.jpg [img_text] Baby Nine-Banded Armadillo [/img]

Those things with the square brackets are my macros. When they are evaluated they turn into the following:

<figure id="myImg" onmousedown="zoomImageClick(this)”>
  <img class="modal-content" alt=""src="assets/2018/IMG_4026.jpg”>
  <figcaption> Baby Nine-Banded Armadillo </figcaption>
</figure>

The goal in all of this was to allow users to click on my images and zoom them up into bigger pictures (as well as spit out a nice looking caption). This was nigh impossible using markdown. Doing it in HTML was just ugly. Doing it with macros was trivial.  

Part One: Okay, you’ve got me interested – what do I do?

This is the cool part: very little.   Let’s start with your index.twig file. The idea is that we want to substitute our macro labels with the HTML code (or whatever you want, really).  

   {# ==== Do macro Substitution - macros are in our theme config YAML ==== #}
   {% for macro_name, macro_value in config.website_macros %}
      {% set content = content|replace({(macro_name):  (macro_value)}) %}
   {% endfor %}

   {# ==== Display our content like normal ==== #}
   <div id="main">
      <div class="container">
         {{ content }}
      </div>
   </div>

Part Two: YAML file that contains our website macros

Remember that config directory that contained the config.yml file? You can have more than one configuration file. And since they are YAML files, everything can be structured. So, create a file named `yourwebsite.yml` and put the following in it:

website_macros:
    '[img_url]':  '<figure id="myImg" onmousedown="zoomImageClick(this)"><img class="modal-content" alt="" src="'
    '[img_text]': '"><figcaption>'
    '[/img]':     '</figcaption></figure>'

This creates three different macros. They are used as follows:

[img_url] pico_url [img_text] Hello World [/img]

But wait… oh, never mind that was it!

These are macros without any type of parameters (basically simple substitution). It’s simple substitution that makes my creation of pages easier. The best part? It looks far better than the line upon line of HTML in a Markdown file.

UPDATE:
Lloyd chatted with the person who removed his submission. It seems that the issue had less to do with censorship than ‘that’s not how I’ve always done it’. They resolved the issue amicably.

Advertisements

Wikis and Censorship

A wiki is a website on which users collaboratively modify content and structure directly from the web browser. In a typical wiki, text is written using a simplified markup language and often edited with the help of a rich-text editor.

A friend of mine just reported to me that PicoCMS (picocms.org) deleted content he added to their wiki. It was very small and, for the most part, innocuous. It had been removed without warning, without justification, and without reason.

I explained to him that it may have been because the original author felt that it went against the grain of PicoCMS. That perhaps there was a valid reason for it. No, he pointed out, it was a third person. Worse, this same person had deleted other people’s contributions.

He complained that it was an anti-wiki.

Looking into it, there are no rules for PicoCMS’s Wiki; nothing that said, “Oh, it is a wiki in name only, any contributions will be summarily deleted.”

To me this is disturbing. A wiki is an all or nothing affair. You either accept other people’s contributions (like Wikipedia), or you lock people out of it. You don’t promote it as one thing while treating it as another.

I also explained to my friend that open-source doesn’t necessarily mean it is open to suggestions or contributions. Sometimes collaborative only means, “Collaborative with the right people.” Needless to say, he wasn’t mollified.

As such, I’ll repost his attempt to contribute in the next post.

Popovers are NOT Dead on the iPhone

I just spent some time reading and responding to an article that attempted to argue that popovers on iOS 10 don’t work. This is semi-correct: they don’t work intuitively (they never were very intuitive from my point of view).

However, I have an Objective C program that has popovers that have been working quite well.

Here is an image:

Untitled

The first thing you may say is, “Wow, that looks a lot like a popover” and you would be correct (running on an iPhone 5 with iOS 10.2.1).

However, this guy was writing Swift. So then the question was, could it be done in Swift? Perhaps there was something special and Swift was preventing his popovers to act like popovers?

I eventually found an example here by Bartłomiej Semańczyk and bhnascar. I took it and simplified it a little.

import UIKit

class ViewController: UIViewController, UIPopoverPresentationControllerDelegate {
    @IBOutlet weak var bottomButton: UIButton!

    override func viewDidLoad() {
        super.viewDidLoad()
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }

    

    @IBAction func importantButtonPressed(_ sender: UIButton) {
        let popoverContentController = UIViewController()
        popoverContentController.view.backgroundColor = UIColor.blue

        // Set your popover size.
        popoverContentController.preferredContentSize = CGSize(width: 300, height: 300)

        // Set the presentation style to popover
        popoverContentController.modalPresentationStyle = UIModalPresentationStyle.popover

        // Set the popover presentation controller delegate
        popoverContentController.popoverPresentationController!.delegate = self
        popoverContentController.popoverPresentationController?.sourceView = bottomButton

        // Present the popover.
        self.present(popoverContentController, animated: true, completion: nil)

    }

    func adaptivePresentationStyle(for controller: UIPresentationController) -> UIModalPresentationStyle {
        // Return no adaptive presentation style
        return .none
    }
}

This is pretty easy to recreate:

  1. Create a new Swift project.
  2. Put a single button on the View Controller Scene.
  3. Copy (yes, some of it is hidden, but it does copy correctly) and paste the code from above and REPLACE all of the code in ViewController.swift.
  4. Connect the button to the importantButtonPressed method or you will be severely disappointed in me
  5. Run

What should happen is that as soon as you press the button, a blue popover appears. Hooray!

Why do People think Popovers are Dead?

I don’t know. Popovers have never been the easiest code to create, but they aren’t impossible either. Some have said that it is because Apple’s documentation is out of sync with the current iteration of Swift. This may be the true issue—a long time ago I seriously complained about the documentation with OS X beta and Apple asked if I wanted to be an unpaid volunteer to review their docs. That didn’t happen.

And it is true that popovers that work quite flawlessly on the iPad turn into full-screen modal dialogues on the iPhone. Someone at Apple has been paying too much attention to things other than ease of use for the developer.

Or that hobgoblin, consistency.

Anyway, I hope this helps people.
Read the rest of this entry

Interview Jeopardy

I’ll take obscure references for 500, Alex.

I’m of the age where I remember when an interview was actually that: what you had done, how you solve the problems, why you chose that solution over others.

Today, interviews have turned into the equivalent of gameshows with the interviewer attempting to pick unusual or even obscure questions to ask the candidate.

For example, I was interviewing for a iOS position and was asked about a particular class (it was designed to allow you to change the look of objects globally). I confessed I had never heard or used it, to which the interviewer said, “Yeah, I hadn’t heard of it until last year.”

So what exactly did he learn? Nothing. My non-usage of a class that even he hadn’t heard of merely pointed out that I had no need to make gross changes to the look-and-feel of iOS. Yes, we call that maintaining the User Experience, something that is very important.

The problem with iOS and OS X is that they have a lot of classes. Many of those classes have a lot of methods. There are many you will use a lot. There are some you may never use. This doesn’t mean that you don’t have the skills, what it means is that you might be one of those rare people who actually reads and uses documentation!

Interviewed By Those Ignorant on the Subject

On one interview I was asked the steps on creating a driver for Windows CE. I explained in detail omitting, by accident, allocating the buffer for the driver. Sadly, the person who was interviewing me only knew Windows and jumped on this with an “Aha!” and asked, “What would happen if you didn’t allocate the buffer?”

“Nothing,” I said, “you would get a black screen.”

“No,” he said obviously full of himself, “it would blue-screen.”

The problem is he was wrong. CE doesn’t always blue-screen. More often it black screens (i.e. nothing) and you end up playing 20 questions trying to figure out why. The problem is that the interviewer had no familiarity with Windows CE (a pretty spiffy RTOS that they slowed to a crawl by slapping much of the junk of Windows on top of it), didn’t know that it wasn’t Windows .

No surprise I didn’t get the job. Sadly, the person that was supposed to interview me was out the day. Also, sadly, this company boasted they hired, “The best of the best,” which means to say they didn’t hire people who knew more than they did.

Don’t get me wrong, hiring is very difficult. However, if someone has a degree and verifiable sources of employment then what is important, to me, is can they get along with the group.

I have had to take everything from timed internet tests where one had to solve puzzles (I loathe puzzles – software design is not puzzle solving), to answer obscure questions.

Rather than try to determine if I know something sans documentation (why memorize it if I can pull it up on the computer? Seems kind of dumb to me), ask me how I solved the decades of problems in C++. That seems far more realistic than silly questions. I not only have a degree, but more decades doing this than you have. Insulting me is not making you look good.

And that is what this really boils down to – it insults the people they are interviewing. Whether they believe it or not, what it says is “I do not trust what you put down on your resume, so prove to me, in 60 seconds, that you are as good as you are.”

So I asked the person who asked the first question, “Tell me what you are to learn from this answer?” He was taken aback. I was just supposed to do as he asked, not question the fact that there is no methodology here, merely random questions people made up in order to somehow judge the candidate.

This is, of course, where asking these random questions fail. They were asked to come up with something to quiz me with, with no guidelines as to what it meant. The candidate could have fifty patents, twenty books on C++ and fail all the questions. Does he get a pass because people know his name compared to the one that gets only 75% of them correct?

Failure Is An Option

Of the multiple interviews, I’ve only had a few that were truly interviews. The others were the Interview Jeopardy or in some cases, Interview Trivial Pursuits. They weren’t fun and all they told me was that this person was less qualified to conduct an interview than Alex Trebec.

Apparently not only is failure an option, these companies are willing to let valuable employees slip through their hands.

The question people should be asking, which they do not, is “Can this person learn our way of doing things?” Even more important, “Can this person continue to learn?” Knowledge is not a one-way street and because you have patterns that you have relied upon for five years doesn’t mean there are other, perhaps more important ones, that you ignored because the “Gang of Four” didn’t write them down.

This assumption of ignorance is currently killing our market. Everyone knows this. I have talked to recruiter after recruiter who has said it is embarrassing, has put off potential candidates and insulted others.

There is no shortcut in the interview process. And yet people keep trying.

When I am asked by friends who are looking, I do tell them about Interview Jeopardy and which companies I feel are the worst about it. Interview Jeopardy does a lot to harm the company brand and, worse, the company doesn’t seem to be aware of this. Why would I want to work for a company that is that self-unaware?

If the point of my interview is not about my skill set, then what is the point? (See? I phrased it as a question!)

Stupid Hash Functions

I’m getting very tired of reading about people implementing Hashable using the following (this is in Swift):

var hashValue : Int {
    get {
        return x ^ y   // x and y are Int
    }
}

Okay, first, let’s examine why this is wrong. The point of a hash function is to “create random data from the nonrandom data” (Knuth, Sorting and Searching) and since x ^ y is equal to y ^ x, it can hardly be considered a method of creating random data. Let us use some real world numbers (represented as hex)

  1. 0x2A ^ 0x40 = 0x6A
  2. 0x40 ^ 0x2A = 0x6A
  3. 0x00 ^ 0x6A = 0x6A
  4. 0x6A ^ 0x00 = 0x6A

A decent hash function? Hardly.

“Oh, but that is what Equitable is for” people have murmured. No, it’s because you slept during class about hashing. Hashing isn’t fun and yes it is hard to create a good hash function, but you didn’t even bother trying.

I don’t like to write hash functions either, but I have at least a basic fundamental understanding of the problems inherent in hash functions. It didn’t take me but a few seconds to come up with four test cases that produced exactly the same hash. Worse, x and y can be swapped and result in the same hash. Position should influence the result of a hash function.

But let us extend the problem to a buffer of four items, w, x, y, z, if you exclusive-or’ed them, you would get the same result had you done it z, y, x, w (go ahead, try it). The problem is that XOR is a communative operation exactly like addition. In fact, in hardware, XOR used to be called “half-adding” because the carry never influenced the next position.

  1. 0x2B ^ 0x5A ^ 0x11 = 0x60
  2. 0x2B ^ 0x11 ^ 0x5A = 0x60
  3. 0x11 ^ 0x5A ^ 0x2B = 0x60
  4. 0x11 ^ 0x2B ^ 0x5A = 0x60
  5. 0x5A ^ 0x11 ^ 0x2B = 0x60
  6. 0x5A ^ 0x2B ^ 0x11 = 0x60

As you can see, three bytes in different order produce exactly the same value. Exclusive or is obviously a poor way to create a hash value.

So this time, instead of pulling something out of our nether regions, let’s try something that makes a little more sense:

var hashValue : Int {
    get {
        return (x * 0x21) ^ y   // x and y are Int
    }
}

This is better. Why? Because we have now made sure that the values are based on their position. This becomes really important when you have a large buffer that needs to be hashed. So, using our previous values we have:

  1. (0x2A * 0x21) ^ 0x40 = 0x52A
  2. (0x40 * 0x21) ^ 0x2A = 0x86A
  3. (0x00 * 0x21) ^ 0x6A = 0x06A
  4. (0x6A * 0x21) ^ 0x00 = 0xDAA

This is a lot closer to creating random data from nonrandom data. Possibly the only minor irritant is the third case where anything with zero will result in the y value as the hash. We can correct this by using a simplified version of Daniel J. Bernstein’s hashing method:

var hashValue : Int {
    get {
        var hash = 5381        
        hash = (hash * 33) + x
        hash = (hash * 33) + y
        return hash
    }
}

Again, we assured that x and y are positional and that zero now affects the resultant hash.

I have hoped I have shown why hashing is not a simple science and why just exclusive-or’ing will result in a horrible hash.

Why I promised, NO REALLY, never to write a GUI API and why I’m breaking that promise

I have a love/hate relationship with Linux. I love many aspects about it. In the same way I hate many aspects about it.

Then came along Swift.

Swift is a gorgeous language. I think I could spend 20 years on learning it and still find surprises. It is like the tiny Christmas present that keeps giving and giving and giving.

The perfect lover.

Okay, maybe not that far, but if it was human it would be the perfect lover.

Many years ago I wrote a GUI API back when there were no GUI API’s. Now, of course, you can’t toss a rock without hitting one (sorry!). But here is the thing – they are all going to do it wrong. Not mildly wrong, but wrong wrong.

So, I’ve decided, along with a friend, that if there is going to be so much wrongness, we might as well toss in a little write… er, I mean, right.

We are building, “from the ground up”, an API for Linux. Which will also run on Mac OS and Windows (just so we can yell “trifecta!”… you don’t get to yell that often and it is fun word to say… come on, say it. SAY IT!)

We’re calling it Mobu which is the name of a dead, extinct bird. Instead of NSclass or UIclass it will be MMclass. Unless we decide on something else. I suggested emoticons, but my partner said that :)View would just annoy people.

I think it’s cute.

UPDATE: Partner did research and he says, “NO! Not Mobu. It will be Iken.”

Okay, then.

Swift on Linux

I was one of many who downloaded and ran Swift on Linux.

It’s spiffy.

But…. (you knew that was coming)

I like Swift. I’ve written what I call a “stupid parser” in Swift that performs quite admirably. But there isn’t an editor for Linux that has all the nice little bits that exist in Xcode.

That’s problem 1.

Then there is the fact that you have basically the language running in a command shell.

That’s problem 2.

I have no doubt that there are people working tirelessly (or tiredly) to get a GUI up and running that is Swift compatible. Unfortunately, those people were not Apple.

What Apple Did Correctly

If you have ever dealt with the GNUstep project (and I have on many occasions) you will discover that the applications it generates look like directories. That’s because they try to emulate what was done on NeXTSTEP – except it doesn’t quite work. Applications look like directories. Ick. The only way to make them look like applications is to run something that is (from Linux users view) nonstandard.

More ick.

Instead, Apple makes applications look like applications. Well, for the moment, they look like applications you run from the command line. That will change.

What to Expect in 2016

By the end of the year I expect there will be projects that allow you to build GUI programs. That will be spiffy.

There will be editors, probably even a playground.

What to Expect RIGHT NOW

You can build programs in Linux for x86 that run in the console. Yes, I ran a “Hello World”. Woo hoo.

And, of course, they did delegates correctly.

Microsoft has already said that they plan on supporting Swift in Windows (hopefully it won’t be a mangled version).

Swift is a nice, clean language. If you are used to C# or Objective C, then I would seriously suggest you look into it. I can easily see it surpassing both of them.

This could be the one language that rules them all.