til-rb 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/LICENSE +21 -0
- data/README.md +7 -0
- data/bin/til +5 -0
- data/lib/til-rb.rb +2 -0
- data/lib/til/core.rb +184 -0
- data/lib/til/version.rb +5 -0
- metadata +77 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 40d7142e1a89db2641e1d6da0699c13ee4a4da511331c9822deaef61ca9d546b
|
4
|
+
data.tar.gz: 29eedc188aa255a16d0cb9734412594013b1b2a18ae2836c5194cc0a3ae827e5
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: d58c4a7620cfd20fc9901fa3bc10526662a6eea6c0393d58334976cf67a002a871bfad747c6b8ddd95190e824a9f98d2cd81548eebab2811cccefdda7a0d6aa6
|
7
|
+
data.tar.gz: c8f88bf4d8a0336efafcbcb4d0add65a8979845fbea4e34cca19e29a2563e06668335c94d22a3af1003f5eb35782db1329de158685a7518b84131276a0ea6486
|
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
MIT License
|
2
|
+
|
3
|
+
Copyright (c) 2020 Pierre Jambet
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
data/README.md
ADDED
data/bin/til
ADDED
data/lib/til-rb.rb
ADDED
data/lib/til/core.rb
ADDED
@@ -0,0 +1,184 @@
|
|
1
|
+
require 'octokit'
|
2
|
+
require 'tempfile'
|
3
|
+
|
4
|
+
module Til
|
5
|
+
class Core
|
6
|
+
|
7
|
+
def self.run
|
8
|
+
# Exit if `fzf` is not available
|
9
|
+
# Optionally print a spinner
|
10
|
+
# Grab the list of existing categories
|
11
|
+
# Feed them into fzf with a new entry to let the user type a category
|
12
|
+
# Grab the category from fzf
|
13
|
+
# Handle the case where it's a new category (as in, figure out the new place in the README)
|
14
|
+
# Open $VISUAL or $EDITOR with a tempfile
|
15
|
+
# Read the file content
|
16
|
+
# Update the README.md with a link to the new entry
|
17
|
+
# Create the new file
|
18
|
+
# Create a new commit
|
19
|
+
# Output a link to the file and the link to edit it
|
20
|
+
til = new
|
21
|
+
til.run
|
22
|
+
end
|
23
|
+
|
24
|
+
def initialize(kernel: Kernel, process: Process, env: ENV, github_client: nil, stderr: $stderr)
|
25
|
+
@kernel = kernel
|
26
|
+
@process = process
|
27
|
+
@env = env
|
28
|
+
@stderr = stderr
|
29
|
+
@github_client = github_client
|
30
|
+
@repo_name = 'pjambet/til'
|
31
|
+
@new_category = false
|
32
|
+
end
|
33
|
+
|
34
|
+
def run
|
35
|
+
catch(:exit) do
|
36
|
+
check_dependencies
|
37
|
+
check_environment_variables
|
38
|
+
existing_categories = fetch_existing_categories
|
39
|
+
selected_category = prompt_fzf(existing_categories)
|
40
|
+
prepopulate_tempfile(selected_category)
|
41
|
+
open_editor
|
42
|
+
til_content = read_file
|
43
|
+
commit_new_til(selected_category, til_content)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
private
|
48
|
+
|
49
|
+
def check_dependencies
|
50
|
+
result = @kernel.system('which fzf', out: '/dev/null', err: '/dev/null')
|
51
|
+
unless result
|
52
|
+
raise "fzf is required, you can install it on macOS with 'brew install fzf'"
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def check_environment_variables
|
57
|
+
if @env['GH_TOKEN'].nil? || @env['GH_TOKEN'] == ''
|
58
|
+
raise 'The GH_TOKEN (with the public_repo or repo scope) environment variable is required'
|
59
|
+
end
|
60
|
+
|
61
|
+
if (@env['VISUAL'].nil? || @env['VISUAL'] == '') && (@env['EDITOR'].nil? || @env['EDITOR'] == '')
|
62
|
+
raise 'The VISUAL or EDITOR environment variables are required'
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def fetch_existing_categories
|
67
|
+
existing_categories = github_client.contents(@repo_name, path: '').filter do |c|
|
68
|
+
c['type'] == 'dir'
|
69
|
+
end
|
70
|
+
|
71
|
+
existing_category_names = existing_categories.map do |category|
|
72
|
+
category[:name]
|
73
|
+
end
|
74
|
+
|
75
|
+
existing_category_names << 'Something else?'
|
76
|
+
end
|
77
|
+
|
78
|
+
def github_client
|
79
|
+
@github_client ||= Octokit::Client.new(access_token: @env['GH_TOKEN'])
|
80
|
+
end
|
81
|
+
|
82
|
+
def prompt_fzf(categories)
|
83
|
+
reader1, writer1 = IO.pipe
|
84
|
+
reader2, writer2 = IO.pipe
|
85
|
+
fzf_pid = @process.spawn('fzf', { out: writer1, in: reader2 })
|
86
|
+
reader2.close
|
87
|
+
writer1.close
|
88
|
+
writer2.puts categories.join("\n")
|
89
|
+
writer2.close
|
90
|
+
Process.waitpid(fzf_pid)
|
91
|
+
selected = reader1.gets.chomp
|
92
|
+
reader1.close
|
93
|
+
if selected == 'Something else?'
|
94
|
+
@new_category = true
|
95
|
+
end
|
96
|
+
selected
|
97
|
+
rescue Errno::EPIPE => e
|
98
|
+
@stderr.puts "Pipe issue: #{e}"
|
99
|
+
throw :exit
|
100
|
+
end
|
101
|
+
|
102
|
+
def prepopulate_tempfile(selected_category, title = 'Title Placeholder')
|
103
|
+
@tempfile = Tempfile.new('til.md')
|
104
|
+
@tempfile.write("# #{title}")
|
105
|
+
@tempfile.write("\n" * 2)
|
106
|
+
@tempfile.write("What did you learn about #{selected_category} today")
|
107
|
+
@tempfile.close
|
108
|
+
end
|
109
|
+
|
110
|
+
def open_editor
|
111
|
+
editor = ENV['VISUAL'] || ENV['EDITOR']
|
112
|
+
system(*editor.split, @tempfile.path)
|
113
|
+
end
|
114
|
+
|
115
|
+
def read_file
|
116
|
+
content = File.read(@tempfile)
|
117
|
+
@tempfile.unlink
|
118
|
+
content
|
119
|
+
end
|
120
|
+
|
121
|
+
def commit_new_til(category, content)
|
122
|
+
commit_title = content.lines[0].chomp
|
123
|
+
if commit_title.start_with?('#')
|
124
|
+
commit_title = commit_title[1..].strip
|
125
|
+
end
|
126
|
+
today = Time.now.strftime '%Y-%m-%d'
|
127
|
+
name = commit_title.split.map(&:downcase).join('-')
|
128
|
+
filename = "#{today}_#{name}.md"
|
129
|
+
|
130
|
+
ref = github_client.ref @repo_name, 'heads/master'
|
131
|
+
commit = github_client.commit @repo_name, ref.object.sha
|
132
|
+
tree = github_client.tree @repo_name, commit.commit.tree.sha, recursive: true
|
133
|
+
readme = github_client.readme @repo_name
|
134
|
+
readme_content = Base64.decode64 readme.content
|
135
|
+
|
136
|
+
blob = github_client.create_blob @repo_name, content
|
137
|
+
blobs = tree.tree.filter { |object|
|
138
|
+
object[:type] == 'blob' && object[:path] != 'README.md'
|
139
|
+
}.map { |object|
|
140
|
+
object.to_h.slice(:path, :mode, :type, :sha)
|
141
|
+
}
|
142
|
+
|
143
|
+
updated_readme_content = update_readme_content(category, commit_title, filename, readme_content)
|
144
|
+
new_readme_blob = github_client.create_blob @repo_name, updated_readme_content
|
145
|
+
blobs << { path: 'README.md', mode: '100644', type: 'blob', sha: new_readme_blob }
|
146
|
+
|
147
|
+
blobs << { path: "#{category}/#{filename}", mode: '100644', type: 'blob', sha: blob }
|
148
|
+
|
149
|
+
tree = github_client.create_tree @repo_name, blobs
|
150
|
+
commit = github_client.create_commit @repo_name, commit_title, tree.sha, ref.object.sha
|
151
|
+
github_client.update_ref @repo_name, 'heads/master', commit.sha
|
152
|
+
|
153
|
+
puts "You can see your new TIL at : https://github.com/pjambet/til/blob/master/#{category}/#{filename}"
|
154
|
+
puts "You can edit your new TIL at : https://github.com/pjambet/til/edit/master/#{category}/#{filename}"
|
155
|
+
end
|
156
|
+
|
157
|
+
def update_readme_content(category, commit_title, filename, readme_content)
|
158
|
+
beginning = readme_content.index('### Categories') + '### Categories'.length
|
159
|
+
eend = readme_content.index('---', readme_content.index('---') + 1) - 1
|
160
|
+
|
161
|
+
# [["[Git](#git)", "Git", "git"], ["[Qux](#qux)", "Qux", "qux"]]
|
162
|
+
categories = readme_content[beginning..eend].scan(/(\[(\w+)\]\(#(\w+)\))/)
|
163
|
+
|
164
|
+
if @new_category
|
165
|
+
else
|
166
|
+
existing_cat = categories.find { |c| c[2] == category }
|
167
|
+
|
168
|
+
loc_in_page = readme_content.index("### #{existing_cat[1]}")
|
169
|
+
next_cat_location = readme_content.index('###', loc_in_page + 1)
|
170
|
+
|
171
|
+
new_line = "- [#{commit_title}](#{category}/#{filename})"
|
172
|
+
new_readme_content = ''
|
173
|
+
if next_cat_location
|
174
|
+
breakpoint = next_cat_location - 2
|
175
|
+
new_readme_content = readme_content[0..breakpoint] + new_line + readme_content[breakpoint..]
|
176
|
+
else
|
177
|
+
new_readme_content = readme_content + new_line + '\n'
|
178
|
+
end
|
179
|
+
new_readme_content
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
183
|
+
end
|
184
|
+
end
|
metadata
ADDED
@@ -0,0 +1,77 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: til-rb
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.2
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Pierre Jambet
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2020-06-24 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: octokit
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '4.0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '4.0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: mocha
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 1.11.2
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 1.11.2
|
41
|
+
description: til-rb helps you manage a repo of TILs similar to https://github.com/jbranchaud/til
|
42
|
+
email: hello@pjam.me
|
43
|
+
executables:
|
44
|
+
- til
|
45
|
+
extensions: []
|
46
|
+
extra_rdoc_files: []
|
47
|
+
files:
|
48
|
+
- LICENSE
|
49
|
+
- README.md
|
50
|
+
- bin/til
|
51
|
+
- lib/til-rb.rb
|
52
|
+
- lib/til/core.rb
|
53
|
+
- lib/til/version.rb
|
54
|
+
homepage: https://rubygems.org/gems/til-rb
|
55
|
+
licenses:
|
56
|
+
- MIT
|
57
|
+
metadata: {}
|
58
|
+
post_install_message:
|
59
|
+
rdoc_options: []
|
60
|
+
require_paths:
|
61
|
+
- lib
|
62
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
63
|
+
requirements:
|
64
|
+
- - ">="
|
65
|
+
- !ruby/object:Gem::Version
|
66
|
+
version: '0'
|
67
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
68
|
+
requirements:
|
69
|
+
- - ">="
|
70
|
+
- !ruby/object:Gem::Version
|
71
|
+
version: '0'
|
72
|
+
requirements: []
|
73
|
+
rubygems_version: 3.1.2
|
74
|
+
signing_key:
|
75
|
+
specification_version: 4
|
76
|
+
summary: A utility to manage a repo of TILs
|
77
|
+
test_files: []
|