tabscroll 0.0.1 → 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,73 @@
1
+ # tabscroll - Neat guitar tab scroller.
2
+
3
+ `tabscroll` is a (Ruby-powered) guitar tab scroller on the terminal.
4
+
5
+ It supports forward and backwards auto-scrolling and currently
6
+ reads a nice range of guitar tabs.
7
+
8
+ ## Usage and Screenshots
9
+
10
+ $ tabscroll my-guitar-tab.txt
11
+
12
+ Running on a small terminal
13
+ ![big screen](http://www.alexdantas.net/projects/tabscroll/screenshots/screen1.png "Small Screen")
14
+
15
+ The help window on a big screen
16
+ ![big screen](http://www.alexdantas.net/projects/tabscroll/screenshots/screen2.png "Big Screen")
17
+
18
+ ## Guitar tab file format and troubleshooting
19
+
20
+ `tabscroll` only works with textual guitar tabs, not chords with lyrics.
21
+
22
+ It attempts to read any kind of tab format (although it works better with tabs
23
+ exported from _Guitar Pro_). For now it requires you to split each tab row with
24
+ a blank line. For example, this would work:
25
+
26
+ E S S S S S S Q S S S S E S S S S S S E S S S S S S
27
+ --0--------0------0----L---0-1-|--0----------0h-1-0----------0h-1-|
28
+ --1----------0h-1-1----L-1-----|--1----1----------1----1----------|
29
+ ------------------0----L-------|--2--2-----2------0--0-----0------|
30
+ -----0-2----------2----L-------|--3------3--------2------2--------|
31
+ --3------3--------3----L-------|----------------------------------|
32
+ -------------------------------|----------------------------------|
33
+
34
+ E S S S S S S E S S S S S S E S S S S S S E S S S S S S
35
+ --0----3---0-----5--3---0------0-|--L----------0h-1-0----------3p-1-|
36
+ --1----------1-3-0--------3p-0---|--1----1----------1----1----------|
37
+ --2--2---2-------0----0----------|--2--2-----2------0--0-----0------|
38
+ ---------------------------------|--3------3--------2------2--------|
39
+ --0------------------------------|----------------------------------|
40
+ -----------------3------3--------|----------------------------------|
41
+
42
+ But this wouldn't:
43
+
44
+ --0--------0------0----L---0-1-|--0----------0h-1-0----------0h-1-|
45
+ --1----------0h-1-1----L-1-----|--1----1----------1----1----------|
46
+ ------------------0----L-------|--2--2-----2------0--0-----0------|
47
+ -----0-2----------2----L-------|--3------3--------2------2--------|
48
+ --3------3--------3----L-------|----------------------------------|
49
+ -------------------------------|----------------------------------|
50
+ --0----3---0-----5--3---0------0-|--L----------0h-1-0----------3p-1-|
51
+ --1----------1-3-0--------3p-0---|--1----1----------1----1----------|
52
+ --2--2---2-------0----0----------|--2--2-----2------0--0-----0------|
53
+ ---------------------------------|--3------3--------2------2--------|
54
+ --0------------------------------|----------------------------------|
55
+ -----------------3------3--------|----------------------------------|
56
+
57
+ So if something bad happens and the program crashes, edit the tab making sure to
58
+ keep a consistent tab format (6 in 6 lines, or 5 in 5) each with a blank line
59
+ inbetween.
60
+
61
+ At worse, please comment (add `#` at the start of) any line that's not the tab
62
+ (you know, author info, instructions, etc). Sorry for the inconvenience, I plan
63
+ to improve a lot the detection of tabs on the future.
64
+
65
+ ## Contact
66
+
67
+ Hi, I'm Alexandre Dantas! Thanks for having interest in this project. Please
68
+ take the time to visit any of the links below.
69
+
70
+ * `tabscroll` homepage: http://www.alexdantas.net/projects/tabscroll
71
+ * Contact: `eu @ alexdantas.net`
72
+ * My homepage: http://www.alexdantas.net
73
+
@@ -2,71 +2,17 @@
2
2
  #
3
3
  # The main `tabscroll` executable
4
4
 
5
- require 'tabscroll'
5
+ # Is this considered ugly?
6
+ require_relative '../lib/tabscroll'
7
+ require_relative '../lib/tabscroll/settings'
6
8
 
7
- begin
8
- filename = ARGV[0]
9
- if not filename
10
- puts "Usage:"
11
- puts " $ #{PROGRAM_NAME} (filename)"
12
- exit 666
13
- end
14
-
15
- $engine = Engine.new
16
- if not $engine
17
- puts 'Failed to start curses!'
18
- exit 1337
19
- end
20
- $engine.timeout 10
21
-
22
- win = Screen.new(0, 1, $engine.width, $engine.height - 2)
23
- track = Track.new win
24
- track.load filename
25
- track.auto_scroll true
26
-
27
- titlebar = Screen.new(0, 0, $engine.width, 1)
28
- statusbar = Screen.new(0, ($engine.height - 1), $engine.width, 1)
9
+ # class TabScroll expects this hash, watch out!
10
+ $settings = {}
29
11
 
30
- bars_hidden = false
31
- finished = false
32
- while not finished
33
- # WHY DOES GETCH CLEARS UP THE WHOLE SCREEN?
34
- # IT DOESNT MAKE ANY SENSE
35
- c = $engine.getchar
36
- case c
37
- when 'e'
38
- track.end
39
- when 'a'
40
- track.begin
41
- when 'h'
42
- show_help_window
43
- when 'o'
44
- bars_hidden = (bars_hidden ? false : true)
45
- Curses::clear
46
- when '<'
47
- track.scroll -5
48
- when '>'
49
- track.scroll 5
50
- when Curses::KEY_LEFT
51
- track.speed -= 1
52
- when Curses::KEY_RIGHT
53
- track.speed += 1
54
- when Curses::KEY_DOWN, Curses::KEY_UP
55
- track.speed = 0
56
- when 'q'
57
- quit
58
- end
59
-
60
- track.update
61
- track.show
62
- if not bars_hidden
63
- titlebar.mvaddstr(0, 0, "#{filename} (#{track.percent_completed}%) ", Engine::Colors[:cyan])
64
- titlebar.mvaddstr_right(0, " Speed: #{track.speed}", Engine::Colors[:cyan])
65
-
66
- statusbar.mvaddstr_left(0, "#{PROGRAM_NAME} v#{PROGRAM_VERSION} - press `h` for help", Engine::Colors[:green])
67
- end
68
- end
12
+ begin
13
+ $settings = Settings.new
14
+ $settings.parse ARGV
69
15
 
70
- quit
16
+ TabScroll::run $settings[:filename]
71
17
  end
72
18
 
metadata CHANGED
@@ -1,16 +1,19 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tabscroll
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 1.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alexandre Dantas
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-10-13 00:00:00.000000000 Z
11
+ date: 2013-10-10 00:00:00.000000000 Z
12
12
  dependencies: []
13
- description: Scrolls a textual guitar tab on the terminal.
13
+ description: |
14
+ Scrolls a textual guitar tab on the terminal.
15
+ It supports forward and backwards auto-scrolling and currently
16
+ reads a nice range of guitar tabs.
14
17
  email:
15
18
  - eu@alexdantas.net
16
19
  executables:
@@ -18,17 +21,15 @@ executables:
18
21
  extensions: []
19
22
  extra_rdoc_files: []
20
23
  files:
21
- - lib/tabscroll.rb
22
- - lib/tabscroll/engine.rb
23
- - lib/tabscroll/screen.rb
24
- - lib/tabscroll/track.rb
25
- - lib/tabscroll/popup.rb
26
- - lib/tabscroll/timer.rb
27
24
  - bin/tabscroll
25
+ - LICENSE
26
+ - README.md
27
+ - CHANGELOG.md
28
28
  homepage: http://www.alexdantas.net/projects/tabscroll
29
29
  licenses:
30
30
  - GPL-3.0
31
- metadata: {}
31
+ metadata:
32
+ github: http://www.github.com/alexdantas/tabscroll
32
33
  post_install_message:
33
34
  rdoc_options: []
34
35
  require_paths:
@@ -1,40 +0,0 @@
1
- # The main executable file.
2
-
3
- require_relative 'tabscroll/engine'
4
- require_relative 'tabscroll/screen'
5
- require_relative 'tabscroll/track'
6
- require_relative 'tabscroll/popup'
7
-
8
- # Global vars
9
- $engine = nil
10
- PROGRAM_NAME = "tabscroll"
11
- PROGRAM_VERSION = "0.0.1"
12
-
13
- # Terminates program's execution normally, finishing the engine.
14
- def quit
15
- $engine.exit
16
- exit 0
17
- end
18
-
19
- # Displays a help window, waiting for a keypress.
20
- def show_help_window
21
- title = 'Help'
22
- text = <<END_OF_TEXT
23
- q quit
24
- h help/go back
25
- left/right auto-scroll left/right
26
- up/down stop auto-scrolling
27
- </> step scroll left/right
28
- o toggle status/title bars
29
-
30
-
31
- #{PROGRAM_NAME} v#{PROGRAM_VERSION}
32
- homepage alexdantas.net/projects/tabscroll
33
- author Alexandre Dantas <eu@alexdantas.net>
34
- END_OF_TEXT
35
-
36
- pop = Popup.new(title, text)
37
- will_quit = pop.show
38
- quit if will_quit
39
- end
40
-
@@ -1,95 +0,0 @@
1
-
2
- require 'curses'
3
-
4
- # The main interface with Curses.
5
- #
6
- # This acts as a middleman, abstracting away curses' details.
7
- class Engine
8
-
9
- # All possible colors.
10
- Colors = {
11
- :black => 1,
12
- :white => 2,
13
- :red => 3,
14
- :yellow => 4,
15
- :magenta => 5,
16
- :blue => 6,
17
- :green => 7,
18
- :cyan => 8
19
- }.freeze
20
-
21
- # Initializes Ncurses with minimal +width+ and +height+.
22
- #
23
- def initialize(min_width=nil, min_height=nil)
24
- @has_colors = nil
25
-
26
- @screen = Curses::init_screen
27
- return nil if not @screen
28
-
29
- if min_width and min_height
30
- cur_width = @screen.maxx
31
- cur_height = @screen.maxy
32
-
33
- if cur_width < @width or cur_height < @height
34
- self.exit
35
- $stderr << "Error: Screen size too small (#{cur_width}x#{cur_height})\n"
36
- $stderr << "Please resize your terminal to at least #{@width}x#{@height}\n"
37
- return nil
38
- end
39
- end
40
-
41
- @has_colors = Curses.has_colors?
42
- if @has_colors
43
- Curses.start_color
44
- Curses.use_default_colors # will use default background
45
-
46
- # Initializes: constant foreground bg
47
- Curses.init_pair(Colors[:white], Curses::COLOR_BLACK, -1)
48
- Curses.init_pair(Colors[:blue], Curses::COLOR_BLUE, -1)
49
- Curses.init_pair(Colors[:red], Curses::COLOR_RED, -1)
50
- Curses.init_pair(Colors[:green], Curses::COLOR_GREEN, -1)
51
- Curses.init_pair(Colors[:magenta], Curses::COLOR_MAGENTA, -1)
52
- Curses.init_pair(Colors[:yellow], Curses::COLOR_YELLOW, -1)
53
- Curses.init_pair(Colors[:cyan], Curses::COLOR_CYAN, -1)
54
- end
55
-
56
- Curses::cbreak
57
- Curses::curs_set 0
58
- Curses::noecho
59
- Curses::nonl
60
- Curses::stdscr.keypad = true # extra keys
61
- end
62
-
63
- def width
64
- return Curses::cols
65
- end
66
-
67
- def height
68
- return Curses::lines
69
- end
70
-
71
- def exit
72
- Curses::refresh
73
- Curses::close_screen
74
- end
75
-
76
- def set_color color
77
- if @has_colors
78
- @screen.attron Curses::color_pair(color)
79
- return self
80
- else
81
- return nil
82
- end
83
- end
84
-
85
- def getchar
86
- return Curses::getch
87
- end
88
-
89
- # +timeout+ says how many milliseconds we wait for a key to be
90
- # pressed.
91
- def timeout timeout
92
- Curses::timeout = timeout
93
- end
94
- end
95
-
@@ -1,60 +0,0 @@
1
-
2
- require_relative 'screen.rb'
3
-
4
- # A simple centralized popup.
5
- #
6
- # It resizes as you place the text on it.
7
- class Popup < Screen
8
-
9
- def initialize(title, text)
10
- @title = title
11
- @text = []
12
- text.each_line do |line|
13
- @text += [line.chomp]
14
- end
15
-
16
- max_width = title.length
17
- max_height = 1
18
-
19
- @text.each do |line|
20
- max_width = line.length if line.length > max_width
21
- max_height += 1
22
- end
23
-
24
- max_width += 2 # left-right borders
25
- max_height += 1 # down border
26
-
27
- x = Curses::cols/2 - max_width/2
28
- y = Curses::lines/2 - max_height/2
29
-
30
- super(x, y, max_width, max_height)
31
- self.background ' '
32
- self.box
33
-
34
- self.mvaddstr_center(0, title, Engine::Colors[:cyan])
35
-
36
- y = 1
37
- @text.each do |line|
38
- self.mvaddstr(1, y, line)
39
- y += 1
40
- end
41
- end
42
-
43
- def show
44
- finished = false
45
- while not finished
46
- c = Curses::getch
47
- case c
48
- when 'q'
49
- return true
50
- when 'h'
51
- finished = true
52
- end
53
- end
54
-
55
- Curses::stdscr.clear
56
- Curses::stdscr.refresh
57
- return false
58
- end
59
- end
60
-
@@ -1,125 +0,0 @@
1
-
2
- require 'curses'
3
-
4
- # A segment of the terminal screen.
5
- #
6
- # BUG WARNING HACK FUCK
7
- # Whenever I use @win.attrset/@win.setpos/@win.addch
8
- # it doesn't work at all.
9
- # Apparently, when I do this, Curses::getch clears up
10
- # the entire screen.
11
- #
12
- # DO NOT DO THIS
13
- #
14
- class Screen
15
- attr_reader :width, :height
16
-
17
- # Creates a Screen at `x` `y` `w` `h`.
18
- def initialize(x, y, w, h)
19
- @win = Curses::Window.new(h, w, y, x)
20
- @width = w
21
- @height = h
22
- end
23
-
24
- # Sets the current color of the Screen.
25
- def set_color color
26
- Curses::attrset(Curses::color_pair color)
27
- end
28
-
29
- # Executes a block of code encapsulated within a color on/off.
30
- # Note that the color can be overrided.
31
- def with_color(color=nil)
32
- Curses::attron(Curses::color_pair color) if color
33
- yield
34
- Curses::attroff(Curses::color_pair color) if color
35
- end
36
-
37
- # Puts a character +c+ on (+x+, +y+) with optional +color+.
38
- def mvaddch(x, y, c, color=nil)
39
- return if x < 0 or x >= @width
40
- return if y < 0 or y >= @height
41
-
42
- self.with_color color do
43
- Curses::setpos(@win.begy + y, @win.begx + x)
44
- Curses::addch c
45
- end
46
- end
47
-
48
- # Puts a string +str+ on (+x+, +y+) with optional +color+.
49
- def mvaddstr(x, y, str, color=nil)
50
- return if x < 0 or x >= @width
51
- return if y < 0 or y >= @height
52
-
53
- self.with_color color do
54
- # @win.setpos(@win.begy + y, @win.begx + x)
55
- # @win.addstr str
56
- Curses::setpos(@win.begy + y, @win.begx + x)
57
- Curses::addstr str
58
- end
59
- end
60
-
61
- # Puts a string +str+ centered on +y+ with optional +color+.
62
- def mvaddstr_center(y, str, color=nil)
63
- x = (@width/2) - (str.length/2)
64
- self.mvaddstr(x, y, str, color)
65
- end
66
-
67
- def mvaddstr_left(y, str, color=nil)
68
- self.mvaddstr(0, y, str, color)
69
- end
70
-
71
- def mvaddstr_right(y, str, color=nil)
72
- x = @width - str.length
73
- self.mvaddstr(x, y, str, color)
74
- end
75
-
76
- # Erases all of the Screen's contents
77
- def clear
78
- @win.clear
79
- end
80
-
81
- # Commits the changes on the Screen.
82
- def refresh
83
- @win.refresh
84
- end
85
-
86
- # Moves window so that the upper-left corner is at `x` `y`.
87
- def move(x, y)
88
- @win.move(y, x)
89
- end
90
-
91
- # Resizes window to +width+ and +h+eight.
92
- def resize(w, h)
93
- @win.resize(h, w)
94
- @width = w
95
- @height = h
96
- end
97
-
98
- # Set block/nonblocking reads for window.
99
- #
100
- # * If `delay` is negative, blocking read is used.
101
- # * If `delay` is zero, nonblocking read is used.
102
- # * If `delay` is positive, waits for `delay` milliseconds and
103
- # returns ERR of no input.
104
- def timeout(delay=-1)
105
- @win.timeout = delay
106
- end
107
-
108
- def background char
109
- @win.bkgd char
110
- @win.refresh
111
- end
112
-
113
- # Sets the Screen border.
114
- #
115
- # * If all arguments are set, that's ok.
116
- # * If only the first 2 arguments are set, they are the vertical
117
- # and horizontal chars.
118
- #
119
- def box(horizontal=0, vertical=0)
120
- @win.box(horizontal, vertical)
121
- @win.refresh
122
- end
123
-
124
- end
125
-