class Til::Core
Constants
- GH_REPO_ENV_VAR_NAME
- GH_TOKEN_ENV_VAR_NAME
Public Class Methods
new(options: {}, kernel: Kernel, process: Process, env: ENV, github_client: nil, stderr: $stderr)
click to toggle source
# File lib/til/core.rb, line 28 def initialize(options: {}, kernel: Kernel, process: Process, env: ENV, github_client: nil, stderr: $stderr) @options = options @kernel = kernel @process = process @env = env @stderr = stderr @github_client = github_client @repo_name = nil @new_category = false end
run(options: {})
click to toggle source
# File lib/til/core.rb, line 11 def self.run(options: {}) # Exit if `fzf` is not available # Optionally print a spinner # Grab the list of existing categories # Feed them into fzf with a new entry to let the user type a category # Grab the category from fzf # Handle the case where it's a new category (as in, figure out the new place in the README) # Open $VISUAL or $EDITOR with a tempfile # Read the file content # Update the README.md with a link to the new entry # Create the new file # Create a new commit # Output a link to the file and the link to edit it til = new(options: options) til.run end
Public Instance Methods
run()
click to toggle source
# File lib/til/core.rb, line 39 def run catch(:exit) do check_dependencies check_environment_variables existing_categories = fetch_existing_categories selected_category = prompt_fzf(existing_categories) if @new_category selected_category = prompt_for_new_category end prepopulate_tempfile(selected_category, @options[:title]) open_editor til_content = read_file commit_new_til(selected_category, til_content) end end
Private Instance Methods
check_dependencies()
click to toggle source
# File lib/til/core.rb, line 57 def check_dependencies result = @kernel.system('which fzf', out: '/dev/null', err: '/dev/null') unless result raise "fzf is required, you can install it on macOS with 'brew install fzf'" end end
check_environment_variables()
click to toggle source
# File lib/til/core.rb, line 64 def check_environment_variables if @env[GH_TOKEN_ENV_VAR_NAME].nil? || @env[GH_TOKEN_ENV_VAR_NAME] == '' if @env['GH_TOKEN'].nil? || @env['GH_TOKEN'] == '' raise "The #{GH_TOKEN_ENV_VAR_NAME} (with the public_repo or repo scope) environment variable is required" else @stderr.puts "Using GH_TOKEN is deprecated, use #{GH_TOKEN_ENV_VAR_NAME} instead" end end if @env[GH_REPO_ENV_VAR_NAME].nil? || @env[GH_REPO_ENV_VAR_NAME] == '' if @env['GH_REPO'].nil? || @env['GH_REPO'] == '' raise "The #{GH_REPO_ENV_VAR_NAME} environment variable is required" else @stderr.puts "Using GH_REPO is deprecated, use #{GH_REPO_ENV_VAR_NAME} instead" end end end
commit_new_til(category, content)
click to toggle source
# File lib/til/core.rb, line 151 def commit_new_til(category, content) commit_title = content.lines[0].chomp if commit_title.start_with?('#') commit_title = commit_title[1..].strip end filename = new_filename(commit_title) ref = github_client.ref repo_name, 'heads/master' commit = github_client.commit repo_name, ref.object.sha tree = github_client.tree repo_name, commit.commit.tree.sha, recursive: true readme = github_client.readme repo_name readme_content = Base64.decode64 readme.content blob = github_client.create_blob repo_name, content blobs = tree.tree.filter { |object| object[:type] == 'blob' && object[:path] != 'README.md' }.map { |object| object.to_h.slice(:path, :mode, :type, :sha) } updated_readme_content = update_readme_content(category, commit_title, filename, readme_content) new_readme_blob = github_client.create_blob repo_name, updated_readme_content blobs << { path: 'README.md', mode: '100644', type: 'blob', sha: new_readme_blob } blobs << { path: "#{category}/#{filename}", mode: '100644', type: 'blob', sha: blob } tree = github_client.create_tree repo_name, blobs commit = github_client.create_commit repo_name, commit_title, tree.sha, ref.object.sha github_client.update_ref repo_name, 'heads/master', commit.sha cgi_escaped_filename = CGI.escape(filename) til_url = "https://github.com/#{repo_name}/blob/master/#{category}/#{cgi_escaped_filename}" til_edit_url = "https://github.com/#{repo_name}/edit/master/#{category}/#{cgi_escaped_filename}" puts "You can see your new TIL at : #{til_url}" puts "You can edit your new TIL at : #{til_edit_url}" end
fetch_existing_categories()
click to toggle source
# File lib/til/core.rb, line 82 def fetch_existing_categories existing_categories = github_client.contents(repo_name, path: '').filter do |c| c['type'] == 'dir' end existing_category_names = existing_categories.map do |category| category[:name] end existing_category_names << 'Something else?' end
github_client()
click to toggle source
# File lib/til/core.rb, line 94 def github_client @github_client ||= Octokit::Client.new(access_token: @env[GH_TOKEN_ENV_VAR_NAME] || @env['GH_TOKEN']) end
new_filename(commit_title)
click to toggle source
# File lib/til/core.rb, line 145 def new_filename(commit_title) today = Time.now.strftime '%Y-%m-%d' name = commit_title.split.map(&:downcase).join('-') "#{today}_#{name}.md" end
open_editor()
click to toggle source
# File lib/til/core.rb, line 134 def open_editor editor = ENV['VISUAL'] || ENV['EDITOR'] || 'vi' system(*editor.split, @tempfile.path) end
prepopulate_tempfile(selected_category, title = 'Title Placeholder')
click to toggle source
# File lib/til/core.rb, line 126 def prepopulate_tempfile(selected_category, title = 'Title Placeholder') @tempfile = Tempfile.new('til.md') @tempfile.write("# #{title}") @tempfile.write("\n" * 2) @tempfile.write("What did you learn about #{selected_category} today") @tempfile.close end
prompt_for_new_category()
click to toggle source
# File lib/til/core.rb, line 122 def prompt_for_new_category Readline.readline("New category > ").downcase end
prompt_fzf(categories)
click to toggle source
# File lib/til/core.rb, line 102 def prompt_fzf(categories) reader1, writer1 = IO.pipe reader2, writer2 = IO.pipe fzf_pid = @process.spawn('fzf', { out: writer1, in: reader2 }) reader2.close writer1.close writer2.puts categories.join("\n") writer2.close Process.waitpid(fzf_pid) selected = reader1.gets.chomp reader1.close if selected == 'Something else?' @new_category = true end selected rescue Errno::EPIPE => e @stderr.puts "Pipe issue: #{e}" throw :exit end
read_file()
click to toggle source
# File lib/til/core.rb, line 139 def read_file content = File.read(@tempfile) @tempfile.unlink content end
repo_name()
click to toggle source
# File lib/til/core.rb, line 98 def repo_name @repo_name ||= (@env[GH_REPO_ENV_VAR_NAME] || @env['GH_REPO']) end
update_readme_content(category, commit_title, filename, readme_content)
click to toggle source
# File lib/til/core.rb, line 188 def update_readme_content(category, commit_title, filename, readme_content) updater = Til::ReadmeUpdater.new(readme_content) if @new_category updater.add_item_for_new_category(category, commit_title, filename) else updater.add_item_for_existing_category(category, commit_title, filename) end end