dephine 0.1.1 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -2,6 +2,12 @@
2
2
 
3
3
  Google dictionary in terminal
4
4
 
5
+ ## Requirements
6
+
7
+ * Ruby (1.9)
8
+ * libncursesw5-dev
9
+ * [mpg123](http://www.mpg123.de/) (<b>it's not required for OS X</b>)
10
+
5
11
  ## Installation
6
12
 
7
13
  $ gem install dephine
@@ -22,6 +28,14 @@ Google dictionary in terminal
22
28
  Used to indicate a range
23
29
  - he trains anything from seven to eight hours a day
24
30
 
31
+ ## Hot-keys
32
+
33
+ * Arrow keys.
34
+ * `Ctrl-n` / `j` to scroll down.
35
+ * `Ctrl-p` / `k` to scroll up.
36
+ * `p` to pronounce.
37
+ * `q` to quit.
38
+
25
39
  ## Contributing
26
40
 
27
41
  1. Fork it
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- $:.unshift File.join(File.expand_path(File.dirname(__FILE__)), %w[.. lib])
3
+ $:.unshift File.expand_path(File.join(File.dirname(__FILE__), %w[.. lib]))
4
4
  require 'dephine'
5
5
 
6
6
  Dephine::CLI.start(ARGV)
@@ -15,4 +15,6 @@ Gem::Specification.new do |gem|
15
15
  gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
16
16
  gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
17
17
  gem.require_paths = ["lib"]
18
+
19
+ gem.add_dependency 'ncursesw', '~> 1.2.4'
18
20
  end
@@ -1,3 +1,4 @@
1
1
  require 'dephine/version'
2
2
  require 'dephine/dictionary'
3
3
  require 'dephine/cli'
4
+ require 'dephine/tui'
@@ -1,39 +1,104 @@
1
+ require 'tempfile'
2
+
1
3
  module Dephine
4
+
5
+ # Public: Make a simple Command Line Interface.
6
+ # To use this class the 'start' class method should be called.
7
+ #
8
+ # Examples
9
+ #
10
+ # CLI.start(ARGV)
11
+ # # => nil
2
12
  class CLI
3
- class << self
4
- def start(args)
5
- banner = []
6
- banner << 'Dephine, Google dictionary in terminal'
7
- banner << 'Usage: dephine [word]'
8
-
9
- if args.empty?
10
- puts banner.join("\n")
11
- else
12
- define(args[0])
13
- end
13
+
14
+ # Public: Use cli arguments for running the application.
15
+ #
16
+ # Returns nothing.
17
+ def self.start(args)
18
+ banner = []
19
+ banner << 'Dephine, Google dictionary in terminal'
20
+ banner << 'Usage: dephine [word]'
21
+
22
+ if args.empty?
23
+ puts banner.join("\n")
24
+ else
25
+ define(args[0])
26
+ end
27
+ end
28
+
29
+ # Public: Cross-platform way of finding an executable in the $PATH.
30
+ #
31
+ # which('ruby') #=> /usr/bin/ruby
32
+ def self.which(cmd)
33
+ exts = ENV['PATHEXT'] ? ENV['PATHEXT'].split(';') : ['']
34
+ ENV['PATH'].split(File::PATH_SEPARATOR).each do |path|
35
+ exts.each { |ext|
36
+ exe = "#{path}/#{cmd}#{ext}"
37
+ return exe if File.executable? exe
38
+ }
39
+ end
40
+ return nil
41
+ end
42
+
43
+ # Public: Play word pronunciation.
44
+ # This method uses either mpg123 or afplay to play the audio file.
45
+ #
46
+ # audio - The String that should be path of an audio file to be played.
47
+ def self.play(audio)
48
+ player = which('mpg123') || which('afplay')
49
+ system("#{player} #{audio} 2>/dev/null")
50
+ end
51
+
52
+ # Internal: Display definitions of a word.
53
+ #
54
+ # arg - The String that will be defined.
55
+ def self.define(arg)
56
+ word = Dephine::Dictionary.new(arg)
57
+
58
+ if word.meanings.empty?
59
+ abort("Word not found in the dictionary!")
14
60
  end
15
61
 
16
- private
17
- def define(arg)
18
- word = Dephine::Dictionary.new(arg)
62
+ t = Dephine::TUI.new
63
+ t.puts arg
19
64
 
20
- if word.meanings.empty?
21
- abort("Word not found in the dictionary!")
65
+ word.meanings.each do |m|
66
+ t.puts
67
+ t.puts "#{m[:type].downcase} #{m[:phonetic]}"
68
+ m[:meanings].each do |d|
69
+ t.puts " #{d[:text]}"
70
+ d[:examples].each do |eg|
71
+ t.puts " - #{eg}"
72
+ end
73
+ t.puts
22
74
  end
75
+ end
23
76
 
24
- puts arg
25
- word.meanings.each do |m|
26
- puts
27
- puts "#{m[:type].downcase} #{m[:phonetic]}"
28
- m[:meanings].each do |d|
29
- puts " #{d[:text]}"
30
- d[:examples].each do |eg|
31
- puts " - #{eg}"
32
- end
33
- puts
77
+ if word.pronunciations.length > 0
78
+ # create tempfile
79
+ file = Tempfile.new('temp-pronunciation.mp3')
80
+
81
+ # download pronunciation mp3 and save to tempfile
82
+ File.open(file, "wb") do |saved_file|
83
+ open(word.pronunciations[0][:url], 'rb') do |read_file|
84
+ saved_file.write(read_file.read)
34
85
  end
35
86
  end
87
+ file.close()
88
+
89
+ # play tempfile
90
+ t.set_key 'p' do
91
+ play(file.path)
92
+ end
36
93
  end
94
+
95
+ t.close
96
+
97
+ end
98
+
99
+ class << self
100
+ private :define
37
101
  end
102
+
38
103
  end
39
104
  end
@@ -4,7 +4,7 @@ require 'json'
4
4
  module Dephine
5
5
  class Dictionary
6
6
  # Public: Returns the Array meanings of the word.
7
- attr_reader :meanings
7
+ attr_reader :meanings, :pronunciations
8
8
 
9
9
  # Public: Initialize some definitions of a word.
10
10
  #
@@ -13,6 +13,7 @@ module Dephine
13
13
  raise ArgumentError, "Word shouldn't be blank" if word.empty?
14
14
 
15
15
  @meanings = []
16
+ @pronunciations = []
16
17
  url = "https://www.google.com/dictionary/json?callback=define&q=#{word}&" \
17
18
  "sl=en&tl=en&restrict=pr%2Cde&client=te"
18
19
 
@@ -26,6 +27,15 @@ module Dephine
26
27
  meanings: []
27
28
  }
