I usually have several blog-post ideas in the pipeline, which I want to keep separate from my finished posts. This article shows how I added some rake
tasks to do this.
What I’ve tried
- Octopress’
published: false
does not work for me. It still generates the drafts, publishing them prematurely on the blog. I don’t know why this is. But even if it worked, I would still have my unfinished drafts somewhere among all my published posts, in the same folder. - I tried writing the drafts in a separate folder on the file system, and only when I was done I would do
rake new_post["My finished post"]
, open the Markdown file, and paste in the finished writing.
What I do now
-
Create the draft:
$ rake new_draft["Octopress Drafts"] Created draft at source/_drafts/2012-05-28-octopress-drafts.md
- The
new_draft
task opens it in Byword, so I can start writing right away. -
When I’m ready:
$ rake promote_draft [0] 2012-05-22-weekly-picks-11.md [1] 2012-05-26-party-profile.md [2] 2012-05-26-uberfordert.md [3] 2012-05-28-octopress-drafts.md Promote which draft? [0-9] 3 Promoted to source/_posts/2012-05-28-octopress-drafts.md
Rakefile additions
Here are my Rakefile additions if you want the same for yourself:
# -- Misc Configs -- ##
drafts_dir = "_drafts" # directory for unfinished blog files not to be generated
desc "Begin a new draft in #{source_dir}/#{drafts_dir}"
task :new_draft, :title do |t, args|
filename = `rake new_post['#{args.title}']`
posts_path = "#{source_dir}/#{posts_dir}"
drafts_path = "#{source_dir}/#{drafts_dir}"
mkdir_p drafts_path
destination = "#{drafts_path}/#{filename.strip}"
FileUtils.mv("#{posts_path}/#{filename.strip}", destination)
puts "Created draft at #{destination}"
`open #{destination}`
end
desc "Move a draft to #{source_dir}/#{posts_dir} when you're ready"
task :promote_draft do
drafts_path = "#{source_dir}/#{drafts_dir}"
Dir.glob("#{drafts_path}/*.*").each_with_index do |draft, idx|
draft_shortname = draft.gsub(/#{drafts_path}\//, '')
puts " [#{idx}] #{draft_shortname}"
end
index_to_promote = ask("Promote which draft?", ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'])
drafts_path = "#{source_dir}/#{drafts_dir}"
source = Dir.glob("#{drafts_path}/*.*")[index_to_promote.to_i]
filename = source.gsub(/#{drafts_path}\//, '')
destination = "#{source_dir}/#{posts_dir}/#{filename}"
FileUtils.mv(source, destination)
puts "Promoted to #{destination}"
end
# task :new_post // changes:
basename = "#{Time.now.strftime('%Y-%m-%d')}-#{title.to_url}.#{new_post_ext}"
filename = "#{source_dir}/#{posts_dir}/#{basename}"
# ... and at the very end:
puts basename # e.g. 2012-05-28-octopress-drafts.md
# end
Let me know what you think on Twitter: @yangmeyer
Cody quality
I’m afraid to say that my Ruby has become rather rusty, to the extent that I am happy that my code works (it’s scarily reminiscent of my JavaScript “skills” back in 2001, actually).
Some things I would like to improve:
- I originally had a
list_drafts
task, which I wanted to invoke frompromote_draft
. Without an Internet connection here, I could not find out how to do this. - Obviously, there is a lot of
"#{source_dir}/#{drafts_dir}"
code duplication going on. I probably should extract it todrafts_path
? - I lazily hard-coded the valid values of which draft to promote, as stringified integers 0–9. What would be a nice way to read in any integer?
- This being a blogging engine for hackers, who should know what they’re doing, I also don’t check whether the index is valid.
I’d be happy to hear your suggestions. Always glad to learn.