Module: Mint::CommandLine

Defined in:
lib/mint/command_line.rb

Class Method Summary collapse

Class Method Details

.configvoid

This method returns an undefined value.

Displays the sum of all active configurations, where local configurations override global ones.



298
299
300
# File 'lib/mint/command_line.rb', line 298

def self.config
  puts YAML.dump(Mint.configuration)
end

.configure(opts, scope = :local) ⇒ void

This method returns an undefined value.

Updates configuration options persistently in the appropriate scope, which defaults to local.

Parameters:

  • opts (Hash)

    a structured set of options to set on Mint at the specified scope

  • scope (Symbol) (defaults to: :local)

    the scope at which to apply the set of options



277
278
279
280
281
# File 'lib/mint/command_line.rb', line 277

def self.configure(opts, scope=:local)
  config_directory = Mint.path_for_scope(scope)
  FileUtils.mkdir_p config_directory
  Helpers.update_yaml! "#{config_directory}/#{Mint::CONFIG_FILE}", opts
end

.create_template(name, type, scope) ⇒ String

Creates a new template directory and file at the specified scope

Parameters:

  • name (String)

    the name of the template to create

  • type (Symbol)

    the type of template (:layout or :style)

  • scope (Symbol)

    the scope at which to create the template

Returns:

  • (String)

    the path to the created template file



164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
# File 'lib/mint/command_line.rb', line 164

def self.create_template(name, type, scope)
  content, ext =
    case type
    when :layout
      [default_layout_content, "erb"]
    when :style
      [default_style_content, "css"]
    else
      abort "Invalid template type: #{type}"
    end
  
  template_dir = Mint.template_path(name, scope)
  file_path = "#{template_dir}/#{type}.#{ext}"
  FileUtils.mkdir_p template_dir
  File.write(file_path, content)
  file_path
end

.default_layout_contentString

Returns default content for layout templates.

Returns:

  • (String)

    default content for layout templates



183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
# File 'lib/mint/command_line.rb', line 183

def self.default_layout_content
  <<~LAYOUT_TEMPLATE
    <!DOCTYPE html>
    <html>
      <head>
        <meta charset="utf-8">
        <title>Document</title>
        <% if style %>
          <link rel="stylesheet" href="<%= style %>">
        <% end %>
      </head>
      <body>
        <%= content %>
      </body>
    </html>
  LAYOUT_TEMPLATE
end

.default_style_contentString

Returns default content for style templates.

Returns:

  • (String)

    default content for style templates



202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
# File 'lib/mint/command_line.rb', line 202

def self.default_style_content
  <<~STYLE_TEMPLATE
    body {
      font-family: -apple-system, 'Segoe UI', Roboto, sans-serif;
      line-height: 1.25;
      max-width: 960px;
      margin: 0 auto;
      padding: 2rem;
      color: #333;
    }

    h1, h2, h3, h4, h5, h6 {
      color: #2c3e50;
    }

    a {
      color: #3498db;
      text-decoration: none;
    }

    a:hover {
      text-decoration: underline;
    }

    code {
      background-color: #f8f9fa;
      padding: 0.2em 0.4em;
      border-radius: 3px;
      font-family: 'Monaco', 'Ubuntu Mono', monospace;
    }
  STYLE_TEMPLATE
end

.discover_files_recursively(directories) ⇒ Array

Recursively discovers Markdown files in the given directories

Parameters:

  • directories (Array)

    the directories to search

Returns:

  • (Array)

    an array of markdown file paths



306
307
308
309
310
311
312
313
314
315
316
317
318
# File 'lib/mint/command_line.rb', line 306

