noteman 0.0.0 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: cfef1b0d08554efc0f7bfc71f6ed9b543e7c2cbf
4
- data.tar.gz: 6fc35f393c65667903582ec4f3a6a55a6dec6481
3
+ metadata.gz: e598f1a385a1bd21e540785be4bc5475a822c1fb
4
+ data.tar.gz: 7cd126062f9066f2e331f012a661977add8d4d00
5
5
  SHA512:
6
- metadata.gz: cd280e064149e5bd7fe56a8d12a55acb8f880c31b085ff3ffb54234a64e29370ba153039038dab455c901c86d9a1482a6b3f658c950d15c466b25b76d86136df
7
- data.tar.gz: 0764f98f71f87d9c03e506cb8d40deb9ea314f133c8c3445906756697fe65184baf15fefec6e4308827c554455acd6b145454f92621a67707bbfc536aa89b500
6
+ metadata.gz: 74a734a10396b3a61e4ebd9920c16552ab48a9677ccae927d3da5bd5abc39c0fe1193f57180d20464df32aeaea61b4a1ae8493810f200171b5c741ea19f383fc
7
+ data.tar.gz: 26643fb89305db7cb9764d5271d57a725edb33ed47695516ea38ff43cb977fed1087a560e4f782b1fcacc7477b4bb8d9e6df638d5e8230193a61bbbb09859326
data/README.md ADDED
@@ -0,0 +1,12 @@
1
+ Noteman
2
+ ===
3
+
4
+ You advanced note manager.
5
+
6
+ Still in development.
7
+
8
+ ## Get started with the code
9
+
10
+ ```bash
11
+ bundle install
12
+ ```
data/bin/note CHANGED
@@ -1,7 +1,80 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
+ require 'gli'
3
4
  require 'noteman'
4
5
 
5
- inbox = Inbox.new
6
+ include GLI::App
7
+ include Noteman::Display
6
8
 
