gloo 3.2.0 → 3.4.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.
Files changed (60) hide show
  1. checksums.yaml +4 -4
  2. data/.ruby-version +1 -1
  3. data/gloo.gemspec +9 -3
  4. data/lib/VERSION +1 -1
  5. data/lib/VERSION_NOTES +14 -0
  6. data/lib/gloo/app/engine.rb +1 -1
  7. data/lib/gloo/app/log.rb +15 -16
  8. data/lib/gloo/app/platform.rb +11 -84
  9. data/lib/gloo/app/prompt.rb +90 -0
  10. data/lib/gloo/app/table.rb +51 -0
  11. data/lib/gloo/convert/falseclass_to_integer.rb +20 -0
  12. data/lib/gloo/convert/nilclass_to_date.rb +21 -0
  13. data/lib/gloo/convert/nilclass_to_datetime.rb +21 -0
  14. data/lib/gloo/convert/nilclass_to_integer.rb +21 -0
  15. data/lib/gloo/convert/nilclass_to_string.rb +21 -0
  16. data/lib/gloo/convert/nilclass_to_time.rb +21 -0
  17. data/lib/gloo/convert/trueclass_to_integer.rb +20 -0
  18. data/lib/gloo/core/error.rb +7 -0
  19. data/lib/gloo/core/gloo_system.rb +7 -14
  20. data/lib/gloo/core/it.rb +7 -0
  21. data/lib/gloo/core/obj.rb +7 -0
  22. data/lib/gloo/core/parser.rb +6 -3
  23. data/lib/gloo/objs/basic/container.rb +1 -2
  24. data/lib/gloo/objs/basic/integer.rb +24 -1
  25. data/lib/gloo/objs/basic/string.rb +116 -1
  26. data/lib/gloo/objs/basic/string_generator.rb +49 -0
  27. data/lib/gloo/objs/basic/text.rb +1 -17
  28. data/lib/gloo/objs/cli/menu.rb +5 -4
  29. data/lib/gloo/objs/cli/select.rb +3 -2
  30. data/lib/gloo/objs/{basic → ctrl}/function.rb +12 -0
  31. data/lib/gloo/objs/data/markdown.rb +59 -6
  32. data/lib/gloo/objs/data/mysql.rb +39 -27
  33. data/lib/gloo/objs/data/pg.rb +1 -1
  34. data/lib/gloo/objs/data/query_result.rb +4 -9
  35. data/lib/gloo/objs/data/table.rb +1 -1
  36. data/lib/gloo/objs/security/cipher.rb +193 -0
  37. data/lib/gloo/objs/security/password.rb +167 -0
  38. data/lib/gloo/objs/system/file_handle.rb +1 -3
  39. data/lib/gloo/objs/web/json.rb +3 -0
  40. data/lib/gloo/objs/web_svr/page.rb +26 -6
  41. data/lib/gloo/objs/web_svr/partial.rb +7 -6
  42. data/lib/gloo/objs/web_svr/svr.rb +267 -14
  43. data/lib/gloo/verbs/invoke.rb +80 -0
  44. data/lib/gloo/verbs/version.rb +1 -1
  45. data/lib/gloo/web_svr/asset.rb +54 -33
  46. data/lib/gloo/web_svr/config.rb +1 -1
  47. data/lib/gloo/web_svr/embedded_renderer.rb +1 -1
  48. data/lib/gloo/web_svr/handler.rb +6 -4
  49. data/lib/gloo/web_svr/request.rb +34 -8
  50. data/lib/gloo/web_svr/response.rb +14 -2
  51. data/lib/gloo/web_svr/response_code.rb +1 -1
  52. data/lib/gloo/web_svr/routing/router.rb +1 -2
  53. data/lib/gloo/web_svr/routing/show_routes.rb +4 -7
  54. data/lib/gloo/web_svr/server.rb +1 -1
  55. data/lib/gloo/web_svr/session.rb +161 -0
  56. data/lib/gloo/web_svr/table_renderer.rb +1 -1
  57. metadata +81 -26
  58. data/lib/gloo/objs/cli/banner.rb +0 -118
  59. data/lib/gloo/objs/cli/bar.rb +0 -133
  60. data/lib/gloo/objs/cli/pastel.rb +0 -104
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f1dca7b53440a446850b2c3bd58b9a2b3c66ef73156bf7e8e90bfba9ddd71032
4
- data.tar.gz: 012614b36386042458633b635a4f28c33fd9be21a50be7bcf37271d8c2aa8360
3
+ metadata.gz: 34119d3b6c3fc676b45d7172a6300e1bef50e7bfd480ecaaeab9ad39be040cc4
4
+ data.tar.gz: b812253883e7589dea4b6588b85661a1cf6e849a61e2c36a658be8279a0a6411
5
5
  SHA512:
