aio_elin 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/LICENSE.txt +675 -0
- data/README.md +9 -0
- data/config.rb +39 -0
- data/lib/aio/base/debug.rb +30 -0
- data/lib/aio/base/toolkit/array.rb +24 -0
- data/lib/aio/base/toolkit/date.rb +46 -0
- data/lib/aio/base/toolkit/deep_clone.rb +10 -0
- data/lib/aio/base/toolkit/diff.rb +104 -0
- data/lib/aio/base/toolkit/excel_office.rb +421 -0
- data/lib/aio/base/toolkit/excel_wps.rb +437 -0
- data/lib/aio/base/toolkit/excel_wps.rb.bak +299 -0
- data/lib/aio/base/toolkit/ipaddr.rb +28 -0
- data/lib/aio/base/toolkit/os.rb +26 -0
- data/lib/aio/base/toolkit/regexp.rb +32 -0
- data/lib/aio/base/toolkit/string.rb +28 -0
- data/lib/aio/base/toolkit/table.rb +441 -0
- data/lib/aio/base/toolkit/test_diff.rb +9 -0
- data/lib/aio/base/toolkit/test_excel.rb +118 -0
- data/lib/aio/base/toolkit/test_word.rb +58 -0
- data/lib/aio/base/toolkit/word_wps.rb +492 -0
- data/lib/aio/base/toolkit.rb +18 -0
- data/lib/aio/base.rb +10 -0
- data/lib/aio/core/device/cisco.rb +13 -0
- data/lib/aio/core/device/cmd_switch.rb +113 -0
- data/lib/aio/core/device/h3c.rb +12 -0
- data/lib/aio/core/device/huawei.rb +10 -0
- data/lib/aio/core/device/juniper.rb +10 -0
- data/lib/aio/core/device/maipu.rb +11 -0
- data/lib/aio/core/device/methods.rb +233 -0
- data/lib/aio/core/device/methods.rb.bak +199 -0
- data/lib/aio/core/device/parent_device.rb +275 -0
- data/lib/aio/core/device.rb +15 -0
- data/lib/aio/core/device_manager.rb +207 -0
- data/lib/aio/core/module/cmd.rb +160 -0
- data/lib/aio/core/module/description.rb +67 -0
- data/lib/aio/core/module/input_style.rb +98 -0
- data/lib/aio/core/module/output_style.rb +80 -0
- data/lib/aio/core/module/platform.rb +30 -0
- data/lib/aio/core/module/ranking.rb +24 -0
- data/lib/aio/core/module/special_style.rb +30 -0
- data/lib/aio/core/module/template.rb +13 -0
- data/lib/aio/core/module.rb +15 -0
- data/lib/aio/core/module_loader.rb +161 -0
- data/lib/aio/core/module_loader.rb.bak +148 -0
- data/lib/aio/core/module_manager.rb +112 -0
- data/lib/aio/core/module_manager.rb.bak +78 -0
- data/lib/aio/core/parse/file.rb +19 -0
- data/lib/aio/core/parse/parser.rb +91 -0
- data/lib/aio/core/parse/parser_machine/bak/has_cmd_state.rb +14 -0
- data/lib/aio/core/parse/parser_machine/bak/has_context_state.rb +11 -0
- data/lib/aio/core/parse/parser_machine/bak/no_cmd_state.rb +11 -0
- data/lib/aio/core/parse/parser_machine/bak/no_context_state.rb +11 -0
- data/lib/aio/core/parse/parser_machine/full_state.rb +12 -0
- data/lib/aio/core/parse/parser_machine/has_device_state.rb +44 -0
- data/lib/aio/core/parse/parser_machine/no_device_state.rb +12 -0
- data/lib/aio/core/parse/parser_machine/parent_state.rb +26 -0
- data/lib/aio/core/parse/parser_machine.rb +47 -0
- data/lib/aio/core/parse.rb +6 -0
- data/lib/aio/core/text/context.rb +211 -0
- data/lib/aio/core/text/line_string.rb +74 -0
- data/lib/aio/core/text/warning.rb +179 -0
- data/lib/aio/core/text.rb +7 -0
- data/lib/aio/core/warning/description.rb +47 -0
- data/lib/aio/core/warning/warning_summarize.rb +232 -0
- data/lib/aio/core/warning.rb +6 -0
- data/lib/aio/core.rb +32 -0
- data/lib/aio/license.rb +687 -0
- data/lib/aio/resource/cover_picture.png +0 -0
- data/lib/aio/resource/line.png +0 -0
- data/lib/aio/resource/logo.png +0 -0
- data/lib/aio/ui/banner.rb +85 -0
- data/lib/aio/ui/readable_text.rb +75 -0
- data/lib/aio/ui/verbose.rb +29 -0
- data/lib/aio/ui/version.rb +9 -0
- data/lib/aio/ui.rb +138 -0
- data/lib/aio.rb +13 -0
- data/lib/modules/cmd/cisco/show_clock.rb +32 -0
- data/lib/modules/cmd/cisco/show_cpu.rb +32 -0
- data/lib/modules/cmd/cisco/show_env.rb +71 -0
- data/lib/modules/cmd/cisco/show_failover.rb +39 -0
- data/lib/modules/cmd/cisco/show_interface_ip_brief.rb +24 -0
- data/lib/modules/cmd/cisco/show_interfaces.rb +177 -0
- data/lib/modules/cmd/cisco/show_inv.rb +43 -0
- data/lib/modules/cmd/cisco/show_ip_interface_brief.rb +42 -0
- data/lib/modules/cmd/cisco/show_ip_ospf_nei.rb +38 -0
- data/lib/modules/cmd/cisco/show_ip_route_summary.rb +81 -0
- data/lib/modules/cmd/cisco/show_memory.rb +27 -0
- data/lib/modules/cmd/cisco/show_process_cpu.rb +35 -0
- data/lib/modules/cmd/cisco/show_process_memory.rb +63 -0
- data/lib/modules/cmd/cisco/show_version.rb +97 -0
- data/lib/modules/cmd/h3c/display_clock.rb +32 -0
- data/lib/modules/cmd/h3c/display_cpu.rb +51 -0
- data/lib/modules/cmd/h3c/display_device_manuinfo.rb +45 -0
- data/lib/modules/cmd/h3c/display_fan.rb +91 -0
- data/lib/modules/cmd/h3c/display_interface.rb +203 -0
- data/lib/modules/cmd/h3c/display_ip_interface_brief.rb +34 -0
- data/lib/modules/cmd/h3c/display_ip_routing.rb +68 -0
- data/lib/modules/cmd/h3c/display_ip_routing_stat.rb +90 -0
- data/lib/modules/cmd/h3c/display_memory.rb +35 -0
- data/lib/modules/cmd/h3c/display_ospf_peer.rb +38 -0
- data/lib/modules/cmd/h3c/display_power.rb +90 -0
- data/lib/modules/cmd/h3c/display_version.rb +54 -0
- data/lib/modules/cmd/h3c/display_vrrp_verbose.rb +86 -0
- data/lib/modules/cmd/maipu/show_env.rb +34 -0
- data/lib/modules/cmd/maipu/show_ip_route.rb +74 -0
- data/lib/modules/cmd/maipu/show_ip_route_statistic.rb +36 -0
- data/lib/modules/cmd/maipu/show_memory.rb +31 -0
- data/lib/modules/cmd/maipu/show_system_fan.rb +66 -0
- data/lib/modules/cmd/maipu/show_system_power.rb +66 -0
- data/lib/modules/cmd/maipu/show_version.rb +50 -0
- data/lib/modules/description/style/crc.rb +22 -0
- data/lib/modules/description/style/input_errors.rb +22 -0
- data/lib/modules/description/style/overrun.rb +22 -0
- data/lib/modules/description/style/proc_ratio.rb +22 -0
- data/lib/modules/description/style/protocol.rb +22 -0
- data/lib/modules/description/style/register.rb +22 -0
- data/lib/modules/description/style/runts.rb +22 -0
- data/lib/modules/description/style/template.rb +22 -0
- data/lib/modules/description/style/total_output_drops.rb +22 -0
- data/lib/modules/input/style/compare_xml.rb +89 -0
- data/lib/modules/input/style/console.rb +222 -0
- data/lib/modules/input/style/console.rb.bak +114 -0
- data/lib/modules/input/style/xinhua_nat.rb +70 -0
- data/lib/modules/output/style/boc_day.rb +223 -0
- data/lib/modules/output/style/cmds.rb +77 -0
- data/lib/modules/output/style/compare_json.rb +26 -0
- data/lib/modules/output/style/compare_report.rb +31 -0
- data/lib/modules/output/style/compare_xml.rb +86 -0
- data/lib/modules/output/style/excel_table_office.rb +407 -0
- data/lib/modules/output/style/excel_table_wps.rb +400 -0
- data/lib/modules/output/style/summary_report.rb +563 -0
- data/lib/modules/special/style/compare.rb +110 -0
- metadata +176 -0
@@ -0,0 +1,78 @@
|
|
1
|
+
# 管理,保存各个加载的模块
|
2
|
+
class Aio::ModuleManager
|
3
|
+
|
4
|
+
# def [](key)
|
5
|
+
# end
|
6
|
+
|
7
|
+
attr_accessor :modules, :modules_count
|
8
|
+
|
9
|
+
# NOTE modules[reference_name] = {
|
10
|
+
# :device_type
|
11
|
+
# :full_path
|
12
|
+
# :klass
|
13
|
+
def initialize
|
14
|
+
# self.module_info_by_path = {}
|
15
|
+
# self.module_load_error_by_path = {}
|
16
|
+
# self.module_paths = []
|
17
|
+
self.modules = {}
|
18
|
+
self.modules_count = {}
|
19
|
+
end
|
20
|
+
|
21
|
+
# 加载一个目录下的所有模块
|
22
|
+
# @param [String] path 目录的路径
|
23
|
+
# @param [Hash] options
|
24
|
+
def load_modules(path, options={})
|
25
|
+
end
|
26
|
+
|
27
|
+
# 将实例化后的模块类放到 modules 中
|
28
|
+
def add_module(path, device_type, reference_name, module_klass)
|
29
|
+
|
30
|
+
modules[reference_name] = {:device_type => device_type,
|
31
|
+
:full_path => path,
|
32
|
+
:klass => module_klass
|
33
|
+
}
|
34
|
+
end
|
35
|
+
|
36
|
+
# 通过设备类型获得模块类
|
37
|
+
# 返回类型为: 数组
|
38
|
+
def get_module_by_device_type(device_type)
|
39
|
+
return_array = []
|
40
|
+
|
41
|
+
device_type = device_type.to_s
|
42
|
+
modules.each do |m|
|
43
|
+
type = m[:device_type]
|
44
|
+
if device_type == type
|
45
|
+
return_array << m[:klass]
|
46
|
+
end
|
47
|
+
next
|
48
|
+
end
|
49
|
+
|
50
|
+
return return_array
|
51
|
+
end
|
52
|
+
|
53
|
+
# 获得所有加载模块的设备类型的字符串型
|
54
|
+
# 返回类型为: 数组
|
55
|
+
def get_modules_device_type_to_str
|
56
|
+
return_array = []
|
57
|
+
|
58
|
+
modules_counts.keys do |key|
|
59
|
+
return_array << key.to_s
|
60
|
+
end
|
61
|
+
|
62
|
+
return return_array
|
63
|
+
end
|
64
|
+
|
65
|
+
|
66
|
+
# 判断此设备类型的模块是否加载
|
67
|
+
def device_type_enable?(device_type)
|
68
|
+
true
|
69
|
+
end
|
70
|
+
|
71
|
+
def notify(opts={})
|
72
|
+
if opts[:count_by_device_type]
|
73
|
+
@modules_count = opts[:count_by_device_type]
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
|
78
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Aio::Parse
|
2
|
+
|
3
|
+
class File
|
4
|
+
|
5
|
+
attr_accessor :file_open
|
6
|
+
|
7
|
+
def initialize(file_path)
|
8
|
+
self.file_open = File.open(file_path, "r+")
|
9
|
+
end
|
10
|
+
|
11
|
+
def each_line
|
12
|
+
file_open.each_line do |line|
|
13
|
+
# 改进点,加入sefe_string方法
|
14
|
+
yield line
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
|
19
|
+
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
#coding=utf-8
|
2
|
+
|
3
|
+
module Aio::Parse
|
4
|
+
class Parser
|
5
|
+
attr_accessor :device_manager
|
6
|
+
attr_accessor :parser_machine
|
7
|
+
|
8
|
+
# 重要!在分析前需要确定input_klass
|
9
|
+
# input_klass 的类为input模块的类
|
10
|
+
# Aio::Module::InputStyle
|
11
|
+
attr_accessor :input_klass
|
12
|
+
|
13
|
+
include Aio::Ui::Verbose
|
14
|
+
|
15
|
+
def initialize(device_manager, parser_machine)
|
16
|
+
self.device_manager = device_manager
|
17
|
+
self.parser_machine = parser_machine
|
18
|
+
|
19
|
+
@invalid_input = Aio::Base::Toolkit::Regexp.merge([
|
20
|
+
Aio::Device::Cisco::InvalidInput,
|
21
|
+
Aio::Device::H3C::InvalidInput,
|
22
|
+
Aio::Device::Huawei::InvalidInput,
|
23
|
+
Aio::Device::Maipu::InvalidInput,
|
24
|
+
Aio::Device::Juniper::InvalidInput,
|
25
|
+
])
|
26
|
+
end
|
27
|
+
|
28
|
+
# 通过巡检文件的方式获得关键信息,并按cmd模块逐个解析
|
29
|
+
def parse_by_module
|
30
|
+
|
31
|
+
# 注意这里manager_ip可有可无, 没有的话默认为nil
|
32
|
+
print_good "正在加载信息..."
|
33
|
+
@input_klass.parse do |device_name, cmd, context, manager_ip|
|
34
|
+
device_info = {
|
35
|
+
:device_name => device_name,
|
36
|
+
:cmd => cmd.strip,
|
37
|
+
:context => Aio::Text::Context.new(context),
|
38
|
+
:manager_ip => manager_ip
|
39
|
+
}
|
40
|
+
|
41
|
+
# 判断 context 是否有效
|
42
|
+
next if invalid?(context)
|
43
|
+
|
44
|
+
# 所有判断交到状态机处理
|
45
|
+
self.parser_machine.get_device(device_info)
|
46
|
+
self.parser_machine.get_full(device_info)
|
47
|
+
end
|
48
|
+
print_good "信息加载完成"
|
49
|
+
|
50
|
+
total = device_manager.devices_number
|
51
|
+
print_good "总共 #{total} 台设备"
|
52
|
+
print_good "正在对各个设备进行分析..."
|
53
|
+
device_manager.each_devices_with_index do |name, klass, i|
|
54
|
+
# 将解析命令后,并修改了自身类的实例覆盖掉原来父类
|
55
|
+
progress_bar(total, i+1, name)
|
56
|
+
|
57
|
+
# Debug处
|
58
|
+
if name == "B_HBWHA_CAM_DS01"
|
59
|
+
#puts "now"
|
60
|
+
end
|
61
|
+
new_klass = klass.parse
|
62
|
+
device_manager[name] = new_klass.instance
|
63
|
+
end
|
64
|
+
clear_line
|
65
|
+
print_good "设备信息分析完成"
|
66
|
+
end
|
67
|
+
|
68
|
+
# 判断 context 是否有效
|
69
|
+
def invalid?(context)
|
70
|
+
return true if context.empty?
|
71
|
+
return true if @invalid_input.match(context[1])
|
72
|
+
return false
|
73
|
+
end
|
74
|
+
|
75
|
+
# 通过output/compare_xml生成的XML文件解析,直接将结果保存
|
76
|
+
# compare_klass 为比较模块
|
77
|
+
# 其中只比较useful的值,并不会去比较warning
|
78
|
+
# warning 有原本device中以及比较中共同得出
|
79
|
+
def parse_by_compare(compare_klass)
|
80
|
+
|
81
|
+
# device_hash 为提供比较文件的hash
|
82
|
+
print_good "正在将比较文件转换为内部Hash表"
|
83
|
+
device_hash = @input_klass.parse
|
84
|
+
compare_klass.device_manager = device_manager
|
85
|
+
compare_klass.input_benchmark = device_hash
|
86
|
+
compare_hash = compare_klass.parse
|
87
|
+
device_manager.merge_warning(compare_hash)
|
88
|
+
end
|
89
|
+
|
90
|
+
end
|
91
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module Aio::Parse
|
2
|
+
class HasDeviceState < ParentState
|
3
|
+
|
4
|
+
def get_device(opts)
|
5
|
+
self.device_manager.add_device(opts)
|
6
|
+
end
|
7
|
+
|
8
|
+
def get_full(opts)
|
9
|
+
|
10
|
+
if ! check_full(opts)
|
11
|
+
no_full
|
12
|
+
elsif
|
13
|
+
@machine.to_full_state
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
17
|
+
|
18
|
+
def no_full
|
19
|
+
end
|
20
|
+
|
21
|
+
# 验证是否有cmd和context了
|
22
|
+
def check_full(opts={})
|
23
|
+
device_name = opts[:device_name]
|
24
|
+
device_klass = self.device_manager.devices[device_name]
|
25
|
+
|
26
|
+
org_cmd = opts[:cmd]
|
27
|
+
org_context = opts[:context]
|
28
|
+
org_cmd_reg = Aio::Base::Toolkit::Regexp.to_reg(org_cmd)
|
29
|
+
device_klass.cmds_context.each_pair do |cmd, context|
|
30
|
+
|
31
|
+
# 只有当有cmd, 并且context不为空的时候才算有
|
32
|
+
# :NOTE 可以在这里的context类加入.check_avlid? 查看是否有效
|
33
|
+
if org_cmd_reg.match(cmd)
|
34
|
+
if ! context.empty?
|
35
|
+
return true
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
return false
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
#coding=utf-8
|
2
|
+
|
3
|
+
module Aio::Parse
|
4
|
+
class ErrorMachineMethod < StandardError
|
5
|
+
def to_s; "请重载此状态机方法"; end
|
6
|
+
end
|
7
|
+
|
8
|
+
class ParentState
|
9
|
+
def initialize(machine)
|
10
|
+
@machine = machine
|
11
|
+
end
|
12
|
+
|
13
|
+
def get_device
|
14
|
+
raise ErrorMachineMethod.new
|
15
|
+
end
|
16
|
+
|
17
|
+
def get_full
|
18
|
+
raise ErrorMachineMethod.new
|
19
|
+
end
|
20
|
+
|
21
|
+
def device_manager
|
22
|
+
@machine.device_manager
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
@@ -0,0 +1,47 @@
|
|
1
|
+
module Aio::Parse
|
2
|
+
|
3
|
+
require "aio/core/parse/parser_machine/parent_state"
|
4
|
+
require "aio/core/parse/parser_machine/no_device_state"
|
5
|
+
require "aio/core/parse/parser_machine/has_device_state"
|
6
|
+
require "aio/core/parse/parser_machine/full_state"
|
7
|
+
|
8
|
+
class ParserMachine
|
9
|
+
# 保存状态机的状态
|
10
|
+
attr_reader :state
|
11
|
+
|
12
|
+
# device_manager
|
13
|
+
attr_reader :device_manager
|
14
|
+
|
15
|
+
def initialize(device_manager)
|
16
|
+
@device_manager = device_manager
|
17
|
+
|
18
|
+
@no_device_state = Aio::Parse::NoDeviceState.new(self)
|
19
|
+
@has_device_state = Aio::Parse::HasDeviceState.new(self)
|
20
|
+
@full_state = Aio::Parse::FullState.new(self)
|
21
|
+
|
22
|
+
@state = @no_device_state
|
23
|
+
end
|
24
|
+
|
25
|
+
def get_device(opts)
|
26
|
+
@state.get_device(opts)
|
27
|
+
end
|
28
|
+
|
29
|
+
def get_full(opts)
|
30
|
+
@state.get_full(opts)
|
31
|
+
end
|
32
|
+
|
33
|
+
# 状态的切换
|
34
|
+
def to_no_device_state
|
35
|
+
@state = @no_device_state
|
36
|
+
end
|
37
|
+
|
38
|
+
def to_has_device_state
|
39
|
+
@state = @has_device_state
|
40
|
+
end
|
41
|
+
|
42
|
+
def to_full_state
|
43
|
+
@state = @full_state
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
@@ -0,0 +1,211 @@
|
|
1
|
+
#coding=utf-8
|
2
|
+
|
3
|
+
module Aio::Text
|
4
|
+
class Context < ::Array
|
5
|
+
|
6
|
+
class OutLineError < StandardError; end
|
7
|
+
|
8
|
+
include Aio::Ui::Verbose
|
9
|
+
|
10
|
+
attr_reader :count_line, :backup_line
|
11
|
+
|
12
|
+
def initialize(*arr)
|
13
|
+
super
|
14
|
+
self.each_with_index do |str, i|
|
15
|
+
self[i] = Aio::Text::LineString.new(str.chomp)
|
16
|
+
end
|
17
|
+
@backup_line = nil
|
18
|
+
@count_line = 0
|
19
|
+
end
|
20
|
+
|
21
|
+
# 到下一行
|
22
|
+
def next
|
23
|
+
@count_line += 1
|
24
|
+
end
|
25
|
+
|
26
|
+
# 对每行进行read, 判断是单步运行还是循环运行
|
27
|
+
# 修改了此处的backup_line 逻辑
|
28
|
+
def readline_match_block(reg, single = false, &block)
|
29
|
+
|
30
|
+
reg = Aio::Base::Toolkit::Regexp.safe(reg)
|
31
|
+
|
32
|
+
first = true
|
33
|
+
loop do
|
34
|
+
line_str = self[@count_line]
|
35
|
+
|
36
|
+
if first
|
37
|
+
@backup_line = @count_line
|
38
|
+
end
|
39
|
+
|
40
|
+
# 如果出界,有可能是因为循环导致
|
41
|
+
# 跳出循环
|
42
|
+
# 此处有问题,无法判断是否为最后一个,并跳出此模块
|
43
|
+
if @backup_line > self.size and line_str.nil?
|
44
|
+
@count_line = @backup_line
|
45
|
+
if Aio::Base::Debug.mismatch?
|
46
|
+
puts "[-] Can't match this line: "
|
47
|
+
puts caller
|
48
|
+
puts " line_string: #{self[@backup_line]}"
|
49
|
+
puts " regexp: #{reg}"
|
50
|
+
end
|
51
|
+
raise OutLineError
|
52
|
+
end
|
53
|
+
|
54
|
+
if line_str.nil?
|
55
|
+
@count_line = @backup_line
|
56
|
+
break
|
57
|
+
end
|
58
|
+
|
59
|
+
first = false
|
60
|
+
begin
|
61
|
+
res = line_str.match_block(reg) do |b|
|
62
|
+
block.call(b) unless block.nil?
|
63
|
+
end
|
64
|
+
rescue IndexError => e
|
65
|
+
print_error "IndexError: 请检查模块block提取信息名称"
|
66
|
+
puts "caller"
|
67
|
+
puts caller
|
68
|
+
exit
|
69
|
+
rescue NoMethodError
|
70
|
+
if Aio::Base::Debug.module_debug?
|
71
|
+
print_error "NoMethodError: 请检查模块block中useful是否定义正确"
|
72
|
+
puts caller
|
73
|
+
end
|
74
|
+
exit
|
75
|
+
rescue ArgumentError => e
|
76
|
+
if Aio::Base::Debug.module_debug?
|
77
|
+
puts "ArgumentError:"
|
78
|
+
puts e.message
|
79
|
+
puts caller
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
@count_line += 1
|
84
|
+
|
85
|
+
# 如果匹配到,跳出循环
|
86
|
+
break if res
|
87
|
+
|
88
|
+
# 如果只是单步运行,就返回
|
89
|
+
break if single
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
# 单行循环
|
94
|
+
# stop 为停止出,在停止处之前的每一行都将输出
|
95
|
+
def readline_match_block_loop(start, stop, &block)
|
96
|
+
stop = Aio::Base::Toolkit::Regexp.safe(stop)
|
97
|
+
loop do
|
98
|
+
readline_match_block(start, true, &block)
|
99
|
+
break if stop.match(self[@count_line])
|
100
|
+
break if self[@count_line].nil?
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
# 读取一个区间,并返回块
|
105
|
+
# 只会执行一次
|
106
|
+
# stop 作为分裂符
|
107
|
+
# opt 当last为false时,不会对stop一行输出
|
108
|
+
# opt 当before为true时,只会分裂stop的前一行,count_line保留
|
109
|
+
def readline_range(start, stop, opt={:last=>false}, &block)
|
110
|
+
str_context = Context.new
|
111
|
+
start = Aio::Base::Toolkit::Regexp.safe(start)
|
112
|
+
stop = Aio::Base::Toolkit::Regexp.safe(stop)
|
113
|
+
backup_line = @count_line
|
114
|
+
|
115
|
+
loop do
|
116
|
+
line_str = self[@count_line]
|
117
|
+
|
118
|
+
if line_str.nil?
|
119
|
+
@count_line = backup_line
|
120
|
+
raise OutLineError
|
121
|
+
end
|
122
|
+
|
123
|
+
if start =~ line_str
|
124
|
+
str_context << line_str
|
125
|
+
@count_line += 1
|
126
|
+
break
|
127
|
+
end
|
128
|
+
@count_line += 1
|
129
|
+
end
|
130
|
+
|
131
|
+
loop do
|
132
|
+
line_str = self[@count_line]
|
133
|
+
#raise OutLineError if line_str.nil?
|
134
|
+
if stop =~ line_str or line_str.nil?
|
135
|
+
str_context << line_str if opt[:last]
|
136
|
+
@count_line += 1 unless opt[:before]
|
137
|
+
break
|
138
|
+
else
|
139
|
+
str_context << line_str
|
140
|
+
end
|
141
|
+
@count_line += 1
|
142
|
+
end
|
143
|
+
|
144
|
+
block.call(str_context)
|
145
|
+
end
|
146
|
+
|
147
|
+
# 当需要多次循环时使用
|
148
|
+
# 此方法用于循环更加安全
|
149
|
+
def readline_range_loop(start, stop, opt={:last=>false}, &block)
|
150
|
+
loop do
|
151
|
+
begin
|
152
|
+
readline_range(start, stop, opt, &block)
|
153
|
+
rescue OutLineError
|
154
|
+
break
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
# 读取一个区间并返回块
|
160
|
+
# 在起始位置之后的行中,满足条件, 则放入同一区间。否则返回
|
161
|
+
def readline_range_if(start, condition, &block)
|
162
|
+
str_context = Context.new
|
163
|
+
start = Aio::Base::Toolkit::Regexp.safe(start)
|
164
|
+
condition = Aio::Base::Toolkit::Regexp.safe(condition)
|
165
|
+
|
166
|
+
loop do
|
167
|
+
line_str = self[@count_line]
|
168
|
+
raise OutLineError if line_str.nil?
|
169
|
+
if start =~ line_str
|
170
|
+
str_context << line_str
|
171
|
+
@count_line += 1
|
172
|
+
break
|
173
|
+
end
|
174
|
+
@count_line += 1
|
175
|
+
end
|
176
|
+
|
177
|
+
loop do
|
178
|
+
line_str = self[@count_line]
|
179
|
+
if condition =~ line_str
|
180
|
+
str_context << line_str
|
181
|
+
@count_line += 1
|
182
|
+
else
|
183
|
+
break
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
187
|
+
block.call(str_context)
|
188
|
+
end
|
189
|
+
|
190
|
+
def readline_range_if_loop(start, condition, &block)
|
191
|
+
loop do
|
192
|
+
begin
|
193
|
+
readline_range_if(start, condition, &block)
|
194
|
+
rescue OutLineError
|
195
|
+
break
|
196
|
+
end
|
197
|
+
end
|
198
|
+
end
|
199
|
+
|
200
|
+
def count_line
|
201
|
+
self[@count_line]
|
202
|
+
end
|
203
|
+
|
204
|
+
def method_missing(mid, *arg, &block)
|
205
|
+
print_error "#{mid} 方法未定义,请检查方法名拼写"
|
206
|
+
puts caller[0]
|
207
|
+
super
|
208
|
+
end
|
209
|
+
|
210
|
+
end
|
211
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
#coding=utf-8
|
2
|
+
|
3
|
+
module Aio::Text
|
4
|
+
class LineString < String
|
5
|
+
class Mismatch < StandardError; end
|
6
|
+
|
7
|
+
include Aio::Ui::Verbose
|
8
|
+
|
9
|
+
# 获得区块
|
10
|
+
def match_block(reg)
|
11
|
+
block = reg.match(self)
|
12
|
+
#raise Mismatch.new, "reg: #{reg}\nstr: #{self.to_s}" if block.nil?
|
13
|
+
if block.nil?
|
14
|
+
return false
|
15
|
+
end
|
16
|
+
|
17
|
+
# 有两种更新的方式,不加str 那么就是从block中的提取
|
18
|
+
# 如果有str, 则直接使用str
|
19
|
+
def block.update(info, sym, str=nil)
|
20
|
+
sym = sym.to_sym
|
21
|
+
if info.nil?
|
22
|
+
print_error "请检查update中的第一个参数是否定义"
|
23
|
+
pp caller
|
24
|
+
end
|
25
|
+
|
26
|
+
if str.nil?
|
27
|
+
info[sym] = self[sym].strip
|
28
|
+
else
|
29
|
+
info[sym] = str.strip
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def block.update_arr(info, sym)
|
34
|
+
sym = sym.to_sym
|
35
|
+
info[sym] ||= []
|
36
|
+
info[sym] << self[sym].strip
|
37
|
+
end
|
38
|
+
|
39
|
+
def block.update_hash(info, sym, key, val)
|
40
|
+
sym = sym.to_sym
|
41
|
+
info[sym] ||= {}
|
42
|
+
info[sym][key] = val.strip
|
43
|
+
end
|
44
|
+
|
45
|
+
# 参数info 放置useful
|
46
|
+
# 参数sym 为Symbol类型的标示
|
47
|
+
# 参数level 为 :serious 或 :ordinary
|
48
|
+
# 参数mod 一般为self
|
49
|
+
# 参数opt[:string] 当block中没有sym项时使用
|
50
|
+
def block.warning(info, sym, level, mod, opt={})
|
51
|
+
sym = sym.to_sym
|
52
|
+
self.update(info, sym, opt[:string])
|
53
|
+
# Aio::Text::Warning 类中的warning方法
|
54
|
+
mod.warning_klass.warning(info, sym, level, mod, opt[:force])
|
55
|
+
end
|
56
|
+
|
57
|
+
def block.warning_serious(info, sym, mod, opt={})
|
58
|
+
sym = sym.to_sym
|
59
|
+
self.update(info, sym, opt[:string])
|
60
|
+
mod.warning_klass.warning_serious(info, sym, mod, opt[:force])
|
61
|
+
end
|
62
|
+
|
63
|
+
def block.warning_ordinary(info, sym, mod, opt={})
|
64
|
+
sym = sym.to_sym
|
65
|
+
self.update(info, sym, opt[:string])
|
66
|
+
mod.warning_klass.warning_ordinary(info, sym, mod, opt[:force])
|
67
|
+
end
|
68
|
+
|
69
|
+
yield block
|
70
|
+
end
|
71
|
+
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|