7
- inbox.hi
9
+ program_desc 'A CLI note manager.'
10
+
11
+ desc 'Do the action to all resulting notes.'
12
+ switch [:a, :all]
13
+
14
+ default_command :find
15
+
16
+ desc 'Search for notes.'
17
+ arg_name 'keywords'
18
+ command :find do |c|
19
+ c.desc 'Search by fomula.'
20
+ c.flag [:f, :fomula]
21
+
22
+ c.action do |global_options,options,args|
23
+ nm = Noteman::NoteManager.search
24
+ if options[:fomula]
25
+ nm.search_by_fomular options[:fomula].result
26
+ end
27
+
28
+ if args.length > 0
29
+ tags = []
30
+ keywords = []
31
+ args.each do |arg|
32
+ if arg.start_with? '@'
33
+ tags << arg.tr('@', '')
34
+ else
35
+ keywords << arg
36
+ end
37
+ end
38
+ nm.by_tags tags
39
+ nm.by_keywords keywords
40
+ nm.result.each { |n| puts n.file }
41
+ else
42
+ note = Noteman::Finder.new.find_note
43
+ note.view
44
+ end
45
+ end
46
+ end
47
+
48
+ desc 'List all tags.'
49
+ command :tags do |c|
50
+ c.desc 'List results one per line, to assist with shell completion.'
51
+ c.switch [:c]
52
+
53
+ c.action do |global_options,options,args|
54
+ nm = Noteman::NoteManager.search
55
+ if options[:c]
56
+ nm.tags.keys.each { |tag| puts tag }
57
+ else
58
+ output_tags nm.tags
59
+ end
60
+ end
61
+ end
62
+
63
+ desc 'Capture new note.'
64
+ arg_name 'note'
65
+ command :new do |c|
66
+ c.desc 'Insert link.'
67
+ c.flag [:l, :link]
68
+
69
+ c.action do |global_options,options,args|
70
+ nm = Noteman::NoteManager.search
71
+ if args.length > 0
72
+ nm.capture(args.join(' '), options[:link])
73
+ else
74
+ input = nm.fork_editor
75
+ nm.capture input
76
+ end
77
+ end
78
+ end
79
+
80
+ exit run(ARGV)
@@ -0,0 +1,54 @@
1
+ require 'deep_merge'
2
+
3
+ module Noteman
4
+ module Config
5
+
6
+ CONFIG_NAME = ".notemanrc"
7
+
8
+ attr_reader :config
9
+
10
+ def config
11
+ if not defined? @config
12
+ @config = read_from_file
13
+ @config['notes_in'] ||= "~/io"
14
+ @config['view_with'] ||= "Marked 2"
15
+ @config['capture_to'] ||= "capture.md"
16
+ @config['ends_with'] ||= "md"
17
+ @config['fomula'] ||= {}
18
+ @config['fomula']['cheatsheets'] ||= {
19
+ 'tags' => 'cheatsheet'
20
+ }
21
+ @config['fomula']['drafts'] ||= {
22
+ 'tags' => 'draft post',
23
+ 'tags_bool' => 'AND'
24
+ }
25
+
26
+ File.open(home_config, 'w') { |yf| YAML::dump(config, yf) }
27
+ end
28
+ @config
29
+ end
30
+
31
+ def home_config
32
+ if Dir.respond_to?('home')
33
+ File.join(Dir.home, CONFIG_NAME)
34
+ else
35
+ File.join(File.expand_path("~"), CONFIG_NAME)
36
+ end
37
+ end
38
+
39
+ def read_from_file
40
+ c = {}
41
+ dir = Dir.pwd
42
+ while(dir != '/')
43
+ if File.exists? File.join(dir, CONFIG_NAME)
44
+ c = YAML.load_file(File.join(dir, CONFIG_NAME)).deep_merge!(c)
45
+ end
46
+ dir = File.dirname(dir)
47
+ end
48
+ if c.empty? && File.exists?(home_config)
49
+ c = YAML.load_file(home_config)
50
+ end
51
+ c
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,11 @@
1
+ module Noteman
2
+ module Display
3
+ include Config
4
+
5
+ def output_tags(tags)
6
+ tags.keys.each do |tag|
7
+ puts "#{tag} (#{tags[tag]})"
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,109 @@
1
+ require 'curses'
2
+
3
+ module Noteman
4
+ class Finder
5
+ include Curses
6
+
7
+ def initialize
8
+ @opend = false
9
+ end
10
+
11
+ def open
12
+ if @opened
13
+ return self
14
+ end
15
+ init_screen
16
+ cbreak
17
+ noecho
18
+ raw
19
+ @search_box = Window.new(3, cols, 0 ,0)
20
+ @search_box.keypad = true
21
+ draw_search_box
22
+
23
+ @result_box = Window.new(30, cols, 3 ,0)
24
+ draw_result_box
25
+
26
+ @message_box = Window.new(3, cols, 40 ,0)
27
+ draw_message_box
28
+
29
+ @opened = true
30
+ self
31
+ end
32
+
33
+ def close
34
+ @opened = false
35
+ close_screen
36
+ end
37
+
38
+ def find_note
39
+ begin
40
+ open
41
+ text = ''
42
+ selected = 0
43
+ notes = []
44
+ while true
45
+ ch = @search_box.getch
46
+ case ch
47
+ when KEY_RESIZE
48
+ next
49
+ when 10 # enter
50
+ break
51
+ when 127 # backspace
52
+ if text.length > 0
53
+ text = text.slice(0, text.length - 1)
54
+ end
55
+ when KEY_UP #arrow up
56
+ #selected -= 1
57
+ selected == 0 ? selected = notes.length - 1 : selected -= 1
58
+ when KEY_DOWN #arrow down
59
+ selected == notes.length - 1 ? selected = 0 : selected += 1
60
+ else
61
+ if ch.is_a? String
62
+ text += ch
63
+ end
64
+ end
65
+ draw_search_box text
66
+ tags = []
67
+ keywords = []
68
+ text.split.each do |t|
69
+ if t.start_with? '@' and t.length > 1
70
+ tags << t.tr('@', '')
71
+ else
72
+ keywords << t
73
+ end
74
+ end
75
+ notes = NoteManager.search.by_tags(tags).by_keywords(keywords).result
76
+ draw_result_box notes, selected
77
+ end
78
+ notes[selected]
79
+ ensure
80
+ close
81
+ end
82
+ end
83
+
84
+ def draw_search_box(text='')
85
+ @search_box.clear
86
+ @search_box.box('|', '-')
87
+ @search_box.setpos(1, 1)
88
+ @search_box.addstr text
89
+ @search_box.refresh
90
+ end
91
+
92
+ def draw_result_box(results=[], selected_index=0)
93
+ @result_box.clear
94
+ results.each_with_index do |n, i|
95
+ @result_box.setpos(i+1, 1)
96
+ @result_box.attrset(i == selected_index ? A_STANDOUT : A_NORMAL)
97
+ @result_box.addstr "#{n.file}"
98
+ end
99
+ @result_box.refresh
100
+ end
101
+
102
+ def draw_message_box(text='')
103
+ @message_box.clear
104
+ @message_box.setpos(1, 1)
105
+ @message_box.addstr "#{text}"
106
+ @message_box.refresh
107
+ end
108
+ end
109
+ end
@@ -0,0 +1,41 @@
1
+ require 'redcarpet'
2
+ module Noteman
3
+ module MDProcessor
4
+ class StackRenderer < Redcarpet::Render::Base
5
+ attr_reader :items
6
+
7
+ def initialize
8
+ super
9
+ @items = []
10
+ end
11
+
12
+ def header(title, level)
13
+ items << { :text => title, :level => level, :type => :header }
14
+ "#{'#' * level} #{title}\n\n"
15
+ end
16
+
17
+ def paragraph(text)
18
+ items << { :text => text, :type => :paragraph }
19
+ "#{text}\n\n"
20
+ end
21
+
22
+ end
23
+
24
+ def get_metadata(text)
25
+ text =~ /^(---\s*\n.*?\n?)^(---\s*$\n?)/m
26
+ meta = YAML.load($1) if $1
27
+ end
28
+
29
+ def remove_metadata(text)
30
+ text.sub /^(---\s*\n.*?\n?)^(---\s*$\n?)/m, ''
31
+ end
32
+
33
+ def get_md(text)
34
+ sr = StackRenderer.new
35
+ md = Redcarpet::Markdown.new(sr)
36
+
37
+ md.render(remove_metadata text)
38
+ sr.items
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,39 @@
1
+ module Noteman
2
+ class Note
3
+ include MDProcessor, Config
4
+ attr_accessor :content, :metadata, :tags, :body, :file
5
+
6
+ def initialize(file)
7
+ @file = file
8
+ @content = File.read file
9
+ @metadata = get_metadata @content
10
+ @body = remove_metadata @content
11
+ end
12
+
13
+ def tags
14
+ @tags = []
15
+ if metadata and metadata['tags']
16
+ @tags = metadata['tags']
17
+ end
18
+ @tags
19
+ end
20
+
21
+ def with_tags?(tags)
22
+ if metadata and metadata['tags']
23
+ if (tags - metadata['tags']).empty?
24
+ return true
25
+ end
26
+ end
27
+ false
28
+ end
29
+
30
+ def contains?(keywords)
31
+ keywords.all? { |word| body.downcase.include? word.downcase }
32
+ end
33
+
34
+ def view
35
+ system("open -a \"#{config['view_with']}\" #{file}")
36
+ end
37
+
38
+ end
39
+ end
@@ -0,0 +1,133 @@
1
+ module Noteman
2
+ class NoteManager
3
+ include Config
4
+ attr_accessor :notes, :result, :tags
5
+
6
+ def initialize
7
+ @notes = []
8
+ Dir.chdir(File.expand_path(config['notes_in']))
9
+ Dir.glob("*.#{config['ends_with']}").each do |file|
10
+ @notes << Note.new(file)
11
+ end
12
+ end
13
+
14
+ def self.search
15
+ @@manager = NoteManager.new unless defined? @@manager
16
+ @@manager.reset_filter
17
+ end
18
+
19
+ def reset_filter
20
+ @result = []
21
+ @result += @notes
22
+ self
23
+ end
24
+
25
+ def by_tags(tags)
26
+ if tags && tags.length > 0
27
+ @result.delete_if { |note| not note.with_tags? tags }
28
+ end
29
+ self
30
+ end
31
+
32
+ def by_keywords(keywords)
33
+ if keywords && keywords.length > 0
34
+ @result.delete_if { |note| not note.contains? keywords }
35
+ end
36
+ self
37
+ end
38
+
39
+ def search_by_fomular(name)
40
+ fomular = config['fomular'][name]
41
+ if fomular
42
+ search
43
+ tags = fomular['tags'].split(' ')
44
+ keywords = fomular['keywords'].split(' ')
45
+ if tags
46
+ by_tags tags
47
+ end
48
+ if keywords
49
+ by_keywords keywords
50
+ end
51
+ else
52
+ puts "No such fomular defined #{name}."
53
+ end
54
+ self
55
+ end
56
+
57
+ def capture(input, link=nil)
58
+ if link
59
+ content = "[#{input}](#{link})"
60
+ else
61
+ content = input
62
+ end
63
+ open(config['capture_to'], 'a') do |f|
64
+ f << "#{content}\n"
65
+ end
66
+ end
67
+
68
+ def choose(notes)
69
+ if notes.length > 1
70
+ notes.each_with_index do |note, i|
71
+ puts "% 3d: %s" % [i, note.file]
72
+ end
73
+ print "> "
74
+ num = STDIN.gets
75
+ return false if num =~ /^[a-z ]*$/i
76
+ chosen = notes[num.to_i]
77
+ elsif notes.length == 1
78
+ chosen = notes[0]
79
+ else
80
+ chosen = false
81
+ end
82
+ chosen
83
+ end
84
+
85
+ def tags
86
+ if not defined? @tags
87
+ @tags = {}
88
+ notes.each do |note|
89
+ note.tags.each do |tag|
90
+ if not @tags.has_key? tag
91
+ @tags[tag] = 1
92
+ else
93
+ @tags[tag] += 1
94
+ end
95
+ end
96
+ end
97
+ end
98
+ @tags
99
+ end
100
+
101
+ def fork_editor(input="")
102
+ tmpfile = Tempfile.new('note')
103
+
104
+ File.open(tmpfile.path,'w+') do |f|
105
+ f.puts input
106
+ end
107
+
108
+ pid = Process.fork { system("$EDITOR #{tmpfile.path}") }
109
+
110
+ trap("INT") {
111
+ Process.kill(9, pid) rescue Errno::ESRCH
112
+ tmpfile.unlink
113
+ tmpfile.close!
114
+ exit 0
115
+ }
116
+
117
+ Process.wait(pid)
118
+
119
+ begin
120
+ if $?.exitstatus == 0
121
+ input = IO.read(tmpfile.path)
122
+ else
123
+ raise "Cancelled"
124
+ end
125
+ ensure
126
+ tmpfile.close
127
+ tmpfile.unlink
128
+ end
129
+
130
+ input
131
+ end
132
+ end
133
+ end
@@ -1,3 +1,3 @@
1
1
  module Noting
