Class: Morpheus::Cli::DotFile

Inherits:
Object
  • Object
show all
Includes:
Term::ANSIColor
Defined in:
lib/morpheus/cli/dot_file.rb

Constant Summary collapse

EXPORTED_ALIASES_HEADER =
"# exported aliases"

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(fn) ⇒ DotFile

attr_reader :file_contents attr_reader :commands attr_reader :cmd_results



29
30
31
32
# File 'lib/morpheus/cli/dot_file.rb', line 29

def initialize(fn)
  @filename = fn
  #load_file()
end

Instance Attribute Details

#filenameObject (readonly)

Returns the value of attribute filename.



24
25
26
# File 'lib/morpheus/cli/dot_file.rb', line 24

def filename
  @filename
end

Class Method Details

.morpheus_profile_filenameObject

the path of the profile source file this is executed when ‘morpheus` is run



14
15
16
# File 'lib/morpheus/cli/dot_file.rb', line 14

def self.morpheus_profile_filename
  File.join(Morpheus::Cli.home_directory, ".morpheus_profile")
end

.morpheusrc_filenameObject

the path of the shell source file this is executed when ‘morpheus shell` is run



20
21
22
# File 'lib/morpheus/cli/dot_file.rb', line 20

def self.morpheusrc_filename
  File.join(Morpheus::Cli.home_directory, ".morpheusrc")
end

Instance Method Details

#execute(stop_on_failure = false, &block) ⇒ Array

execute this file as a morpheus shell script

Parameters:

  • stop_on_failure (true, false) (defaults to: false)

    the will halt execution if a command returns false. Default is false, keep going…

Returns:

  • (Array)

    exit codes of all the commands that were run.



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
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
# File 'lib/morpheus/cli/dot_file.rb', line 40

