noteman 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: e598f1a385a1bd21e540785be4bc5475a822c1fb
4
- data.tar.gz: 7cd126062f9066f2e331f012a661977add8d4d00
3
+ metadata.gz: 4740138c89902d9e1644021bce170a30b7a05bc3
4
+ data.tar.gz: 76bca57c449938f0f842b3f64692882da566811f
5
5
  SHA512:
6
- metadata.gz: 74a734a10396b3a61e4ebd9920c16552ab48a9677ccae927d3da5bd5abc39c0fe1193f57180d20464df32aeaea61b4a1ae8493810f200171b5c741ea19f383fc
7
- data.tar.gz: 26643fb89305db7cb9764d5271d57a725edb33ed47695516ea38ff43cb977fed1087a560e4f782b1fcacc7477b4bb8d9e6df638d5e8230193a61bbbb09859326
6
+ metadata.gz: 0fea16ee9eea6f44f26ad6a1ef8d9fa83e108ffabe280778bc26962f2eb7bb644e0da60d1794a2370b56120751e199fb990e1dc39af9dadb602794bc1be327af
7
+ data.tar.gz: 7955327d04b70d7ff0020607ab2b60bd9035ae3dc8a4f7018b13d6ec233fb9348a470de7e9fe06133af6bf214271b4a128e1d692134e7ee80623bd901645b528
data/README.md CHANGED
@@ -3,10 +3,87 @@ Noteman
3
3
 
4
4
  You advanced note manager.
5
5
 