2
- VERSION = '0.0.0'
2
+ VERSION = '0.1.0'
3
3
  end
data/lib/noteman.rb CHANGED
@@ -1,4 +1,7 @@
1
- require 'noteman/version.rb'
2
- require 'noteman/inbox.rb'
3
-
4
- NOTING_CONFIG_NAME = ".notemanrc"
1
+ require 'tempfile'
2
+ require 'noteman/md_processor'
3
+ require 'noteman/config'
4
+ require 'noteman/display'
5
+ require 'noteman/finder'
6
+ require 'noteman/note'
7
+ require 'noteman/note_manager'
metadata CHANGED
@@ -1,15 +1,113 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: noteman
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.0
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Xiaoxing Hu
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-10-31 00:00:00.000000000 Z
12
- dependencies: []
11
+ date: 2014-11-12 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rake
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: aruba
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: gli
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - '='
46
+ - !ruby/object:Gem::Version
47
+ version: 2.12.2
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - '='
53
+ - !ruby/object:Gem::Version
54
+ version: 2.12.2
55
+ - !ruby/object:Gem::Dependency
56
+ name: deep_merge
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '1.0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '1.0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: redcarpet
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '3.2'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '3.2'
83
+ - !ruby/object:Gem::Dependency
84
+ name: highline
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '1.6'
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '1.6'
97
+ - !ruby/object:Gem::Dependency
98
+ name: curses
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: '1.0'
104
+ type: :runtime
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: '1.0'
13
111
  description: A tool for managing your markdown notes.