def self.discover_files_recursively(directories)
  markdown_files = []
  directories.each do |dir|
    if File.file?(dir)
      markdown_files << dir if dir =~ /\.(#{Mint::MARKDOWN_EXTENSIONS.join('|')})$/i
    elsif File.directory?(dir)
      Dir.glob("#{dir}/**/*.{#{Mint::MARKDOWN_EXTENSIONS.join(',')}}", File::FNM_CASEFOLD).each do |file|
        markdown_files << file
      end
    end
  end
  markdown_files.sort
end

.edit(name, type, scope) ⇒ void

This method returns an undefined value.

Retrieve named template file (probably a built-in or installed template) and shell out that file to the user’s favorite editor.

Parameters:

  • name (String)

    the name of a template to edit

  • type (Symbol)

    either :layout or :style

  • scope (Symbol)

    the scope at which to look for/create the template



242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
# File 'lib/mint/command_line.rb', line 242

def self.edit(name, type, scope)
  abort "[error] No template specified" if name.nil? || name.empty?

  begin
    file = case type
           when :layout
             Mint.lookup_layout(name)
           when :style
             Mint.lookup_style(name)
           else
             abort "[error] Invalid template type: #{type}. Use :layout or :style"
           end
  rescue Mint::TemplateNotFoundException        
    print "Template '#{name}' does not exist. Create it? [y/N]: "
    response = STDIN.gets.chomp.downcase
    
    if response == 'y' || response == 'yes'
      file = create_template(name, type, scope)
      puts "Created template: #{file}"
    else
      abort "Template creation cancelled."
    end
  end

  editor = ENV["EDITOR"] || "vi"
  system "#{editor} #{file}"
end

.help(message) ⇒ void

This method returns an undefined value.

Prints a help banner

Parameters:

  • message (String, #to_s)

    a message to output



87
88
89
# File 'lib/mint/command_line.rb', line 87

def self.help(message)
  puts message
end

.install(file, name, scope = :local) ⇒ void

This method returns an undefined value.

Install the named file as a template

Parameters:

  • file (File)

    the file to install to the appropriate Mint directory

  • name (String)

    the template name to install as

  • scope (Symbol) (defaults to: :local)

    the scope at which to install



97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
# File 'lib/mint/command_line.rb', line 97

def self.install(file, name, scope = :local)
  if file.nil?
    raise "[error] No file specified for installation"
  end
  
  filename, ext = file.split "."

  template_name = name || filename
  type = Mint.css_formats.include?(ext) ? :style : :layout
  destination = Mint.template_path(template_name, scope) + "#{type}.#{ext}"
  FileUtils.mkdir_p File.dirname(destination)

  if File.exist? file
    FileUtils.cp file, destination
  else
    raise "[error] No such file: #{file}"
  end
end

.parse(argv) ⇒ Hash

Parses ARGV using OptionParser

Parameters:

  • argv (Array)

    a list of arguments to parse

Returns:

  • (Hash)

    an object that contains parsed options, remaining arguments, and a help message



14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
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
# File 'lib/mint/command_line.rb', line 14

def self.parse(argv)
  parsed_options = {}

  parser = OptionParser.new do |cli|
    cli.banner = "Usage: mint [command] files [options]"

    cli.on "-t", "--template TEMPLATE", "Specify the template (layout + style)" do |t|
      parsed_options[:layout_or_style_or_template] = [:template, t]
    end

    cli.on "-l", "--layout LAYOUT", "Specify only the layout" do |l|
      parsed_options[:layout_or_style_or_template] = [:layout, l]
    end

    cli.on "-s", "--style STYLE", "Specify only the style" do |s|
      parsed_options[:layout_or_style_or_template] = [:style, s]
    end

    cli.on "-w", "--root ROOT", "Specify a root outside the current directory" do |r|
      parsed_options[:root] = r
    end

    cli.on "-o", "--output-file FORMAT", "Specify the output file format with substitutions: \#{basename}, \#{original_extension}, \#{new_extension}" do |o|
      parsed_options[:output_file] = o
    end

    cli.on "-d", "--destination DESTINATION", "Specify a destination directory, relative to the root" do |d|
      parsed_options[:destination] = d
    end

    cli.on "--inline-style", "Inline CSS into the HTML document (default)" do
      parsed_options[:style_mode] = :inline
    end

    cli.on "--style-destination DESTINATION", "Create stylesheet at specified directory or file path and link it" do |destination|
      parsed_options[:style_mode] = :external
      parsed_options[:style_destination] = destination
    end

    cli.on "-g", "--global", "Specify config changes on a global level" do
      parsed_options[:scope] = :global
    end

    cli.on "-u", "--user", "Specify config changes on a user-wide level" do
      parsed_options[:scope] = :user
    end

    cli.on "-l", "--local", "Specify config changes on a project-specific level" do
      parsed_options[:scope] = :local
    end

    cli.on "-r", "--recursive", "Recursively find all Markdown files in subdirectories" do
      parsed_options[:recursive] = true
    end
  end

  transient_argv = argv.dup
  parser.parse! transient_argv
  
  if parsed_options[:style_mode] == :inline && parsed_options[:style_destination]
    raise ArgumentError, "--inline-style and --style-destination cannot be used together"
  end
  
  default_options = Mint.default_options.merge(destination: Dir.getwd)
  { argv: transient_argv, options: default_options.merge(parsed_options), help: parser.help }
end

.process_output_format(format_string, input_file) ⇒ String

Processes the output file format string with substitutions

Parameters:

  • format_string (String)

    the format string with #{} substitutions

  • input_file (String)

    the original input file path

Returns:

  • (String)

    the processed output file name



145
146
147
148
149
150
151
152
153
154
155
156
# File 'lib/mint/command_line.rb', line 145

def self.process_output_format(format_string, input_file)
  basename = File.basename(input_file, ".*")
  original_extension = File.extname(input_file)[1..-1] || ""
  
  # TODO: Remove hardcoded new_extension
  new_extension = "html"
  
  format_string.
    gsub('#{basename}', basename).
    gsub('#{original_extension}', original_extension).
    gsub('#{new_extension}', new_extension)
end

.publish!(files, commandline_options = {}) ⇒ void

This method returns an undefined value.

Renders and writes to file all resources described by a document. Specifically: it publishes a document, using the document’s accessors to determine file placement and naming, and then renders its style. This method will overwrite any existing content in a document’s destination files. The ‘render_style` option provides an easy way to stop Mint from rendering a style, even if the document’s style is not nil.

Parameters:

  • files (Array, #each)

    a group of filenames

  • commandline_options (Hash, #[]) (defaults to: {})

    a structured set of configuration options that will guide Mint.publish!



331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
# File 'lib/mint/command_line.rb', line 331

def self.publish!(files, commandline_options={})
  # TODO: Establish commandline defaults in one place
  # TODO: Use `commandline_options` everywhere instead of `options` and `doc_options`
  options = { root: Dir.getwd }.merge(Mint.configuration_with commandline_options)

  if commandline_options[:recursive]
    files = discover_files_recursively(files.empty? ? ["."] : files)
  end

  files.each_with_index do |file, idx|
    # Pass all files list when processing multiple files (for navigation in templates like garden)
    all_files = files.size > 1 ? files : nil
    
    Document.new(file,
      root: options[:root],
      destination: options[:destination],
      context: options[:context],
      name: options[:name],
      style_mode: options[:style_mode],
      style_destination: options[:style_destination],
      layout: options[:layout],
      style: options[:style],
      template: options[:template],
      layout_or_style_or_template: options[:layout_or_style_or_template],
      all_files: all_files
    ).publish!(:render_style => (idx == 0))
  end
end

.set(key, value, scope = :local) ⇒ void

This method returns an undefined value.

Tries to set a config option (at the specified scope) per the user’s command.

Parameters:

  • key

    the key to set

  • value

    the value to set key to

  • scope (defaults to: :local)

    the scope at which to set the configuration



290
291
292
# File 'lib/mint/command_line.rb', line 290

def self.set(key, value, scope = :local)
  configure({ key => value }, scope)
end

.templates(filter = "", scope = :local) ⇒ void

This method returns an undefined value.

List the installed templates

Parameters:

  • filter (String) (defaults to: "")

    optional filter pattern

  • scope (Symbol) (defaults to: :local)

    the scope to list templates from



130
131
132
133
134
135
136
137
138
# File 'lib/mint/command_line.rb', line 130

def self.templates(filter = "", scope = :local)
  filter = filter.to_s  # Convert nil to empty string
  Mint.templates(scope).
    grep(Regexp.new(filter)).
    sort.
    each do |template|
      puts "#{File.basename template} [#{template}]"
    end
end

.uninstall(name, scope = :local) ⇒ void

This method returns an undefined value.

Uninstall the named template

Parameters:

  • name (String)

    the name of the template to be uninstalled

  • scope (Symbol) (defaults to: :local)

    the scope from which to uninstall



121
122
123
# File 'lib/mint/command_line.rb', line 121

def self.uninstall(name, scope = :local)
  FileUtils.rm_r Mint.template_path(name, scope)
end