6
- Still in development.
6
+ Still in development. More features are coming.
7
+
8
+ ## Contents
9
+
10
+ - [What and why](#what-and-why)
11
+ - [Installation](#installation)
12
+ - [Configuration](#configuration)
13
+ - [Usage](#usage)
14
+
15
+ ## What and why
16
+
17
+ `noteman` is a convenient CLI for managing your plain text notes. It can search by content, tags, keywords and whatever wired stuff you can think of by extending it. There are plenty of great GUI tools to do this. E.g. [nvAlt](http://brettterpstra.com/projects/nvalt/), [Ulysses](http://www.ulyssesapp.com). The motivation behind this project is to simplify the note management process into a couple of simple command lines, and at the same time, make it possible to be crafted into a power tool if you wanted by the extensiblility it provides.
18
+
19
+ ## Installation
20
+
21
+ Installing `noteman` is straightforward.
22
+
23
+ ```bash
24
+ gem install noteman
25
+ ```
26
+
27
+ ## Configuration
28
+
29
+ The first time you run `noteman` by invoking the command `note` will generate the config file with default values. Which looks like this.
30
+
31
+ ``` yaml
32
+ ---
33
+ notes_in: "~/notes"
34
+ view_with: marked 2
35
+ capture_to: capture.md
36
+ ends_with: md
37
+ home: "~/.noteman"
38
+ ```
39
+
40
+ The config file is stored in "~/.notemanrc".
41
+
42
+ ## Usage
43
+
44
+ You can always invoke `note help` to see a list commands. But here I will describe the basic functions that current version provides.
45
+
46
+ ### Capture notes
47
+
48
+ Capturing notes is as simple as:
49
+
50
+ ```bash
51
+ note new
52
+ ```
53
+
54
+ This command will open your default text editor (set in environment variable). Jot down your note, save and quit. The note will be appended onto file defined in the config `capture_to`.
55
+
56
+ You also can quickly jot down a one line note without opening a text editor. E.g.
57
+
58
+ ```bash
59
+ note new buy milk
60
+ ```
61
+
62
+ If you want to save an URL link with the text. Use `-l` or `--link` option.
63
+ ```bash
64
+ note new watch this video -l http://www.youtube.com
65
+ ```
66
+ This will create a markdown style link.
67
+
68
+ To view what you have captured, use this command to open the inbox.
69
+
70
+ ```bash
71
+ note inbox
72
+ ```
73
+ This command will open your `capture.md` file with the app configured in the config file. By default it is [Marked 2](http://marked2app.com/).
74
+
75
+ ### Find your notes
76
+
77
+ Searching for notes is quick and fun.
78
+
79
+ ```bash
80
+ note find
81
+ ```
82
+ This command will bring up a search bar, and a result window (don't worry, it's still CLI). Just put down your keywords, there will be a list of results displayed instantly. Navigate through them with arrow keys(up and down). Select one with `Enter` will open the file. Or press `Esc` to quit.
7
83
 
8
84
  ## Get started with the code
9
85
 
10
86
  ```bash
11
87
  bundle install
12
88
  ```
89
+
data/bin/note CHANGED
@@ -29,18 +29,20 @@ command :find do |c|
29
29
  tags = []
30
30
  keywords = []
31
31
  args.each do |arg|
32
- if arg.start_with? '@'
33
- tags << arg.tr('@', '')
34
- else
35
- keywords << arg
36
- end
32
+ if arg.start_with? '@'
33
+ tags << arg.tr('@', '')
34
+ else
35
+ keywords << arg
36
+ end
37
37
  end
38
38
  nm.by_tags tags
39
39
  nm.by_keywords keywords
40
40
  nm.result.each { |n| puts n.file }
41
41
  else
42
42
  note = Noteman::Finder.new.find_note
43
- note.view
43
+ if note
44
+ note.view
45
+ end
44
46
  end
45
47
  end
46
48
  end
@@ -77,4 +79,11 @@ command :new do |c|
77
79
  end
78
80
  end
79
81
 
82
+ desc 'Show the inbox.'
83
+ command :inbox do |c|
84
+ c.action do |global_options,options,args|
85
+ Noteman::NoteManager.search.inbox.view
86
+ end
87
+ end
88
+
80
89
  exit run(ARGV)
@@ -1,7 +1,12 @@
1
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'
2
+
3
+ Gem.find_files("noteman/**/*.rb").each do |f|
4
+ require f
5
+ end
6
+
7
+ Dir["#{Dir.home}/.noteman/plugins/*.rb"].each do |f|
8
+ require f
9
+ end
10
+
11
+ module Noteman
12
+ end
@@ -2,51 +2,38 @@ require 'deep_merge'
2
2
 
3
3
  module Noteman
4
4
  module Config
5
-
6
- CONFIG_NAME = ".notemanrc"
7
-
5
+ NOTEMAN_CONFIG = File.join(Dir.home, '.notemanrc')
8
6
  attr_reader :config
9
7
 
10
8
  def config
11
9
  if not defined? @config
12
10
  @config = read_from_file
13
- @config['notes_in'] ||= "~/io"
11
+ @config['notes_in'] ||= "~/notes"
14
12
  @config['view_with'] ||= "Marked 2"
15
13
  @config['capture_to'] ||= "capture.md"
16
14
  @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
- }
15
+ @config['home'] ||= "~/.noteman"
16
+ # @config['state_file'] ||= "state.json"
17
+ # @config['dropbox_path'] ||= "/notes"
18
+ # @config['fomula'] ||= {}
19
+ # @config['fomula']['cheatsheets'] ||= {
20
+ # 'tags' => 'cheatsheet'
21
+ # }
22
+ # @config['fomula']['drafts'] ||= {
23
+ # 'tags' => 'draft post',
24
+ # 'tags_bool' => 'AND'
25
+ # }
25
26
 
26
- File.open(home_config, 'w') { |yf| YAML::dump(config, yf) }
27
+ File.open(NOTEMAN_CONFIG, 'w') { |yf| YAML::dump(config, yf) }
28
+ FileUtils.mkdir_p @config['home']
27
29
  end
28
30
  @config
29
31
  end
30
32
 
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
33
  def read_from_file
40
34
  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)
35
+ if c.empty? && File.exists?(NOTEMAN_CONFIG)
36
+ c = YAML.load_file(NOTEMAN_CONFIG)
50
37
  end
51
38
  c
52
39
  end
@@ -0,0 +1,39 @@
1
+ require 'dropbox_sdk'
2
+ require 'fileutils'
3
+ require 'pp'
4
+
5
+ module Noteman
6
+ module Dropbox
7
+ include Config
8
+ APP_KEY = ''
9
+ APP_SECRET = ''
10
+
11
+ def sync
12
+ state = load_state
13
+ # auth
14
+ if not state['access_token']
15
+ web_auth = DropboxOAuth2FlowNoRedirect.new(APP_KEY, APP_SECRET)
16
+ authorize_url = web_auth.start()
17
+ puts "1. Go to: #{authorize_url}"
18
+ puts "2. Click \"Allow\" (you might have to log in first)."
19
+ puts "3. Copy the authorization code."
20
+
21
+ print "Enter the authorization code here: "
22
+ STDOUT.flush
23
+ auth_code = STDIN.gets.strip
24
+
25
+ access_token, user_id = web_auth.finish(auth_code)
26
+ puts "Link successful."
27
+ state['access_token'] = access_token
28
+ end
29
+
30
+ cursor = state['cursor']
31
+ access_token = state['access_token']
32
+ c = DropboxClient.new(access_token)
33
+ result = c.delta cursor, config['dropbox_path']
34
+ pp result
35
+ #save_state state
36
+ end
37
+
38
+ end
39
+ end
@@ -1,109 +1,113 @@
1
1
  require 'curses'
2
2
 
3
3
  module Noteman
4
- class Finder
5
- include Curses
4
+ class Finder
5
+ include Curses
6
6
 
7
- def initialize
8
- @opend = false
9
- end
7
+ def initialize
8
+ @opend = false
9
+ end
10
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
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
22
 
23
- @result_box = Window.new(30, cols, 3 ,0)
24
- draw_result_box
23
+ @result_box = Window.new(30, cols, 3 ,0)
24
+ draw_result_box
25
25
 
26
- @message_box = Window.new(3, cols, 40 ,0)
27
- draw_message_box
26
+ @message_box = Window.new(3, cols, 40 ,0)
27
+ draw_message_box
28
28
 
29
- @opened = true
30
- self
31
- end
29
+ @opened = true
30
+ self
31
+ end
32
32
 
33
- def close
34
- @opened = false
35
- close_screen
36
- end
33
+ def close
34
+ @opened = false
35
+ close_screen
36
+ end
37
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
38
+ def find_note
39
+ begin
40
+ open
41
+ text = ''
42
+ selected = 0
43
+ notes = []
44
+ while true
45
+ ch = @search_box.getch
46
+ #draw_message_box "#{ch}"
47
+ case ch
48
+ when KEY_RESIZE
49
+ next
50
+ when 10 # enter
51
+ break
52
+ when 27 # esc
53
+ return
54
+ when 127 # backspace
55
+ if text.length > 0
56
+ text = text.slice(0, text.length - 1)
57
+ end
58
+ when KEY_UP #arrow up
59
+ #selected -= 1
60
+ selected == 0 ? selected = notes.length - 1 : selected -= 1
61
+ when KEY_DOWN #arrow down
62
+ selected == notes.length - 1 ? selected = 0 : selected += 1
63
+ else
64
+ if ch.is_a? String
65
+ text += ch
66
+ end
67
+ end
68
+ draw_search_box text
69
+ tags = []
70
+ keywords = []
71
+ text.split.each do |t|
72
+ if t.start_with? '@' and t.length > 1
73
+ tags << t.tr('@', '')
74
+ else
75
+ keywords << t
76
+ end
77
+ end
78
+ notes = NoteManager.search.by_tags(tags).by_keywords(keywords).result
79
+ draw_result_box notes, selected
80
+ end
81
+ notes[selected]
82
+ ensure
83
+ close
84
+ end
85
+ end
83
86
 
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
87
+ def draw_search_box(text='')
88
+ @search_box.clear
89
+ @search_box.box(' ', ' ')
90
+ @search_box.setpos(1, 1)
91
+ @search_box.attrset(A_BOLD)
92
+ @search_box.addstr text
93
+ @search_box.refresh
94
+ end
91
95
 
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
96
+ def draw_result_box(results=[], selected_index=0)
97
+ @result_box.clear
98
+ results.each_with_index do |n, i|
99
+ @result_box.setpos(i+1, 1)
100
+ @result_box.attrset(i == selected_index ? A_STANDOUT : A_NORMAL)
101
+ @result_box.addstr "#{n.file}"
102
+ end
103
+ @result_box.refresh
104
+ end
101
105
 
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
106
+ def draw_message_box(text='')
107
+ @message_box.clear
108
+ @message_box.setpos(1, 1)
109
+ @message_box.addstr "#{text}"
110
+ @message_box.refresh
111
+ end
112
+ end
109
113
  end
@@ -1,39 +1,39 @@
1
1
  module Noteman
2
- class Note
3
- include MDProcessor, Config
4
- attr_accessor :content, :metadata, :tags, :body, :file
2
+ class Note
3
+ include MDProcessor, Config
4
+ attr_accessor :content, :metadata, :tags, :body, :file
5
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
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
12
 
13
13
  def tags
14
14
  @tags = []
15
- if metadata and metadata['tags']
15
+ if metadata and metadata['tags']
16
16
  @tags = metadata['tags']
17
17
  end
18
18
  @tags
19
19
  end
20
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
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
29
 
30
- def contains?(keywords)
31
- keywords.all? { |word| body.downcase.include? word.downcase }
32
- end
30
+ def contains?(keywords)
31
+ keywords.all? { |word| body.downcase.include? word.downcase }
32
+ end
33
33
 
34
34
  def view
35
- system("open -a \"#{config['view_with']}\" #{file}")
35
+ system("open -a \"#{config['view_with']}\" #{file}")
36
36
  end
37
37
 
38
- end
38
+ end
39
39
  end
@@ -65,6 +65,10 @@ module Noteman
65
65
  end
66
66
  end
67
67
 
68
+ def inbox
69
+ notes.select { |n| n.file == config['capture_to'] }.first
70
+ end
71
+
68
72
  def choose(notes)
69
73
  if notes.length > 1
70
74
  notes.each_with_index do |note, i|
@@ -0,0 +1,74 @@
1
+ module Noteman
2
+ module Dropbox
3
+ include Config
4
+
5
+ def state_file
6
+ File.join File.expand_path(config['home']), config['state_file']
7
+ end
8
+
9
+ def load_state
10
+ if File.exist? state_file
11
+ state = JSON.parse(File.read(state_file), :max_nesting => false)
12
+ state['tree'] = Node.from_json_content(state['tree'])
13
+ else
14
+ state = {
15
+ 'tree' => {}
16
+ }
17
+
18
+ save_state state
19
+ end
20
+ state
21
+ end
22
+
23
+ def save_state(state)
24
+ state['tree'] = Node.to_json_content(state['tree'])
25
+ File.open(state_file,"w") do |f|
26
+ f.write(JSON.pretty_generate(state, :max_nesting => false))
27
+ end
28
+ end
29
+
30
+ # We track folder state as a tree of Node objects.
31
+ class Node
32
+ attr_accessor :path, :content
33
+ def initialize(path, content)
34
+ # The "original" page (i.e. not the lower-case path)
35
+ @path = path
36
+ # For files, content is a pair (size, modified)
37
+ # For folders, content is a hash of children Nodes, keyed by lower-case file names.
38
+ @content = content
39
+ end
40
+ def folder?()
41
+ @content.is_a? Hash
42
+ end
43
+ def to_json()
44
+ [@path, Node.to_json_content(@content)]
45
+ end
46
+ def self.from_json(jnode)
47
+ path, jcontent = jnode
48
+ Node.new(path, Node.from_json_content(jcontent))
49
+ end
50
+ def self.to_json_content(content)
51
+ if content.is_a? Hash
52
+ map_hash_values(content) { |child| child.to_json }
53
+ else
54
+ content
55
+ end
56
+ end
57
+ def self.from_json_content(jcontent)
58
+ if jcontent.is_a? Hash
59
+ map_hash_values(jcontent) { |jchild| Node.from_json jchild }
60
+ else
61
+ jcontent
62
+ end
63
+ end
64
+ end
65
+
66
+ # Run a mapping function over every value in a Hash, returning a new Hash.
67
+ def map_hash_values(h)
68
+ new = {}
69
+ h.each { |k,v| new[k] = yield v }
70
+ new
71
+ end
72
+
73
+ end
74
+ end
@@ -1,3 +1,3 @@
1
1
  module Noting
2
- VERSION = '0.1.0'
2
+ VERSION = '0.1.1'
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: noteman
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.1
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-11-12 00:00:00.000000000 Z
11
+ date: 2014-12-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -38,6 +38,48 @@ dependencies:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
40
  version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: pry
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: pry-doc
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: method_source
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
41
83
  - !ruby/object:Gem::Dependency
42
84
  name: gli
43
85
  requirement: !ruby/object:Gem::Requirement
@@ -108,6 +150,20 @@ dependencies:
108
150
  - - "~>"
109
151
  - !ruby/object:Gem::Version
110
152
  version: '1.0'
153
+ - !ruby/object:Gem::Dependency
154
+ name: dropbox-sdk
155
+ requirement: !ruby/object:Gem::Requirement
156
+ requirements:
157
+ - - "~>"
158
+ - !ruby/object:Gem::Version
159
+ version: '1.6'
160
+ type: :runtime
161
+ prerelease: false
162
+ version_requirements: !ruby/object:Gem::Requirement
163
+ requirements:
164
+ - - "~>"
165
+ - !ruby/object:Gem::Version
166
+ version: '1.6'
111
167
  description: A tool for managing your markdown notes.
112
168
  email: dawnstar.hu@gmail.com
113
169
  executables:
@@ -120,10 +176,12 @@ files:
120
176
  - lib/noteman.rb
121
177
  - lib/noteman/config.rb
122
178
  - lib/noteman/display.rb
179
+ - lib/noteman/dropbox.rb
123
180
  - lib/noteman/finder.rb
124
181
  - lib/noteman/md_processor.rb
125
182
  - lib/noteman/note.rb
126
183
  - lib/noteman/note_manager.rb
184
+ - lib/noteman/state.rb
127
185
  - lib/noteman/version.rb
128
186
  homepage: https://github.com/xiaoxinghu/noteman
129
187
  licenses: