alx 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,13 @@
1
+ module Alx
2
+
3
+ module Executer
4
+
5
+ def start( cmd )
6
+ return true if system( "#{cmd}" )
7
+ raise "Command: #{cmd} failed."
8
+ end
9
+
10
+ end
11
+
12
+ end
13
+
@@ -0,0 +1,62 @@
1
+ require 'alx/library'
2
+ require 'optparse'
3
+ require 'tempfile'
4
+
5
+ module Alx
6
+
7
+ class Handler
8
+ attr_reader :command_name
9
+
10
+ def initialize( details )
11
+ @conf = details[ :configuration ]
12
+ @command_name = details[ :command ]
13
+
14
+ @opts = OptionParser.new
15
+ banner_text = @command_name
16
+ banner_text += ' [options]' if details[ :options ]
17
+ banner_text += " <#{details[ :rest_description ]}>" if details[ :rest_description ]
18
+ banner_text += "\n #{details[ :description ]}"
19
+ add_options( details[ :options ] ) if details[ :options ]
20
+ @opts.banner = banner_text
21
+ end
22
+
23
+ def help
24
+ @opts.help
25
+ end
26
+
27
+ protected
28
+ def add_options( opts )
29
+ opts.each { | o | add_option( o ) }
30
+ end
31
+
32
+ def add_option( opt )
33
+ case opt
34
+ when :editor
35
+ @opts.on( '-e EDITOR', '--editor EDITOR', 'Use EDITOR instead of predefined editor.' ) { | editor | @conf[ :editor ] = editor }
36
+ when :stdin
37
+ @opts.on( '-i', '--stdin', 'Use stdin instead of an editor.' ) { @conf.delete( :editor ) }
38
+ when :stdout
39
+ @opts.on( '-o', '--stdout', 'Print to stdout instead of starting a viewer.' ) { @conf[ :stdout ] = true }
40
+ when :html
41
+ @opts.on( '-h', '--html', 'Generate html from the original text file.' ) { @conf[ :html ] = true }
42
+ end
43
+ end
44
+
45
+ def parse_options
46
+ @conf[ :rest ] = @opts.parse( @conf[ :rest ] ).join( ' ' )
47
+ end
48
+
49
+ def options_error( message )
50
+ puts message
51
+ puts help
52
+ raise ""
53
+ end
54
+
55
+ def load_library
56
+ @lib = Alx::Library.new
57
+ @lib.load_library( @conf[ :default_shelf_dir ] )
58
+ end
59
+ end
60
+
61
+ end
62
+
@@ -0,0 +1,39 @@
1
+ require 'alx/handler'
2
+
3
+ module Alx
4
+
5
+ class HelpHandler < Handler
6
+ def initialize( configuration, controller )
7
+ super(
8
+ :configuration => configuration,
9
+ :command => 'help',
10
+ :rest_description => 'command',
11
+ :description => "Gives more information on defined command." )
12
+ @controller = controller
13
+ end
14
+
15
+ def handle
16
+ parse_options
17
+ handler = @controller.handlers[ @conf[ :rest ] ]
18
+ if handler
19
+ puts handler.help
20
+ return;
21
+ end
22
+
23
+ default_help
24
+ end
25
+
26
+ private
27
+ def default_help
28
+ executable_name = File.basename( $PROGRAM_NAME )
29
+ text = "Usage: #{executable_name} command [options]\n"
30
+ text += "An easy to use text document manager.\n\n"
31
+ text += "Commands:\n"
32
+ @controller.handlers.keys.each { | command | text+=" " + command + "\n" }
33
+ text += "\nFor more information type: #{executable_name} help <command>"
34
+ puts text
35
+ end
36
+ end
37
+
38
+ end
39
+
@@ -0,0 +1,27 @@
1
+ require 'alx/book'
2
+
3
+ module Alx
4
+
5
+ class Library
6
+ def initialize
7
+ @books = []
8
+ end
9
+
10
+ def load_library( directory )
11
+ Dir.open( directory ) do | dir |
12
+ files = dir.entries.keep_if { | i | i !~ /^\./ }
13
+ files.each do | file |
14
+ @books << Book.new( file.gsub( /_/, " " ), "#{directory}/#{file}" )
15
+ end
16
+ end
17
+ self
18
+ end
19
+
20
+ def list( pattern )
21
+ @books.select { | book | book.title=~/#{pattern}/ }
22
+ end
23
+
24
+ end
25
+
26
+ end
27
+
@@ -0,0 +1,22 @@
1
+ require 'alx/handler'
2
+
3
+ module Alx
4
+
5
+ class ListHandler < Handler
6
+ def initialize( configuration )
7
+ super(
8
+ :configuration => configuration,
9
+ :command => 'list',
10
+ :rest_description => 'pattern',
11
+ :description => "Lists matching books in the library. Lists all if there's no pattern given." )
12
+ end
13
+
14
+ def handle
15
+ parse_options
16
+ load_library.list( @conf[ :rest ] ).each { | book | puts book.title }
17
+ end
18
+
19
+ end
20
+
21
+ end
22
+
@@ -0,0 +1,36 @@
1
+ require 'alx/handler'
2
+
3
+ module Alx
4
+
5
+ class RemoveHandler < Handler
6
+ def initialize( configuration )
7
+ super(
8
+ :configuration => configuration,
9
+ :command => 'remove',
10
+ :rest_description => 'pattern',
11
+ :description => "Removes matching books from the library." )
12
+ end
13
+
14
+ def handle
15
+ parse_options
16
+ options_error( "No pattern given. Please provide one." ) if @conf[ :rest ].empty?
17
+ matching_books = load_library.list( @conf[ :rest ] )
18
+ return remove_book( matching_books.pop ) if matching_books.size == 1
19
+ matching_books.each { | book | remove_book( book ) if ask?( "Do you really want to remove #{book.title}?" ) }
20
+ end
21
+
22
+ private
23
+ def ask?( message )
24
+ printf message + " (yes/no) "
25
+ answer = $stdin.gets.chomp
26
+ return answer == "yes"
27
+ end
28
+
29
+ def remove_book( book )
30
+ puts "Removing #{book.title}. A backup is saved to /tmp just in case."
31
+ FileUtils.mv( book.file_name, "/tmp" )
32
+ end
33
+ end
34
+
35
+ end
36
+
@@ -0,0 +1,39 @@
1
+ require 'redcarpet'
2
+
3
+ module Alx
4
+
5
+ class Renderer
6
+ def initialize( conf )
7
+ @conf = conf
8
+ end
9
+
10
+ def render_to_file( book, destination = nil )
11
+ on_file( destination ) { | file | file.puts( render( book ) ) }
12
+ end
13
+
14
+ def render( book )
15
+ if @conf[ :html ]
16
+ markdown = Redcarpet::Markdown.new( Redcarpet::Render::HTML.new, :fenced_code_blocks => true, :tables => true )
17
+ return markdown.render( book.content )
18
+ end
19
+ book.content
20
+ end
21
+
22
+ private
23
+ def on_file( destination )
24
+ file_name = destination ? destination : temp_file
25
+ File.open( file_name, "w" ) do | file |
26
+ yield file
27
+ end
28
+ file_name
29
+ end
30
+
31
+ def temp_file
32
+ extension = @conf[ :html ] ? ".html" : ".md"
33
+ file_name = "/tmp/" + Time.now.to_i.to_s + extension
34
+ end
35
+
36
+ end
37
+
38
+ end
39
+
@@ -0,0 +1,32 @@
1
+ require 'alx/handler'
2
+ require 'alx/renderer'
3
+ require 'alx/viewer'
4
+
5
+ module Alx
6
+
7
+ class ShowHandler < Handler
8
+ def initialize( configuration )
9
+ super(
10
+ :configuration => configuration,
11
+ :command => 'show',
12
+ :rest_description => 'pattern',
13
+ :description => "Shows book matching the given pattern.",
14
+ :options => [ :html, :stdout ] )
15
+ end
16
+
17
+ def handle
18
+ parse_options
19
+ options_error( "No pattern given. Please provide one." ) if @conf[ :rest ].empty?
20
+ load_library.list( @conf[ :rest ] ).each { | book | show_book( book ) }
21
+ end
22
+
23
+ private
24
+ def show_book( book )
25
+ file_name = Renderer.new( @conf ).render_to_file( book )
26
+ Viewer.new( @conf ).view( file_name )
27
+ end
28
+
29
+ end
30
+
31
+ end
32
+
@@ -0,0 +1,3 @@
1
+ module Alx
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,32 @@
1
+ module Alx
2
+
3
+ class Viewer
4
+ include Executer
5
+
6
+ def initialize( conf )
7
+ @conf = conf
8
+ end
9
+
10
+ def view( file_name )
11
+ if @conf[ :stdout ]
12
+ File.open( file_name ) do | file |
13
+ while line = file.gets
14
+ $stdout.puts line
15
+ end
16
+ end
17
+
18
+ return true
19
+ end
20
+
21
+ if @conf[ :html ]
22
+ start( @conf[ :html_viewer ] + " " + file_name )
23
+ return true
24
+ end
25
+
26
+ start( @conf[ :terminal_viewer ] + " " + file_name )
27
+ end
28
+
29
+ end
30
+
31
+ end
32
+
@@ -0,0 +1,23 @@
1
+ require_relative 'test_helper'
2
+ require 'test/unit'
3
+ require 'alx/book'
4
+ require 'stringio'
5
+
6
+ class BookTest < Test::Unit::TestCase
7
+
8
+ def setup
9
+ @text = 'something something dark\nside\n'
10
+ File.stubs( :open ).yields( StringIO.new( @text ) )
11
+ @book = Alx::Book.new( 'title', 'filename' )
12
+ end
13
+
14
+ def teardown
15
+ File.unstub( :open )
16
+ end
17
+
18
+ def test_show_content
19
+ @book.content.should == @text
20
+ end
21
+
22
+ end
23
+
@@ -0,0 +1,37 @@
1
+ require_relative 'test_helper'
2
+ require 'test/unit'
3
+ require 'alx/controller'
4
+ require 'rspec'
5
+
6
+ class ControllerTest < Test::Unit::TestCase
7
+
8
+ def setup
9
+ @testconf = {}
10
+ @controller = Alx::Controller.new( @testconf )
11
+ @handlers = @controller.handlers
12
+ end
13
+
14
+ def test_constructor_creates_handlers
15
+ @controller.handlers.should have_key( 'add' )
16
+ @controller.handlers.should have_key( 'list' )
17
+ @controller.handlers.should have_key( 'show' )
18
+ @controller.handlers.should have_key( 'remove' )
19
+ @controller.handlers.should have_key( 'help' )
20
+ end
21
+
22
+ def test_command_handler_should_be_called_if_exists
23
+ @testconf[ :command ] = 'help'
24
+ @handlers[ 'help' ] = HandlerStub.new( @testconf )
25
+ @controller.run()
26
+ @handlers[ 'help' ].handle_called.should == true
27
+ end
28
+
29
+ def test_help_handler_should_be_called_if_command_does_not_exist
30
+ @testconf[ :command ] = 'somethingsomethingdarkside'
31
+ @handlers[ 'help' ] = HandlerStub.new( @testconf )
32
+ lambda { @controller.run() }.should raise_error
33
+ @handlers[ 'help' ].handle_called.should == true
34
+ end
35
+
36
+ end
37
+
@@ -0,0 +1,42 @@
1
+ require_relative 'test_helper'
2
+ require 'test/unit'
3
+ require 'alx/editor'
4
+
5
+ class EditorTest < Test::Unit::TestCase
6
+
7
+ def setup
8
+ @conf = Hash.new
9
+ @editor = Alx::Editor.new( @conf )
10
+ @file_output = StringIO.new
11
+ File.stubs( :open ).yields( @file_output )
12
+ end
13
+
14
+ def teardown
15
+ File.unstub( :open )
16
+ end
17
+
18
+ def test_editor_error
19
+ @conf[ :editor ] = DUMMY_EXEC
20
+ lambda { @editor.edit( '/tmp/some_file' ) }.should raise_error
21
+ end
22
+
23
+ def test_editor_returns_false
24
+ @conf[ :editor ] = FALSE_EXEC
25
+ lambda { @editor.edit( '/tmp/some_file' ) }.should raise_error
26
+ end
27
+
28
+ def test_editor_success
29
+ @conf[ :editor ] = TRUE_EXEC
30
+ lambda { @editor.edit( '/tmp/some_file' ) }.should_not raise_error
31
+ end
32
+
33
+ def test_stdin
34
+ text_to_write = "some string"
35
+ stub_in_and_out( text_to_write ) do
36
+ lambda { @editor.edit( '/tmp/some_file' ) }.should_not raise_error
37
+ end.should =~ /Reading.*from.*standard.*input/
38
+ @file_output.string.chomp.should == text_to_write
39
+ end
40
+
41
+ end
42
+
@@ -0,0 +1,33 @@
1
+ require_relative 'test_helper'
2
+ require 'test/unit'
3
+ require 'alx/library'
4
+ require 'alx/book'
5
+
6
+ class LibraryTest < Test::Unit::TestCase
7
+
8
+ def setup_dir( dir )
9
+ dir.entries << "first_file"
10
+ dir.entries << "almost_first_file"
11
+ dir.entries << "second_file"
12
+ end
13
+
14
+ def setup
15
+ @directory = 'something'
16
+ @dir_stub = DirStub.new
17
+ setup_dir( @dir_stub )
18
+ Dir.stubs( :open ).yields( @dir_stub )
19
+ @library = Alx::Library.new.load_library( @directory )
20
+ end
21
+
22
+ def teardown
23
+ Dir.unstub( :open )
24
+ end
25
+
26
+ def test_list_pattern
27
+ books = @library.list( 'first' )
28
+ books.size.should == 2
29
+ books[ 0 ].title.should == @dir_stub.entries[ 0 ].gsub( /_/, ' ' )
30
+ end
31
+
32
+ end
33
+