/usr/lib/ruby/vendor_ruby/sass/exec/base.rb is in ruby-sass 3.4.6-2.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 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 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 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 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 | require 'optparse'
module Sass::Exec
# The abstract base class for Sass executables.
class Base
# @param args [Array<String>] The command-line arguments
def initialize(args)
@args = args
@options = {}
end
# Parses the command-line arguments and runs the executable.
# Calls `Kernel#exit` at the end, so it never returns.
#
# @see #parse
def parse!
# rubocop:disable RescueException
begin
parse
rescue Exception => e
# Exit code 65 indicates invalid data per
# http://www.freebsd.org/cgi/man.cgi?query=sysexits. Setting it via
# at_exit is a bit of a hack, but it allows us to rethrow when --trace
# is active and get both the built-in exception formatting and the
# correct exit code.
at_exit {exit 65} if e.is_a?(Sass::SyntaxError)
raise e if @options[:trace] || e.is_a?(SystemExit)
if e.is_a?(Sass::SyntaxError)
$stderr.puts e.sass_backtrace_str("standard input")
else
$stderr.print "#{e.class}: " unless e.class == RuntimeError
$stderr.puts e.message.to_s
end
$stderr.puts " Use --trace for backtrace."
exit 1
end
exit 0
# rubocop:enable RescueException
end
# Parses the command-line arguments and runs the executable.
# This does not handle exceptions or exit the program.
#
# @see #parse!
def parse
@opts = OptionParser.new(&method(:set_opts))
@opts.parse!(@args)
process_result
@options
end
# @return [String] A description of the executable
def to_s
@opts.to_s
end
protected
# Finds the line of the source template
# on which an exception was raised.
#
# @param exception [Exception] The exception
# @return [String] The line number
def get_line(exception)
# SyntaxErrors have weird line reporting
# when there's trailing whitespace
if exception.is_a?(::SyntaxError)
return (exception.message.scan(/:(\d+)/).first || ["??"]).first
end
(exception.backtrace[0].scan(/:(\d+)/).first || ["??"]).first
end
# Tells optparse how to parse the arguments
# available for all executables.
#
# This is meant to be overridden by subclasses
# so they can add their own options.
#
# @param opts [OptionParser]
def set_opts(opts)
Sass::Util.abstract(this)
end
# Set an option for specifying `Encoding.default_external`.
#
# @param opts [OptionParser]
def encoding_option(opts)
encoding_desc = if Sass::Util.ruby1_8?
'Does not work in Ruby 1.8.'
else
'Specify the default encoding for input files.'
end
opts.on('-E', '--default-encoding ENCODING', encoding_desc) do |encoding|
if Sass::Util.ruby1_8?
$stderr.puts "Specifying the encoding is not supported in ruby 1.8."
exit 1
else
Encoding.default_external = encoding
end
end
end
# Processes the options set by the command-line arguments. In particular,
# sets `@options[:input]` and `@options[:output]` to appropriate IO streams.
#
# This is meant to be overridden by subclasses
# so they can run their respective programs.
def process_result
input, output = @options[:input], @options[:output]
args = @args.dup
input ||=
begin
filename = args.shift
@options[:filename] = filename
open_file(filename) || $stdin
end
@options[:output_filename] = args.shift
output ||= @options[:output_filename] || $stdout
@options[:input], @options[:output] = input, output
end
COLORS = {:red => 31, :green => 32, :yellow => 33}
# Prints a status message about performing the given action,
# colored using the given color (via terminal escapes) if possible.
#
# @param name [#to_s] A short name for the action being performed.
# Shouldn't be longer than 11 characters.
# @param color [Symbol] The name of the color to use for this action.
# Can be `:red`, `:green`, or `:yellow`.
def puts_action(name, color, arg)
return if @options[:for_engine][:quiet]
printf color(color, "%11s %s\n"), name, arg
STDOUT.flush
end
# Same as `Kernel.puts`, but doesn't print anything if the `--quiet` option is set.
#
# @param args [Array] Passed on to `Kernel.puts`
def puts(*args)
return if @options[:for_engine][:quiet]
Kernel.puts(*args)
end
# Wraps the given string in terminal escapes
# causing it to have the given color.
# If terminal esapes aren't supported on this platform,
# just returns the string instead.
#
# @param color [Symbol] The name of the color to use.
# Can be `:red`, `:green`, or `:yellow`.
# @param str [String] The string to wrap in the given color.
# @return [String] The wrapped string.
def color(color, str)
raise "[BUG] Unrecognized color #{color}" unless COLORS[color]
# Almost any real Unix terminal will support color,
# so we just filter for Windows terms (which don't set TERM)
# and not-real terminals, which aren't ttys.
return str if ENV["TERM"].nil? || ENV["TERM"].empty? || !STDOUT.tty?
"\e[#{COLORS[color]}m#{str}\e[0m"
end
def write_output(text, destination)
if destination.is_a?(String)
open_file(destination, 'w') {|file| file.write(text)}
else
destination.write(text)
end
end
private
def open_file(filename, flag = 'r')
return if filename.nil?
flag = 'wb' if @options[:unix_newlines] && flag == 'w'
file = File.open(filename, flag)
return file unless block_given?
yield file
file.close
end
def handle_load_error(err)
dep = err.message[/^no such file to load -- (.*)/, 1]
raise err if @options[:trace] || dep.nil? || dep.empty?
$stderr.puts <<MESSAGE
Required dependency #{dep} not found!
Run "gem install #{dep}" to get it.
Use --trace for backtrace.
MESSAGE
exit 1
end
end
end
|