6
- metadata.gz: 0ae04823687860a34d4134bc9f3338a7d05dd68b6cd618d8ef8f1f51198bbcd2ea692f3737ab6e235f175ffa184114c6158071fc743ccc1073cba27d1d4efca0
7
- data.tar.gz: 4a0c04fb3f64e2d7c045b72fd4a6f7c8b8d172b18b030de033d492803adf67eaf8c0f657e174b861d6de05172755f8bfb8273f3be42d53913c074923468371e7
6
+ metadata.gz: 33d90fe0f4135042d0d5d6cfa4323438183e43e034ce525542bff0aa34bd16baf703ed7819de51c5ad19b38dd51fec8423a4999179e08e41e0dbc89ad0f3d20c
7
+ data.tar.gz: 017e592805017fc75f776a9a1673eb50aba32ef227260c573f382e8dc83d067ac2429b1f18d722df22672b8f7c57cd941769180d517398db74cde98aeb56a64d
data/.ruby-version CHANGED
@@ -1 +1 @@
1
- ruby-3.0.2
1
+ ruby-3.2.5
data/gloo.gemspec CHANGED
@@ -33,14 +33,20 @@ Gem::Specification.new do |spec|
33
33
 
34
34
  spec.add_dependency "activesupport", '~> 6.1', ">= 6.1.5"
35
35
  spec.add_dependency 'chronic', '~> 0.10', '>= 0.10.2'
36
- spec.add_dependency 'colorize', '~> 0.8', '>= 0.8.1'
37
- spec.add_dependency 'tty', '~> 0.10', '>= 0.10.0'
36
+
37
+ spec.add_dependency 'colorize', '~> 1.1.0', '>= 1.1.0'
38
+ spec.add_dependency 'inquirer'
39
+ spec.add_dependency 'reline'
40
+ spec.add_dependency 'terminal-table'
41
+
38
42
  spec.add_dependency 'json', '~> 2.1', '>= 2.1.0'
39
- spec.add_dependency 'openssl', '~> 2.1', '>= 2.1.0'
43
+ spec.add_dependency 'openssl'
40
44
  spec.add_dependency 'net-ssh', '~> 6.1', '>= 6.1.0'
41
45
  spec.add_dependency 'mysql2', '~> 0.5', '>= 0.5.3'
42
46
  spec.add_dependency 'sqlite3', '~> 1.4', '>= 1.4.2'
43
47
  spec.add_dependency 'os', '~> 1.1', '>= 1.1.4'
44
48
  spec.add_dependency 'pg', '~> 1.5.4'
45
49
  spec.add_dependency 'thin', '~> 1.8.2'
50
+ spec.add_dependency 'redcarpet', '~> 3.6.0'
51
+ spec.add_dependency 'bcrypt', '~> 3.1.20'
46
52
  end
data/lib/VERSION CHANGED
@@ -1 +1 @@
1
- 3.2.0
1
+ 3.4.0
data/lib/VERSION_NOTES CHANGED
@@ -1,3 +1,17 @@
1
+ 3.4.0 - 2024.09.22
2
+ - Refactor for old TTY lib
3
+ - Additional web server functionality
4
+ - Web session and security helpers
5
+ - Other functions in support of serving web pages and running web server
6
+
7
+
8
+ 3.3.0 - 2024.08.16
9
+ - Adds nil converters to string and integer.
10
+ - Adds render to markdown object to convert to html
11
+ - Adds invoke verb to call a function from a script
12
+ - Web updates: singular name conventions
13
+
14
+
1
15
  3.2.0 - 2024.07.07