28
29
 
30
+ # add pronunciation
31
+ primary['terms'].each do |term|
32
+ if term['type'] == 'sound'
33
+ @pronunciations << {
34
+ url: term['text'],
35
+ }
36
+ end
37
+ end
38
+
29
39
  # add meanings
30
40
  primary['entries'][1..-1].each do |entry|
31
41
  @meanings[-1][:meanings] << {
@@ -0,0 +1,170 @@
1
+ require 'ncursesw'
2
+
3
+ module Dephine
4
+
5
+ # Public: Terminal User Interface for making a simple UI.
6
+ # All methods are instance methods and should be called on an instance.
7
+ #
8
+ # Examples
9
+ #
10
+ # t = TUI.new
11
+ # t.puts 'it uses ncurses'
12
+ # t.close
13
+ # # => 'it uses ncurses'
14
+ class TUI
15
+ # Public: Initialize a terminal user interface.
16
+ def initialize
17
+ Ncurses.initscr
18
+ Ncurses.nonl
19
+ Ncurses.cbreak
20
+ Ncurses.noecho
21
+
22
+ @screen = Ncurses.stdscr
23
+ @screen.scrollok(true)
24
+ @screen.keypad(true)
25
+
26
+ @top = 0
27
+ @contexts = []
28
+ @callbacks = {}
29
+ end
30
+
31
+ def maxy
32
+ @screen.getmaxy
33
+ end
34
+
35
+ # Public: Add a String to an Array named 'contexts'.
36
+ # This method basically doesn't act like the built-in method 'puts',
37
+ # but values of 'contexts' will be printed.
38
+ #
39
+ # text - The String that will be pushed to an Array.
40
+ #
41
+ # Returns the contexts Array.
42
+ def puts(text = '')
43
+ @contexts << text
44
+ end
45
+
46
+ # Public: Move up the scroll.
47
+ #
48
+ # Returns true or fase.
49
+ def scroll_up
50
+ if @top > 0
51
+ @screen.scrl(-1)
52
+ @top -= 1
53
+ str = @contexts[@top]
54
+
55
+ if str
56
+ @screen.move(0, 0)
57
+ @screen.addstr(str)
58
+ end
59
+
60
+ true
61
+
62
+ else
63
+ false
64
+ end
65
+ end
66
+
67
+ # Public: Move down the scroll.
68
+ #
69
+ # Returns true or false.
70
+ def scroll_down
71
+ if @top + maxy < @contexts.length
72
+ @screen.scrl(1)
73
+ @top += 1
74
+ str = @contexts[@top + maxy - 1]
75
+
76
+ if str
77
+ @screen.move(maxy - 1, 0)
78
+ @screen.addstr(str)
79
+ end
80
+
81
+ true
82
+
83
+ else
84
+ false
85
+ end
86
+ end
87
+
88
+ # Internal: Set some hot-keys for performing basic things.
89
+ # Basic things are scroll up, scroll down and quit.
90
+ #
91
+ # Returns nothing.
92
+ def hotkeys
93
+ loop do
94
+ c = @screen.getch
95
+
96
+ case c
97
+ when Ncurses::KEY_DOWN, 14, 'j'.ord
98
+ scroll_down
99
+
100
+ when Ncurses::KEY_UP, 16, 'k'.ord
101
+ scroll_up
102
+
103
+ when Ncurses::KEY_NPAGE
104
+ (maxy - 2).times do
105
+ break if !scroll_down
106
+ end
107
+
108
+ when Ncurses::KEY_PPAGE
109
+ (maxy - 2).times do
110
+ break if !scroll_up
111
+ end
112
+
113
+ when Ncurses::KEY_LEFT
114
+ while scroll_up; end
115
+
116
+ when Ncurses::KEY_RIGHT
117
+ while scroll_down; end
118
+
119
+ when 'q'.ord
120
+ break
121
+
122
+ when @callbacks[c]
123
+ true
124
+
125
+ else
126
+ @screen.move(0, 0)
127
+ @screen.addstr("[unknown key `#{Ncurses.keyname(c)}'=#{c}] ")
128
+ end
129
+
130
+ @screen.move(0, 0)
131
+ end
132
+ end
133
+
134
+ # Public: Set a hot-key for calling a block.
135
+ #
136
+ # key - The key to be set as a hot-key.
137
+ # block - The block to be called when pressing the key.
138
+ #
139
+ # Examples
140
+ #
141
+ # set_key 'q' do
142
+ # quit
143
+ # end
144
+ # # => nil
145
+ #
146
+ # Returns nothing.
147
+ def set_key(key, &block)
148
+ @callbacks[key.ord] = block
149
+ end
150
+
151
+ # Public: Close the created terminal user interface.
152
+ # This method should be called for closing the terminal user interface.
153
+ #
154
+ # Returns nothing.
155
+ def close
156
+ @contexts[0..maxy-1].each_with_index do |line, idx|
157
+ @screen.move(idx, 0)
158
+ @screen.addstr(line.to_s)
159
+ end
160
+
161
+ @screen.move(0, 0)
162
+ @screen.refresh
163
+ hotkeys
164
+ Ncurses.endwin
165
+ end
166
+
167
+ private :hotkeys
168
+
169
+ end
170
+ end
@@ -1,3 +1,3 @@
1
1
  module Dephine
2
- VERSION = "0.1.1"
2
+ VERSION = "0.2.0"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dephine
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.2.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,8 +9,24 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-01-16 00:00:00.000000000 Z
13
- dependencies: []
12
+ date: 2013-02-02 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: ncursesw
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: 1.2.4
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ version: 1.2.4
14
30
  description:
15
31
  email:
16
32
  - contact@s1n4.com
@@ -29,6 +45,7 @@ files:
29
45
  - lib/dephine.rb
30
46
  - lib/dephine/cli.rb
31
47
  - lib/dephine/dictionary.rb
48
+ - lib/dephine/tui.rb
32
49
  - lib/dephine/version.rb
33
50
  homepage: http://s1n4.com/dephine
34
51
  licenses: []
@@ -50,9 +67,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
50
67
  version: '0'
51
68
  requirements: []
52
69
  rubyforge_project:
53
- rubygems_version: 1.8.24
70
+ rubygems_version: 1.8.23
54
71
  signing_key:
55
72
  specification_version: 3
56
73
  summary: Google dictionary in terminal
57
74
  test_files: []
58
- has_rdoc: