tabscroll 0.0.1 → 1.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,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
-