New Post Command


Overview

The new_post command is designed to create the YAML front matter for a new post (the content will be written directly in the markdown file). As you’ll see throughout the rest of the series on nanoc commands, the new_post command is the template for other content types. The focus is on flexibility, allowing the user to create tags and an image at the command line if desired. Let’s get started

Command Header

The command begins with a few header elements that are required for all nanoc commands. You should use simple language here because these elements show up in the help for the command.

Usage

usage       'new_post [options]'

The usage line tells the user what they need to type after ‘nanoc’ in order to execute the command. (in this case nanoc new_post) This should match the command’s file name (i.e. new_post.rb = new_post. The ‘[options]’ at the end indicates that it has options.

Aliases

aliases     :np, :newpost

Aliases are abbreviations that the user can enter in order to execute the command. I’ve chosen the alias ‘np’ (short for new post) and ‘newpost’. Don’t forget to put the “:” in front of the alias so its get picked up by the command.

Summary

summary     'Creates a new post'

A one line summary of what the command does.

Description

description 'This command creates a new post.'

A more detailed description of what the command does. This can be multi-line.

Flags

Flags are ‘on/off’ switches (which don’t have arguments) that allow you to indicate if something if an attribute exists or doesn’t. For example you might have a ‘c’ flag that turns comments on or off for a post. To trurn comments ON you would type

nanoc np "New Post" -c

The help flag is a special type of flag.

Help Flag

flag   :h, :help,  'show help for this command' do |value, cmd|
  puts cmd.help
  exit 0
end

The ‘h’ or ‘help’ flag prints out all of the header info (command name, usage, description, options) whenever the user types ‘-h’ after the command name. This is very helpful for figuring out what the command does and what options the user has when executing the command.

See an example below:

NAME                                                                                                                                                                                      
    new_post - Creates a new post                                                                                                                                                         
    aliases: np newpost                                                                                                                                                                   
                                                                                                                                                                                          
USAGE                                                                                                                                                                                     
    nanoc new_post [options]                                                                                                                                                              
                                                                                                                                                                                          
DESCRIPTION                                                                                                                                                                               
    This command creates a new post.                                                                                                                                                      
                                                                                                                                                                                          
OPTIONS                                                                                                                                                                                   
    -h --help        show help for this command                                                                                                                                           
    -i --image       add an image to the post (upload image to content/post/images/ first) and enter the filename                                                                         
    -t --tags        tags

Options

Options are special flags that have a string associated with them. For example, if you add the “-t” option flag to ‘nanoc np’ and then type a list of tags separated by commas (ie. -t “news,information”) you can add tags to the newly created post. Another option in this command, ‘-i’ adds an image to the top of the post if the image is uploaded to the posts/images/folder.

run

The ‘run’ command is where all the action is. It takes the arguments (i.e. the name of the post) and the options and executes code. Let’s take the entire run block in pieces:

require

The run block references some code which is contained in third-party ruby gem files. The ‘to_url’ function requires the “stringex” gem and some of the input/output files require “highline”. I’ve also created a bunch of helper functions for nanoc commands which I’ve put in the ‘lib’ directory. See the following post.

line

The line object stores the results of the Highline gem’s ‘ask’ function so that I can query the user if he/she wants to overwrite an existing post with the same filename.

local

I prefer to have the timestamps in my local timezone so I wrote a simple function called ‘tz’ which takes the current time and applies the relevant timezone offset from UTC.

file names

The yaml and content for each post is stored in a markdown file in the content/posts directory which is titled date-title.md (i.e. 2013-11-20-new-post-command.md).

tags

I convert the tags option to an array of tags so that I can print it out under the “tags:” heading.

post

Once all the elements have been created, I open the newly created file (see filename) and store the I/O in the post object. I write out the YAML front matter line-by-line. Remember that the first and last lines of the front matter must be ‘—’. I have created a custom function called print_attr which takes options that have multiple values (such as tags) and prints them out line by line. I also check if the image option has a value, and if so, I print the image filename in the YAML front matter so it can be incorporated when the page is compiled.

The full run block is below.

run do |opts, args, cmd|
  require 'stringex'
  require 'highline'
  require './lib/helpers.rb' 
  line = HighLine.new
  local = tz(Time.now,'America/New_York')
  FileUtils.mkdir_p './content/posts'
  title = args[0]
  tags = string_to_array(opts[:tags])
  filename = "./content/posts/#{Time.now.strftime('%Y-%m-%d')}-#{title.to_url}.md"
  check_exists(filename, line, "Abort! New Post not created!")
  puts "Creating new post: #{filename}"
    open(filename, 'w') do |post|
    post.puts '---'
    post.puts "title: \"#{title}\""
    post.puts "created_at: #{local}"
    post.puts 'kind: article'
    post.puts 'type: post'
    if !opts[:image].nil? 
      post.puts "image: #{opts[:image]}"
    end
    print_attr(tags, "tags", post)
    post.puts "---\n\n"
  end
end

Full Code

The full code listing of new_post.rb is below so you can see how everything fits together.

usage       'new_post [options]'
aliases     :np, :newpost
summary     'Creates a new post'
description 'This command creates a new post.'

flag   :h, :help,  'show help for this command' do |value, cmd|
  puts cmd.help
  exit 0
end

option :t, :tags, 'tags', :argument => :optional
option :i, :image, 'add an image to the post (upload image to content/post/images/ first) and enter the filename', :argument => :optional
  
run do |opts, args, cmd|
  require 'stringex'
  require 'highline'
  require './lib/helpers.rb'  
  line = HighLine.new
  local = tz(Time.now,'America/New_York')
  FileUtils.mkdir_p './content/posts'
  title = args[0]
  tags = string_to_array(opts[:tags])
  filename = "./content/posts/#{Time.now.strftime('%Y-%m-%d')}-#{title.to_url}.md"
  check_exists(filename, line, "Abort! New Post not created!")
  puts "Creating new post: #{filename}"
    open(filename, 'w') do |post|
    post.puts '---'
    post.puts "title: \"#{title}\""
    post.puts "created_at: #{local}"
    post.puts 'kind: article'
    post.puts 'type: post'
    if !opts[:image].nil? 
      post.puts "image: #{opts[:image]}"
    end
    print_attr(tags, "tags", post)
    post.puts "---\n\n"
  end
end

comments powered by Disqus

Date

Wednesday, November 20, 2013

Estimated Reading Time

7 minutes

Categories

Previous Article

Next Article