salticid 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,30 @@
1
+ module Ncurses
2
+ # Returns size of screen [y, x]
3
+ def self.dimensions
4
+ x = Array.new
5
+ y = Array.new
6
+ Ncurses.getmaxyx(Ncurses.stdscr, y, x)
7
+ [y.first, x.first]
8
+ end
9
+
10
+ class WINDOW
11
+ # Adds a FormattedString
12
+ def add_formatted_string(string)
13
+ string.each do |part|
14
+ # Set attributes
15
+ part[1..-1].each {| attribute| attron attribute }
16
+ addstr part[0]
17
+ # Unset attributes
18
+ part[1..-1].each {| attribute| attroff attribute }
19
+ end
20
+ end
21
+
22
+ # Returns cursor y and x coordinates.
23
+ def cursor
24
+ y = Array.new
25
+ x = Array.new
26
+ getyx y, x
27
+ [y.first, x.first]
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,28 @@
1
+ class Salticid
2
+ class Interface
3
+ module Resizeable
4
+ def resize(dimensions = nil)
5
+ case dimensions
6
+ when Hash
7
+ # Resize self
8
+ @height = dimensions[:height] if dimensions[:height]
9
+ @width = dimensions[:width] if dimensions[:width]
10
+ @top = dimensions[:top] if dimensions[:top]
11
+ @left = dimensions[:left] if dimensions[:left]
12
+
13
+ if @window
14
+ # Resize window
15
+ @window.mvwin @top, @left
16
+ @window.resize @height, @width
17
+ end
18
+
19
+ true
20
+ else
21
+ # Resize parent
22
+ @interface.resize
23
+ false
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,134 @@
1
+ class Salticid
2
+ class Interface
3
+ class TabView < View
4
+
5
+ def initialize(interface, params = {})
6
+ super
7
+
8
+ @tabs = []
9
+ @active = -1
10
+ end
11
+
12
+ # Gets the active tab
13
+ def active
14
+ @tabs[@active] || nil
15
+ end
16
+
17
+ # Sets the active tab
18
+ def active=(tab)
19
+ @active = @tabs.index tab
20
+ render
21
+ end
22
+
23
+ # Adds a tab (and switches to it by default)
24
+ def add(tab)
25
+ @tabs << tab
26
+ @active = @tabs.size - 1
27
+ render
28
+ end
29
+
30
+ alias :<< :add
31
+
32
+ # Deletes a tab and switches to the previous tab
33
+ def delete(tab)
34
+ @tabs.delete tab
35
+ previous
36
+ end
37
+
38
+ # Iterates over each tab
39
+ def each(&block)
40
+ @tabs.each &block
41
+ end
42
+
43
+ # Advances to the next tab
44
+ def next
45
+ scroll 1
46
+ end
47
+
48
+ # Goes to the previous tab
49
+ def previous
50
+ scroll -1
51
+ end
52
+
53
+ # Draws to screen
54
+ def render
55
+ return false if @tabs.empty?
56
+ # Divide into regions
57
+
58
+ # Ignore dividers
59
+ width = @width - size + 1
60
+ base_width = width / size
61
+ regions = Array.new(size, base_width)
62
+
63
+ # Add remainder to successive tabs.
64
+ (width - base_width * size).times do |i|
65
+ regions[i] += 1
66
+ end
67
+
68
+ # Move to start
69
+ @window.move 0,0
70
+
71
+ @tabs.each_with_index do |tab, i|
72
+ if i > 0
73
+ @window.addch Ncurses::ACS_VLINE
74
+ end
75
+
76
+ color = Interface::COLOR_PAIRS[tab.state]
77
+ @window.attron color if color
78
+ @window.attron Ncurses::A_BOLD
79
+ @window.attron Ncurses::A_REVERSE if i == @active
80
+ @window.addstr tab.to_s.slice(0,regions[i]).center(regions[i])
81
+ @window.attroff Ncurses::A_REVERSE if i == @active
82
+ @window.attroff Ncurses::A_BOLD
83
+ @window.attroff color if color
84
+ end
85
+
86
+ @window.refresh
87
+ end
88
+
89
+ def resize(dimensions = nil)
90
+ return unless super
91
+
92
+ @tabs.each do |tab|
93
+ tab.resize(
94
+ :top => 1,
95
+ :left => 0,
96
+ :height => height - 1,
97
+ :width => width
98
+ )
99
+ end
100
+ active.render
101
+ end
102
+
103
+ # Moves by a number of tabs
104
+ def scroll(delta = 1)
105
+ active.hide rescue NoMethodError
106
+ @active = (@active + delta).modulo(@tabs.size)
107
+ active.show
108
+ render
109
+ end
110
+
111
+ def shutdown
112
+ @tabs.each do |tab|
113
+ tab.shutdown
114
+ end
115
+ @tabs = []
116
+ end
117
+
118
+ # Number of tabs
119
+ def size
120
+ @tabs.size
121
+ end
122
+
123
+ # Switches the active tab to the specified label
124
+ def switch_to_label(label)
125
+ if index = @tabs.map{ |tab| tab.to_s }.index(label)
126
+ @active = index
127
+ render
128
+ else
129
+ raise RuntimeError.new("no tab labeled #{label}")
130
+ end
131
+ end
132
+ end
133
+ end
134
+ end
@@ -0,0 +1,49 @@
1
+ class Salticid
2
+ class Interface
3
+ class View
4
+ include Resizeable
5
+
6
+ attr_accessor :window, :height, :width, :top, :left
7
+
8
+ def initialize(interface, params = {})
9
+ @interface = interface
10
+ @height = params[:height] || Ncurses.LINES
11
+ @width = params[:width] || Ncurses.COLS
12
+ @top = params[:top] || 0
13
+ @left = params[:left] || 0
14
+
15
+ @window = Ncurses::WINDOW.new @height, @width, @top, @left
16
+ end
17
+
18
+ def height=(height)
19
+ @height = height
20
+ @window.resize @height, @width
21
+ end
22
+
23
+ def hide
24
+ @hidden = true
25
+ @window.erase
26
+ end
27
+
28
+ def left=(left)
29
+ @left = left
30
+ @window.mvwin @top, @left
31
+ end
32
+
33
+ def show
34
+ @hidden = false
35
+ render
36
+ end
37
+
38
+ def top=(top)
39
+ @top = top
40
+ @window.mvwin @top, @left
41
+ end
42
+
43
+ def width=(width)
44
+ @width = width
45
+ @window.resize @height, @width
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,8 @@
1
+ class Message
2
+ attr_reader :severity, :text, :time
3
+ def initialize(*args)
4
+ @text = args.pop
5
+ @severity = args.first
6
+ @time = Time.now
7
+ end
8
+ end
@@ -0,0 +1,98 @@
1
+ class Salticid::Role
2
+ # A role is a list of tasks.
3
+ attr_reader :name, :tasks, :salticid
4
+
5
+ def initialize(name, opts = {})
6
+ @name = name.to_s
7
+ @tasks = []
8
+ @salticid = opts[:salticid]
9
+ end
10
+
11
+ # Runs the block in the context of each.
12
+ def each_host(&block)
13
+ hosts.each do |host|
14
+ host.instance_exec &block
15
+ end
16
+ end
17
+
18
+ # Returns an array of all hosts in this salticid which include this role.
19
+ def hosts
20
+ @salticid.hosts.select do |host|
21
+ host.roles.include? self
22
+ end
23
+ end
24
+
25
+ def inspect
26
+ "#<Role #{name} tasks=#{@tasks.inspect}>"
27
+ end
28
+
29
+ # Sets or gets the name of this role.
30
+ def name(name = nil)
31
+ if name
32
+ @name = name.to_s
33
+ else
34
+ @name
35
+ end
36
+ end
37
+
38
+ # Finds (and optionally defines) a task.
39
+ #
40
+ # Tasks are first resolved in the role's task list, then in the Salticid's task
41
+ # list. Finally, tasks are created from scratch. Any invocation of task adds
42
+ # that task to this role.
43
+ #
44
+ # If a block is given, the block is assigned to the local (role) task. The
45
+ # task is dup'ed to prevent modifying a possible global task.
46
+ #
47
+ # The task is returned at the end of the method.
48
+ def task(name, &block)
49
+ name = name.to_s
50
+
51
+ if task = @tasks.find{|t| t.name == name}
52
+ # Found in self
53
+ elsif (task = @salticid.tasks.find{|t| t.name == name}) and not block_given?
54
+ # Found in salticid
55
+ @tasks << task
56
+ else
57
+ # Create new task in self
58
+ task = Salticid::Task.new(name, :salticid => @salticid)
59
+ @tasks << task
60
+ end
61
+
62
+ if block_given?
63
+ # Remove the task from our list, and replace it with a copy.
64
+ # This is to prevent local declarations from clobbering global tasks.
65
+ i = @tasks.index(task) || @task.size
66
+ task = task.dup
67
+ task.block = block
68
+ @tasks[i] = task
69
+ end
70
+
71
+ task
72
+ end
73
+
74
+ def to_s
75
+ @name.to_s
76
+ end
77
+
78
+ def to_string
79
+ r = "Role #{@name}:\n"
80
+ r << " Tasks:\n"
81
+ r << tasks.map { |t| " #{t}" }.sort!.join("\n")
82
+ r << "\n Hosts:\n"
83
+ r << hosts.map { |h| " #{h}" }.join("\n")
84
+ end
85
+
86
+ # When a task name is called on a role, it is automatically run on every host
87
+ # associated with that role.
88
+ #
89
+ # role(:myapp).deploy => role(:myapp).each_host { |h| h.myapp.deploy }
90
+ def method_missing(meth, *args, &block)
91
+ name = meth.to_s
92
+ if task = @tasks.find { |t| t.name == name }
93
+ hosts.each do |host|
94
+ task.run(host, *args)
95
+ end
96
+ end
97
+ end
98
+ end
@@ -0,0 +1,26 @@
1
+ class RoleProxy
2
+ # Wraps a Role in the context of a Host: calls to the RoleProxy are passed to
3
+ # the Role it wraps, but called with the host as the first argument. This
4
+ # allows role-method chaining for nice namespaces.
5
+ #
6
+ # RoleProxy.new(host, role).some_task(*args) =>
7
+ # role.some_task(host, *args)
8
+ #
9
+ # RoleProxies are created on the fly by Hosts; you shouldn't have to
10
+ # instantiate them directly. They're involved when you do something like:
11
+ #
12
+ # host :foo do
13
+ # my_role.some_task
14
+ # end
15
+
16
+ undef_method(*(instance_methods.map(&:intern) - [:__id__, :__send__, :respond_to?, :object_id]))
17
+
18
+ def initialize(host, role)
19
+ @host = host
20
+ @role = role
21
+ end
22
+
23
+ def method_missing(meth, *args, &block)
24
+ @role.tasks.find{|t| t.name == meth.to_s}.run(@host, *args, &block)
25
+ end
26
+ end
@@ -0,0 +1,49 @@
1
+ class Salticid::Task
2
+ # A named block, runnable in some context
3
+ attr_accessor :name, :block
4
+
5
+ def initialize(name, opts = {})
6
+ @name = name.to_s
7
+ end
8
+
9
+ def ==(other)
10
+ self.name == other.name and
11
+ self.block == other.block
12
+ end
13
+
14
+ def dup
15
+ dup = Salticid::Task.new(@name)
16
+ dup.block = @block
17
+ dup
18
+ end
19
+
20
+ def inspect
21
+ "#<Task #{@name}>"
22
+ end
23
+
24
+ # Sets or gets the name of this task.
25
+ def name(name = nil)
26
+ if name
27
+ @name = name.to_s
28
+ else
29
+ @name
30
+ end
31
+ end
32
+
33
+ # Runs the task in a given context
34
+ def run(context = nil, *args)
35
+ if context
36
+ context.instance_exec(*args, &@block)
37
+ else
38
+ @block.call(*args)
39
+ end
40
+ end
41
+
42
+ def to_s
43
+ @name.to_s
44
+ end
45
+
46
+ def to_string
47
+ "Task #{self}"
48
+ end
49
+ end
@@ -0,0 +1,3 @@
1
+ class Salticid
2
+ VERSION = "0.9.0"
3
+ end
@@ -0,0 +1,5 @@
1
+ require 'snippets/string/slash'
2
+ require 'snippets/symbol/slash'
3
+ require 'snippets/symbol/to_proc'
4
+ require 'snippets/object/instance_exec'
5
+ require 'snippets/object/__dir__'