salticid 0.9.0

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,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__'