alx 0.0.1

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.
@@ -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
+