2
16
  - Update with more web server functionality, http methods, resource routing
3
17
  - Expands query with additional html table support
@@ -182,7 +182,7 @@ module Gloo
182
182
  #
183
183
  def loop
184
184
  while @running
185
- @last_cmd = @platform.prompt_cmd
185
+ @last_cmd = @platform.prompt.ask
186
186
  process_cmd
187
187
  end
188
188
  end
data/lib/gloo/app/log.rb CHANGED
@@ -34,7 +34,7 @@ module Gloo
34
34
  # If quiet is true, then message are written to the log
35
35
  # but not to the console.
36
36
  #
37
- def initialize( engine, quiet=true )
37
+ def initialize( engine, quiet = true )
38
38
  @engine = engine
39
39
  @quite = quiet
40
40
  @debug = engine.settings.debug
@@ -59,30 +59,30 @@ module Gloo
59
59
  # Files
60
60
  # ---------------------------------------------------------------------
61
61
 
62
- #
62
+ #
63
63
  # Get the log file.
64
- #
64
+ #
65
65
  def log_file
66
66
  return File.join( @engine.settings.log_path, LOG_FILE )
67
67
  end
68
68
 
69
- #
69
+ #
70
70
  # Get the error log file.
71
- #
71
+ #
72
72
  def err_file
73
73
  return File.join( @engine.settings.log_path, ERROR_FILE )
74
74
  end
75
75
 
76
-
77
76
  # ---------------------------------------------------------------------
78
77
  # Static Helpers
79
78
  # ---------------------------------------------------------------------
80
79
 
81
- #
80
+ #
82
81
  # Does the given str represent a logging level?
83
- #
84
- def self.is_level? str
82
+ #
83
+ def self.is_level?( str )
85
84
  return false unless str.is_a? String
85
+
86
86
  return LEVELS.include? str.strip.downcase
87
87
  end
88
88
 
@@ -90,9 +90,9 @@ module Gloo
90
90
  # Log file clearing
91
91
  # ---------------------------------------------------------------------
92
92
 
93
- #
93
+ #
94
94
  # Clear the log files.
95
- #
95
+ #
96
96
  def clear
97
97
  File.write( log_file, CLEARED )
98
98
  File.write( err_file, CLEARED )
@@ -100,7 +100,6 @@ module Gloo
100
100
  create_loggers
101
101
  end
102
102
 
103
-
104
103
  # ---------------------------------------------------------------------
105
104
  # Standard Output
106
105
  # ---------------------------------------------------------------------
@@ -108,13 +107,13 @@ module Gloo
108
107
  #
109
108
  # Show a message unless we're in quite mode.
110
109
  #
111
- def show( msg, color=nil )
110
+ def show( msg, color = nil )
112
111
  return if @quiet
113
112
 
114
113
  if color
115
114
  puts ColorizedString[ msg ].colorize( color.to_sym )
116
115
  else
117
- puts msg
116
+ puts msg
118
117
  end
119
118
  end
120
119
 
@@ -122,9 +121,9 @@ module Gloo
122
121
  # Logging functions
123
122
  # ---------------------------------------------------------------------
124
123
 
125
- #
124
+ #
126
125
  # Write to the specified level.
127
- #
126
+ #
128
127
  def write( msg, level )
129
128
  if level == DEBUG
130
129
  debug msg
@@ -4,16 +4,8 @@
4
4
  # Handle input and output for the CLI platform.
5
5
  #
6
6
  require 'active_support'
7
- require 'tty-prompt'
8
- require 'tty-cursor'
9
- require 'tty-screen'
10
- require 'tty-pager'
11
- require 'tty-markdown'
12
- require 'tty-editor'
13
- require 'tty-table'
14
7
  require 'colorize'
15
8
  require 'colorized_string'
16
- require 'pastel'
17
9
 
18
10
  module Gloo
19
11
  module App
@@ -21,56 +13,28 @@ module Gloo
21
13
 
22
14
  DEFAULT_TMP_FILE = 'tmp.txt'.freeze
23
15
 
24
- attr_reader :prompt
16
+ attr_reader :prompt, :table
25
17
 
26
18
  #
27
19
  # Set up Platform.
28
20
  #