def execute(stop_on_failure=false, &block)
  if !File.exists?(@filename)
    print "#{Term::ANSIColor.red}source file not found: #{@filename}#{Term::ANSIColor.reset}\n" # if Morpheus::Logging.debug?
  else
    Morpheus::Logging::DarkPrinter.puts "executing source file #{@filename}" if Morpheus::Logging.debug?
  end
  file_contents = File.read(@filename)
  lines = file_contents.split("\n")
  cmd_results = []
  line_num = 0
  lines.each_with_index do |line, line_index|
    line_num = line_index + 1
    line = line.strip
    next if line.empty?
    next if line =~ /^\#/ # skip comments
    
    # print "#{dark} #=> executing source file line #{line_num}: #{line}#{reset}\n" if Morpheus::Logging.debug?

    # allow semicolons inside arguments too..
    #command_list = line.strip.split(';').compact
    command_list = line.split(/(;)(?=(?:[^"']|["|'][^"']*")*$)/).reject {|it| it.to_s.strip.empty? || it.to_s.strip == ";" }
    command_list.each do |input|
      input = input.strip
      if input.empty?
        next
      end
      argv = nil
      begin
        argv = Shellwords.shellsplit(input)
      rescue => err
        cmd_result = false
        puts "#{red} Unparsable source file: #{@filename} line: #{line_num} '#{input}' #{reset} - #{err}"
      end
      if argv[0] && Morpheus::Cli::CliRegistry.has_command?(argv[0]) || Morpheus::Cli::CliRegistry.has_alias?(argv[0])
        #log_history_command(input)
        cmd_result = nil
        begin
          cmd_result = Morpheus::Cli::CliRegistry.exec(argv[0], argv[1..-1])
        rescue SystemExit => err
          if err.success?
            cmd_result = true
          else
            puts "#{red} source file: #{@filename} line: #{line_num} command: #{argv[0]}#{reset} error: exited non zero - #{err}"
            cmd_result = false
          end
        rescue => err
          # raise err
          puts "#{red} source file: #{@filename} line: #{line_num} command: #{argv[0]}#{reset} error: unexpected error - #{err}"
          cmd_result = false
        end
        cmd_results << cmd_result
        # next command please!
      else
        puts "#{red}Unrecognized source command file: #{@filename} line: #{line_num} command: #{argv[0]}#{reset}"
        cmd_result = false
      end
      if cmd_result == false
        if stop_on_failure
          return cmd_results
        end
      end
    end

  end
  return cmd_results
end

#export_aliases(alias_definitions) ⇒ Object

this saves the source file, upserting alias definitions at the bottom todo: smarter logic to allow the user to put stuff AFTER this section too under the section titled ‘# exported aliases’

Parameters:

  • alias_definitions (Map)

    Map of alias_name => command_string

Returns:

  • nil



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
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
# File 'lib/morpheus/cli/dot_file.rb', line 112

def export_aliases(alias_definitions)
  if !@filename
    print "#{Term::ANSIColor.dark}Skipping source file save because filename has not been set#{Term::ANSIColor.reset}\n" if Morpheus::Logging.debug?
    return false
  end
  if !Dir.exists?(File.dirname(@filename))
    FileUtils.mkdir_p(File.dirname(@filename))
  end
  if !File.exists?(@filename)
    print "#{Term::ANSIColor.dark}Initializing source file #{@filename}#{Term::ANSIColor.reset}\n" if Morpheus::Logging.debug?
    FileUtils.touch(@filename)
  else
    print "#{dark} #=> Saving source file #{@filename}#{reset}\n" if Morpheus::Logging.debug?
  end


  config_text = File.read(@filename)
  config_lines = config_text.split(/\n/)
  new_config_lines = []
  existing_alias_definitions = {}
  header_line_index = config_lines.index {|line| line.strip.include?(EXPORTED_ALIASES_HEADER) }
  if header_line_index
    # keep everything before the exported alias section
    new_config_lines = config_lines[0..header_line_index-1]
    existing_alias_lines = config_lines[header_line_index..config_lines.size-1]
    # parse out the existing alias definitions
    existing_alias_lines.each do |line|
      if line =~ /^alias\s+/
        alias_name, command_string = Morpheus::Cli::CliRegistry.parse_alias_definition(line)
        if alias_name.empty? || command_string.empty?
          print "#{dark} #=> removing bad config line #{line_num} invalid alias definition: #{line}\n" if Morpheus::Logging.debug?
        else
          existing_alias_definitions[alias_name] = command_string
        end
      end
    end
  else
    new_config_lines = config_lines
    new_config_lines << "" # blank line before alias header
  end

  # append header line
  new_config_lines << EXPORTED_ALIASES_HEADER
  new_config_lines << "# Do not put anything below here, or it will be lost when aliases are exported"
  #new_config_lines << ""

  # update aliases, sort them, and append the lines
  new_alias_definitions = existing_alias_definitions.merge(alias_definitions)
  new_alias_definitions.keys.sort.each do |alias_name|
    new_config_lines << "alias #{alias_name}='#{new_alias_definitions[alias_name]}'"
  end
  
  # include a blank line after this section
  new_config_lines << ""
  new_config_lines << ""

  new_config_text = new_config_lines.join("\n")
  
  File.open(@filename, 'w') {|f| f.write(new_config_text) }
  return true
end

#remove_aliases(alias_names) ⇒ Object

this saves the source file, removing alias definitions at the bottom todo: smarter logic to allow the user to put stuff AFTER this section too under the section titled ‘# exported aliases’

Parameters:

  • alias_definitions (Map)

    Map of alias_name => command_string

Returns:

  • nil



179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
# File 'lib/morpheus/cli/dot_file.rb', line 179

def remove_aliases(alias_names)
  if !@filename
    print "#{Term::ANSIColor.dark}Skipping source file save because filename has not been set#{Term::ANSIColor.reset}\n" if Morpheus::Logging.debug?
    return false
  end
  if !Dir.exists?(File.dirname(@filename))
    FileUtils.mkdir_p(File.dirname(@filename))
  end
  if !File.exists?(@filename)
    print "#{Term::ANSIColor.dark}Initializing source file #{@filename}#{Term::ANSIColor.reset}\n" if Morpheus::Logging.debug?
    FileUtils.touch(@filename)
  else
    print "#{dark} #=> Saving source file #{@filename}#{reset}\n" if Morpheus::Logging.debug?
  end


  config_text = File.read(@filename)
  config_lines = config_text.split(/\n/)
  
  new_config_lines = config_lines.reject {|line|
    alias_names.find {|alias_name| /^alias\s+#{Regexp.escape(alias_name)}\s?\=/ }
  }
  
  new_config_text = new_config_lines.join("\n")
  
  File.open(@filename, 'w') {|f| f.write(new_config_text) }
  return true
end