14
112
  email: dawnstar.hu@gmail.com
15
113
  executables:
@@ -17,11 +115,17 @@ executables:
17
115
  extensions: []
18
116
  extra_rdoc_files: []
19
117
  files:
118
+ - README.md
20
119
  - bin/note
21
120
  - lib/noteman.rb
22
- - lib/noteman/inbox.rb
121
+ - lib/noteman/config.rb
122
+ - lib/noteman/display.rb
123
+ - lib/noteman/finder.rb
124
+ - lib/noteman/md_processor.rb
125
+ - lib/noteman/note.rb
126
+ - lib/noteman/note_manager.rb
23
127
  - lib/noteman/version.rb
24
- homepage:
128
+ homepage: https://github.com/xiaoxinghu/noteman
25
129
  licenses:
26
130
  - MIT
27
131
  metadata: {}
@@ -41,7 +145,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
41
145
  version: '0'
42
146
  requirements: []
43
147
  rubyforge_project:
44
- rubygems_version: 2.4.1
148
+ rubygems_version: 2.4.2
45
149
  signing_key:
46
150
  specification_version: 4
47
151
  summary: You advanced note manager.
data/lib/noteman/inbox.rb DELETED
@@ -1,5 +0,0 @@
1
- class Inbox
2
- def hi
3
- puts "Hi, this is your inbox."
4
- end
5
- end