29
21
  def initialize
30
- @prompt = TTY::Prompt.new
22
+ @prompt = Gloo::App::Prompt.new( self )
23
+ @table = Gloo::App::Table.new( self )
31
24
  end
32
25
 
33
26
  #
34
27
  # Show a message.
35
28
  #
36
- def show( msg, md=false, page=false )
37
- if md
38
- msg = TTY::Markdown.parse msg
39
- end
40
-
41
- if page
42
- # pager = TTY::Pager::SystemPager.new command: 'less -R'
43
- pager = TTY::Pager.new
44
- pager.page( msg )
45
- else
46
- puts msg
47
- end
48
- end
49
-
50
- #
51
- # Prompt for the next command.
52
- #
53
- def prompt_cmd
54
- return @prompt.ask( default_prompt )
29
+ def show( msg )
30
+ puts msg
55
31
  end
56
32
 
57
33
  #
58
34
  # Clear the screen.
59
35
  #
60
36
  def clear_screen
61
- @cursor ||= TTY::Cursor
62
- print @cursor.clear_screen
63
- print @cursor.move_to( 0, 0 )
64
- end
65
-
66
- #
67
- # Edit some temporary text and return the edited text.
68
- #
69
- def edit initial_value
70
- tmp = File.join( $settings.tmp_path, DEFAULT_TMP_FILE )
71
- File.open( tmp, 'w' ) { |file| file.write( initial_value ) }
72
- TTY::Editor.open( tmp )
73
- return File.read( tmp )
37
+ puts "\e[H\e[2J"
74
38
  end
75
39
 
76
40
  #
@@ -80,6 +44,7 @@ module Gloo
80
44
  return Gloo::Persist::DiscMech.new( engine )
81
45
  end
82
46
 
47
+
83
48
  # ---------------------------------------------------------------------
84
49
  # Color helper
85
50
  # ---------------------------------------------------------------------
@@ -92,36 +57,6 @@ module Gloo
92
57
  return colorized.to_s
93
58
  end
94
59
 
95
- # ---------------------------------------------------------------------
96
- # Table helper
97
- # ---------------------------------------------------------------------
98
-
99
- #
100
- # Show the given table data.
101
- #
102
- def show_table( headers, data, title = nil )
103
- pastel = ::Pastel.new
104
- if headers
105
- table = TTY::Table.new headers, data
106
- else
107
- table = TTY::Table.new rows: data
108
- end
109
- pad = [ 0, 1, 0, 1 ]
110
- rendered = table.render( :ascii, indent: 2, padding: pad ) do |r|
111
- r.border.style = :blue
112
- r.filter = proc do |val, row_index, _col_index|
113
- # col_index % 2 == 1 ? pastel.red.on_green(val) : val
114
- if headers && row_index.zero?
115
- pastel.blue( val )
116
- else
117
- row_index.odd? ? pastel.white( val ) : pastel.yellow( val )
118
- end
119
- end
120
- end
121
- puts
122
- puts "#{title.white}" if title
123
- puts "#{rendered}\n\n"
124
- end
125
60
 
126
61
  # ---------------------------------------------------------------------
127
62
  # Sceen helpers
@@ -130,14 +65,16 @@ module Gloo
130
65
  # Get the number of vertical lines on screen.
131
66
  #
132
67
  def lines
133
- TTY::Screen.rows
68
+ rows, columns = $stdout.winsize
69
+ return rows
134
70
  end
135
71
 
136
72
  #
137
73
  # Get the number of horizontal columns on screen.
138
74
  #
139
75
  def cols
140
- TTY::Screen.cols
76
+ rows, columns = $stdout.winsize
77
+ return columns
141
78
  end
142
79
 
143
80
  # ---------------------------------------------------------------------
@@ -146,16 +83,6 @@ module Gloo
146
83
 
147
84
  private
148
85
 
149
- #
150
- # Get the default prompt text.
151
- #
152
- def default_prompt
153
- dt = DateTime.now
154
- d = dt.strftime( '%Y.%m.%d' )
155
- t = dt.strftime( '%I:%M:%S' )
156
- return "#{'gloo'.blue} #{d.yellow} #{t.white} >"
157
- end
158
-
159
86
  end
