27 May 2018

I have now a couple of sites using jekyll, one is this one and another one is this little news site that simply posts links to happy dog news. So far I've always created new posts using a small shell script or simply copying the previous entry and changing date/title.

Since that is a bit annoying, I decided to try using a plugin in Sublime Text, and this article explores how to do just that (spoiler: it's all python).

Jekyll templates have a relatively simple structure, based on a mix of YAML metadata and Markdown contents. For example:

---
layout: post
title: "Let's Encrypt support in Dreamhost"
categories: [blog]
tags: [main]
date: 2016-01-31 18:48:32 +0200
---
First paragraphs that will be shown on list views where you want only an
excerpt of the text.

<!--more-->

Rest of the article goes here

One can add any number of tags to the front matter, and then use them in templates to add particular behaviours. I use those in comics, for instance, to indicate the main image of the comic, or if it's a simple reference to a news article then I include a target-url to the source site.

The file name should include the date of the post, but they are actually sorted based on the date indicated inside the YAML front matter.

So, long story short, this is how to create a sublime text plugin:

  1. Go to Tools/Developer/New Plugin (creates a template file in the right location)
  2. Replace contents with something similar to the code below
  3. Any method ending in Command becomes available (eg "NewBlogEntryCommand" becomes new_blog_entry).
  4. Save file in the location indicated, name is irrelevant.
  5. Associate the command to a new shortcut: Preferences/Key Bindings and add an entry like:
  {"keys": ["ctrl+shift+b"], "command": "new_blog_entry" }

Here's the actual code I'm using, yours can be simpler or more complex. I'm asking for two parameters from the user: a title and a 'target url'. I will add thumbnailing capabilities to it soon (similar to what Twitter etc do).

import sublime
import sublime_plugin
import datetime
import re

class NewBlogEntryCommand(sublime_plugin.TextCommand):

    def run(self, edit):

        self.url = ""

        def on_done_url(input_string):
            self.url = input_string
            self.thumbnail = ""  # todo: fetch
            now = datetime.datetime.utcnow()
            targetview.run_command("insert_snippet", { "contents":
              """---
layout: post
title: "%s"
categories: [blog]
tags: [main]
date: %s
target-url: %s
thumbnail: %s
---
Text
<!--more-->
Text
"""
            % (self.title,
               now.strftime("%Y-%m-%dT%H:%M:%S+00:00"),
               self.url,
               self.thumbnail)
            })
            filename = re.sub(r'[^0-9a-z\-_ ]', '', self.title.lower())
            filename = filename.replace(' ', '-')
            targetview.set_name("%s-%s.markdown" % (now.strftime("%Y-%m-%d"),
              filename[:80]))


        def on_done(input_string):
            self.title = input_string
            targetwindow.show_input_panel("Main Url:", "", on_done_url, None, None)

        window = self.view.window()
        targetview = window.new_file()
        targetwindow = targetview.window()
        targetwindow.show_input_panel("Blog post title:", "", on_done, None, None)

A couple of notes:

  1. Receiving input from the user is asynchronous, so you register a callback
  2. You can add any python code you want, which is quite powerful if you are doing repetitive tasks.

(Follow me on Twitter, on Facebook or add this RSS feed) (Sígueme en Twitter, on Facebook o añade mi feed RSS)
details

Comments