Posts

  • (reduce summarize year-2019)

    Be at war with your vices, at peace with your neighbors, and let every new year find you a better man.

    – Benjamin Franklin

    It’s again this time of the year when we get to reflect on the year behind us and hope for a better year ahead of us. Earlier today I read my summary of 2018 and the goals I set for myself for 2019. As usual, I’ve failed to fulfill all of my objectives, but I feels that I did reasonably well overall.

    Read More
  • Meta Advent 2019 Redux

    Now that the “Meta Advent 2019” blogging challenge is behind me, I’d like to write some thoughts on it.

    I’m super proud of myself. Frankly, I wasn’t quite sure I’ll make it. 24 blog posts are a lot! I had never had a blogging streak of more than 5 days (give or take), so the objective was as ambitious as they get. Still, somehow I found the time, the energy and the focus needed to succeed. The articles I wrote were certainly not my finest, but I think I had several pretty good ones and I hope they were useful to my dear readers.

    Goals are a great thing. The clear goal of this challenge kept me going and focused those past 3 weeks. Seeing the progress the other people were making (especially Arne) also helped a lot.

    Having a backlog of topics is important. I didn’t have any specific plan for the articles that I was going to write, but I did have a long list of ideas in general. Some of the topics were there for years before I finally got to writing about them. On the other hand - at least a third of the topic ideas came to me on the fly. Basically they were inspired by something I was doing the day I wrote the article.

    The more you write the easier it becomes. I wrote most of the articles in something like 30 minutes. The longest articles took me something like 2 hours, mostly because they needed more copy editing before I was happy with their state.

    An Advent of Emacs would be pretty cool. That’s something I realized during the course of the Meta Advent. Unfortunately there was absolutely no way I could find the time to write two articles each day. Maybe next year… At any rate, I certainly plan to write a few Emacs Redux articles now.

    I’m (probably) not doing this again. December was a super busy month for me at work, so it was really hard to find time for writing, or anything else for that matter. That’s also the main reason why most of the articles were pretty short. As my limited free time went into blogging I didn’t have much activity on my OSS projects this month.

    Role models are important. Special thanks to Arne for kicking off the whole “Advent of Parens” idea! You should also check out his thoughts on the whole experience.

    That’s all I have for you today. Short, sweet and chaotic! Now it’s time for me to go back to reading other people’s blog posts and to work on my OSS projects. Merry Christmas, everyone!

  • Weird Ruby: Array Multiplication

    This article is part of the “Meta Advent 2019” series. I’ve committed to writing a new blog post here every day until Christmas.

    So, we’ve made it to the final day of this year’s advent and to the final day of my “Meta Advent” blogging marathon! Time to examine another fun Ruby weirdness!

    Most Rubyists probably know that they can use Array#* to “multiply” an array:1

    arr = [1, 2, 3]
    arr * 3 # => [1, 2, 3, 1, 2, 3, 1, 2, 3]
    

    Nothing weird so far. Array#*, however, can do a bit more than this - its behaviour changes drastically when you pass a string instead of a number to it:

    arr * " " => "1 2 3"
    arr * "," => "1,2,3"
    

    Seems now it behaves just like Array#join. Weird, right? I’d strong advise against using Array#* instead of Array#join, but it’s a cool little trick to know and a fine example of Ruby’s extreme flexibility.

    That’s all I have for you today! Enjoy the holidays!

    Articles in the Series

    1. I can’t remember when was the last time I needed to do something like this. 

  • Hard CIDER: Dealing with Multiple Project Markers

    This article is part of the “Meta Advent 2019” series. I’ve committed to writing a new blog post here every day until Christmas.

    A while ago I wrote an article explaining how the jack-in process in CIDER works, but I omitted one subject - what happens if your project has multiple project marker files (e.g. project.clj and deps.edn). This wasn’t a big issue a few years back, when almost everyone was using Leiningen, but now it’s pretty common to have some project with both Leiningen and tools.deps project marker files in it, or maybe tools.deps and shadow-cljs. So, how does CIDER handle such ambiguity and decide which tool to use when starting a REPL?

    Well, by default it will simply prompt you to select one of the build tools it detected. Pretty simple, but also a bit annoying if you keep selecting the same tool all of the time. Fortunately, CIDER has an option to customize this though the cider-preferred-build-tool configuration variable.1 If you’re fond of Leiningen you can instruct CIDER to always prefer it like this:

    (setq cider-preferred-build-tool 'lein)
    

    In practice it will be common to have the preferred build tool depending on the project you’re working on, so an optimal approach to leverage this variable would be through project-specific configuration:

    ((clojure-mode
      (cider-preferred-build-tool . lein)))
    

    In the end of the day you might combine the two approaches by putting in your global configuration (e.g. init.el) your favourite tool and overriding this default choice on a per-project basis via .dir-locals.el. That’s what I normally do, although frankly speaking, I restart my REPLs so rarely that I don’t have any issues being prompted about the build tool to use every time I do so.

    That’s all I have for you today. See you again tomorrow!

    Articles in the Series

    1. CIDER uses the “build tool” terminology for historical reasons, as tools.deps didn’t exist back then. 

  • mdfind: A Command-line Interface to macOS's Spotlight

    This article is part of the “Meta Advent 2019” series. I’ve committed to writing a new blog post here every day until Christmas.

    macOS’s Spotlight is an extremely powerful and fast search tool. Its speed is derived from the fact that internally Spotlight relies on a pre-built file database (similar to what the Unix utility locate does). While for most people using Spotlight’s GUI interface is probably fine, people like me prefer to be able to leverage it from their terminals. Fortunately, that’s pretty easy to do, as macOS ships with a command-line interface for Spotlight called mdfind.1

    Let’s play a bit with mdfind to see how it can help us. I’ll share with you some of the ways in which I normally use mdfind. I encourage all of you to try the examples locally to get a better feel for how the different commands works.

    Here’s how you’d search for all files containing some text (you can think of this as some hybrid of grep and find):

    $ mdfind cider
    

    Here’s how you’d search for all files matching some name:

    $ mdfind -name bozhidar.jpg
    

    Note that this does a simple text match for the name, so you can easily expand the search by making it more generic:

    $ mdfind -name bozhidar
    

    You can also search for multiple words in the filename:

    $ mdfind -name clojure mobi
    

    You can easily limit the search to a particular directory like this:

    $ mdfind -onlyin ~/Downloads -name bozhidar
    

    Another way to limit a search is by specifying the type (kind) of the files to look for/in:

    $ mdfind kind:image -name bozhidar
    

    You can also do some fancier searches by matching for some specific macOS file metadata. The example bellow is searching for all files and folders named exactly “Clojure”:

    $ mdfind "kMDItemFSName = Clojure"
    

    Admittedly it’s not very easy to remember attribute names like this one, but the possibility this opens up are almost endless. To get an idea about the metadata attributes that exist you can check them for some file with the mdls command:

    $ mdls index.md
    kMDItemContentCreationDate         = 2018-10-27 06:08:22 +0000
    kMDItemContentCreationDate_Ranking = 2018-10-27 00:00:00 +0000
    kMDItemContentModificationDate     = 2018-10-27 06:08:22 +0000
    kMDItemContentType                 = "net.daringfireball.markdown"
    kMDItemContentTypeTree             = (
        "net.daringfireball.markdown",
        "public.item",
        "public.text",
        "public.data",
        "public.content",
        "net.daringfireball.markdown",
        "public.plain-text"
    )
    kMDItemDateAdded                   = 2018-10-27 06:08:22 +0000
    kMDItemDateAdded_Ranking           = 2018-10-27 00:00:00 +0000
    kMDItemDisplayName                 = "index.md"
    kMDItemFSContentChangeDate         = 2018-10-27 06:08:22 +0000
    kMDItemFSCreationDate              = 2018-10-27 06:08:22 +0000
    kMDItemFSCreatorCode               = ""
    kMDItemFSFinderFlags               = 0
    kMDItemFSHasCustomIcon             = (null)
    kMDItemFSInvisible                 = 0
    kMDItemFSIsExtensionHidden         = 0
    kMDItemFSIsStationery              = (null)
    kMDItemFSLabel                     = 0
    kMDItemFSName                      = "index.md"
    kMDItemFSNodeCount                 = (null)
    kMDItemFSOwnerGroupID              = 20
    kMDItemFSOwnerUserID               = 501
    kMDItemFSSize                      = 175
    kMDItemFSTypeCode                  = ""
    kMDItemInterestingDate_Ranking     = 2018-10-27 00:00:00 +0000
    kMDItemKind                        = "Plain Text Document"
    kMDItemLogicalSize                 = 175
    kMDItemPhysicalSize                = 4096
    

    You can find more information on metadata attributes, as well as some advanced mdfind queries here.

    Another cool thing about mdfind is that you never have to rebuild its database manually, as this is automatically handled by macOS. When I was using GNU/Linux back in the day I’d have to setup some cron job to keep my locate database up to date, and occasionally I’d had to trigger its update manually.

    That’s all I have for you today. I’d love it if you share in the comments some of your favourite uses of mdfind. See you tomorrow!

    1. I believe MD stands for “meta data”. 

Subscribe via RSS | View Older Posts