160
87
  end
161
88
  end
@@ -0,0 +1,90 @@
1
+ # Author:: Eric Crane (mailto:eric.crane@mac.com)
2
+ # Copyright:: Copyright (c) 2024 Eric Crane. All rights reserved.
3
+ #
4
+ # CLI input.
5
+ #
6
+ require 'active_support'
7
+ require 'colorize'
8
+ require 'colorized_string'
9
+ require 'inquirer'
10
+ require "reline"
11
+
12
+ module Gloo
13
+ module App
14
+ class Prompt
15
+
16
+ #
17
+ # Set up Prompt.
18
+ #
19
+ def initialize platform
20
+ @platform = platform
21
+ end
22
+
23
+ #
24
+ # Show the prompt and get input.
25
+ # Use the default prompt if none is provided.
26
+ #
27
+ def ask( prompt=nil )
28
+ prompt ||= default_prompt
29
+
30
+ response = Reline.readline( "#{prompt} ", true)
31
+
32
+ # I don't like this one because it appends a ':' to the prompt.
33
+ # response = Ask.input prompt
34
+
35
+ # This was just the brute force way to do it.
36
+ # puts prompt
37
+ # return $stdin.gets.chomp
38
+
39
+ return response
40
+ end
41
+
42
+ #
43
+ # Prompt for multiline input.
44
+ #
45
+ def multiline( prompt )
46
+ puts 'To end input, type a period on a line by itself.'
47
+ text = Reline.readmultiline( "#{prompt} ", true ) do |input|
48
+ input.split.last == '.'
49
+ end
50
+
51
+ return text.lines[0..-2]
52
+ end
53
+
54
+ #
55
+ # Confirmation prompt.
56
+ # Answer is yes or no.
57
+ #
58
+ def yes?( prompt )
59
+ value = Ask.confirm "#{prompt} "
60
+ return value
61
+ end
62
+
63
+ #
64
+ # Show a selection list to choose from.
65
+ #
66
+ def select( prompt, options )
67
+ i = Ask.list prompt, options
68
+ return options[ i ]
69
+ end
70
+
71
+
72
+ # ---------------------------------------------------------------------
73
+ # Private Functions
74
+ # ---------------------------------------------------------------------
75
+
76
+ private
77
+
78
+ #
79
+ # Get the default prompt text.
80
+ #
81
+ def default_prompt
82
+ dt = DateTime.now
83
+ d = dt.strftime( '%Y.%m.%d' )
84
+ t = dt.strftime( '%I:%M:%S' )
85
+ return "#{'gloo'.blue} #{d.yellow} #{t.white} >"
86
+ end
87
+
88
+ end
89
+ end
90
+ end
@@ -0,0 +1,51 @@
1
+ # Author:: Eric Crane (mailto:eric.crane@mac.com)
2
+ # Copyright:: Copyright (c) 2024 Eric Crane. All rights reserved.
3
+ #
4
+ # CLI input.
5
+ #
6
+ require 'colorize'
7
+ require 'terminal-table'
8
+
9
+ module Gloo
10
+ module App
11
+ class Table
12
+
13
+ #
14
+ # Set up Table Helper.
15
+ #
16
+ def initialize platform
17
+ @platform = platform
18
+ end
19
+
20
+ #
21
+ # Put a box around the given string.
22
+ def box( str_value )
23
+ puts str_value
24
+ box = Terminal::Table.new( :headings => [], :rows => [ [ str_value ] ] )
25
+ return box.to_s
26
+ end
27
+
28
+ #
29
+ # Show the given table data.
30
+ #
31
+ def show( headers, data, title = nil )
32
+ unless title.blank?
33
+ table = Terminal::Table.new(
34
+ :title => title, :headings => headers, :rows => data )
35
+ else
36
+ table = Terminal::Table.new( :headings => headers, :rows => data )
37
+ end
38
+ puts table.to_s.colorize( color: :white, background: :black )
39
+ end
40
+
41
+
42
+ # ---------------------------------------------------------------------
43
+ # Private Functions
44
+ # ---------------------------------------------------------------------
45
+
46
+ private
47
+
48
+
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,20 @@
1
+ # Author:: Eric Crane (mailto:eric.crane@mac.com)
2
+ # Copyright:: Copyright (c) 2024 Eric Crane. All rights reserved.
3
+ #
4
+ # Conversion tool: FALSE to Integer.
5
+ #
6
+
7
+ module Gloo
8
+ module Convert
9
+ class FalseClassToInteger
10
+
11
+ #
12
+ # Convert the given FALSE value to an integer.
13
+ #
14
+ def convert( value )
15
+ return 0
16
+ end
17
+
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,21 @@
1
+ # Author:: Eric Crane (mailto:eric.crane@mac.com)
2
+ # Copyright:: Copyright (c) 2024 Eric Crane. All rights reserved.
3
+ #
4
+ # Conversion tool: Nil to Date.
5
+ #
6
+ require 'chronic'
7
+
8
+ module Gloo
9
+ module Convert
10
+ class NilClassToDate
11
+
12
+ #
13
+ # Convert a nil to a date.
14
+ #
15
+ def convert( value )
16
+ return Chronic.parse( '' )
17
+ end
18
+
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,21 @@
1
+ # Author:: Eric Crane (mailto:eric.crane@mac.com)
2
+ # Copyright:: Copyright (c) 2024 Eric Crane. All rights reserved.
3
+ #
4
+ # Conversion tool: Nil to DateTime.
5
+ #
6
+ require 'chronic'
7
+
8
+ module Gloo
9
+ module Convert
10
+ class NilClassToDateTime
11
+
12
+ #
13
+ # Convert a nil to a date.
14
+ #
15
+ def convert( value )
16
+ return Chronic.parse( '' )
17
+ end
18
+
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,21 @@
1
+ # Author:: Eric Crane (mailto:eric.crane@mac.com)
2
+ # Copyright:: Copyright (c) 2024 Eric Crane. All rights reserved.
3
+ #
4
+ # Conversion tool: Nil to Integer.
5
+ #
6
+ require 'chronic'
7
+
8
+ module Gloo
9
+ module Convert
10
+ class NilClassToInteger
11
+
12
+ #
13
+ # Convert a nil to a string.
14
+ #
15
+ def convert( value )
16
+ return 0
17
+ end
18
+
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,21 @@
1
+ # Author:: Eric Crane (mailto:eric.crane@mac.com)
2
+ # Copyright:: Copyright (c) 2024 Eric Crane. All rights reserved.
3
+ #
4
+ # Conversion tool: Nil to String.
5
+ #
6
+ require 'chronic'
7
+
8
+ module Gloo
9
+ module Convert
10
+ class NilClassToString
11
+
12
+ #
13
+ # Convert a nil to a string.
14
+ #
15
+ def convert( value )
16
+ return ''
17
+ end
18
+
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,21 @@
1
+ # Author:: Eric Crane (mailto:eric.crane@mac.com)
2
+ # Copyright:: Copyright (c) 2024 Eric Crane. All rights reserved.
3
+ #
4
+ # Conversion tool: Nil to Time.
5
+ #
6
+ require 'chronic'
7
+
8
+ module Gloo
9
+ module Convert
10
+ class NilClassToTime
11
+
12
+ #
13
+ # Convert a nil to a date.
14
+ #
15
+ def convert( value )
16
+ return Chronic.parse( '' )
17
+ end
18
+
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,20 @@
1
+ # Author:: Eric Crane (mailto:eric.crane@mac.com)
2
+ # Copyright:: Copyright (c) 2024 Eric Crane. All rights reserved.
3
+ #
4
+ # Conversion tool: TRUE to Integer.
5
+ #
6
+
7
+ module Gloo
8
+ module Convert
9
+ class TrueClassToInteger
10
+
11
+ #
12
+ # Convert the given TRUE value to an integer.
13
+ #
14
+ def convert( value )
15
+ return 1
16
+ end
17
+
18
+ end
19
+ end
20
+ end
@@ -56,6 +56,13 @@ module Gloo
56
56
  return @value.to_s
57
57
  end
58
58
 
59
+ #
60
+ # Is this a function object?
61
+ #
62
+ def is_function?
63
+ return false
64
+ end
65
+
59
66
  end
60
67
  end
61
68
  end