Module: Roby::CLI::Gen::Helpers

Included in:
Roby::CLI::Gen
Defined in:
lib/roby/cli/gen/helpers.rb

Overview

Helper methods for generator actions and templates

The module is used to extend Roby::CLI::Gen. Its methods are usually accessed as singletong methods on Roby::CLI::Gen, e.g. Gen.resolve_name.

Defined Under Namespace

Classes: Base, Context

Instance Method Summary collapse

Instance Method Details

#in_module(*module_path) ⇒ (String,String,String)

Helper to handle opening and closing modules

Examples:

usually used in e.g. ERB with

<% indent, open, close = Roby::App::GenBase.in_module("A", "Module") %>
<%= open %>
<%= indent %>class MyClass
<%= indent %>    it_does_something
<%= indent %>end
<%= close %>

Returns:

  • ((String,String,String))

    the indentation string for the module’s content, the code necessary to open the module and the code to close it



195
196
197
198
199
200
201
202
203
204
205
206
207
# File 'lib/roby/cli/gen/helpers.rb', line 195

def in_module(*module_path)
    indent = ""
    open_code = []
    close_code = []
    last_module_i = module_path.size - 1
    module_path.each_with_index do |m, i|
        nodoc = " #:nodoc:" if i == last_module_i
        open_code.push "#{indent}module #{m}#{nodoc}"
        close_code.unshift "#{indent}end"
        indent += "    "
    end
    [indent, open_code.join("\n"), close_code.join("\n")]
end

#make_context(vars) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Generate a context that be given to the context: argument to Thor’s template action



177
178
179
# File 'lib/roby/cli/gen/helpers.rb', line 177

def make_context(vars)
    Context.new(vars).context
end

#pathize(string) ⇒ Object

Converts an input string that is in camelcase into a path string

NOTE: Facets’ String#pathize and String#snakecase have corner cases that really don’t work for us:

'2D'.snakecase => '2_d'
'GPS'.pathize => 'gp_s'


216
217
218
219
220
221
222
223
224
225
# File 'lib/roby/cli/gen/helpers.rb', line 216

def pathize(string)
    string
        .gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2')
        .gsub(/([a-z])([A-Z][a-z])/, '\1_\2')
        .gsub("__", "/")
        .gsub("::", "/")
        .gsub(/\s+/, "") # spaces are bad form
        .gsub(/[?%*:|"<>.]+/, "") # reserved characters
        .downcase
end

#resolve_name(gen_type, given_name, robot_name, file_root, namespace_root) ⇒ Object

Resolve a user-given model name into the corresponding file path and namespace path

Both paths are returned relative to the given roots

Examples:

resolve_names('models/actions/navigation.rb',
              ['models', 'actions'],
              ['Actions']) # => [['navigation.rb'], ['Navigation']]
resolve_names('models/tasks/navigation/goto.rb',
              ['models', 'tasks'],
              ['Tasks'])
        # => [['navigation/goto.rb'], ['Navigation', 'Goto']]
resolve_names('models/tasks/navigation/goto.rb',
              ['models', 'actions'],
              ['Actions'])
        # => raise, as models/actions must be the path root

Raises:

  • InconsistenName if parts of the given name are inconsistent with the given roots



33
34
35
36
37
38
39
40
41
42
43
44
45
# File 'lib/roby/cli/gen/helpers.rb', line 33

def resolve_name(
    gen_type, given_name, robot_name, file_root, namespace_root
)
    if given_name =~ /\// || given_name[0, 1] !~ /[A-Z]/
        resolve_name_as_path(
            gen_type, given_name, robot_name, file_root, namespace_root
        )
    else
        resolve_name_as_constant(
            gen_type, given_name, robot_name, file_root, namespace_root
        )
    end
end

#resolve_name_as_constant(gen_type, given_name, robot_name, file_root, namespace_root) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Helper for #resolve_name



94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
# File 'lib/roby/cli/gen/helpers.rb', line 94

def resolve_name_as_constant(
    gen_type, given_name, robot_name, file_root, namespace_root
)
    robot_module =
        if robot_name
            [robot_name.camelcase(:upper)]
        else
            []
        end

    given_class_name = given_name.split("::")
    app_module_name = Roby.app.module_name.split("::")
    full_namespace_root = app_module_name + namespace_root

    non_matching_full_prefix =
        full_namespace_root.each_with_index.find do |p, i|
            given_class_name[i] != p
        end

    if non_matching_full_prefix
        if non_matching_full_prefix[1] != 0
            raise CLIInvalidArguments,
                  "attempted to create a #{gen_type} model outside "\
                  "of its expected namespace "\
                  "#{full_namespace_root.join('::')}"
        else
            non_matching_app_prefix =
                namespace_root.each_with_index.find do |p, i|
                    given_class_name[i] != p
                end
            if non_matching_app_prefix
                if non_matching_app_prefix[1] != 0
                    raise CLIInvalidArguments,
                          "attempted to create a #{gen_type} model "\
                          "outside of its expected namespace "\
                          "#{full_namespace_root.join('::')}"
                else
                    given_class_name =
                        full_namespace_root + given_class_name
                end
            else
                given_class_name =
                    app_module_name + given_class_name
            end
        end
    end

    if robot_name && given_class_name[-2, 1] != robot_module
        raise CLIInvalidArguments,
              "attempted to create a model for robot #{robot_name} "\
              "outside the expected namespace "\
              "#{robot_module.join('::')} "\
              "(e.g. #{given_class_name[0..-2].join('::')}"\
              "::#{robot_module.join('::')}"\
              "::#{given_class_name[-1]})"
    end

    file_name = given_class_name[full_namespace_root.size..-1]
                .map { |camel| pathize(camel) }
    [file_name, given_class_name]
end

#resolve_name_as_path(gen_type, given_name, robot_name, file_root, namespace_root) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Helper for #resolve_name



50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
# File 'lib/roby/cli/gen/helpers.rb', line 50

def resolve_name_as_path(
    gen_type, given_name, robot_name, file_root, namespace_root
)
    robot_module =
        if robot_name
            [robot_name.camelcase(:upper)]
        else
            []
        end

    file_name = given_name.split("/")
    non_matching_prefix = file_root.each_with_index.find do |p, i|
        file_name[i] != p
    end
    if non_matching_prefix
        if non_matching_prefix[1] != 0
            raise CLIInvalidArguments,
                  "attempted to create a #{gen_type} model "\
                  "outside of #{file_root.join('/')}"
        else
            file_name = file_root + file_name
        end
    end

    if robot_name && file_name[-2] != robot_name
        raise CLIInvalidArguments,
              "attempted to create a model for robot #{robot_name} "\
              "outside a #{robot_name}/ subfolder"
    end

    file_name[-1] = File.basename(file_name[-1], ".rb")
    file_name_without_root = file_name[file_root.size..-1]

    app_module_name = Roby.app.module_name.split("::")
    class_without_app =
        namespace_root +
        file_name_without_root.map { |n| n.camelcase(:upper) }
    class_name = app_module_name + class_without_app
    [file_name_without_root, class_name]
end