opal/corelib/file.rb
# helpers: truthy
# backtick_javascript: true
class ::File < ::IO
Separator = SEPARATOR = '/'
ALT_SEPARATOR = nil
PATH_SEPARATOR = ':'
# Assuming case insenstive filesystem
FNM_SYSCASE = 0
windows_root_rx = %r{^[a-zA-Z]:(?:\\|\/)}
class << self
def absolute_path(path, basedir = nil)
sep = SEPARATOR
sep_chars = `$sep_chars()`
new_parts = []
path = path.respond_to?(:to_path) ? path.to_path : path
path = ::Opal.coerce_to!(`path`, ::String, :to_str)
basedir ||= ::Dir.pwd
path_abs = `path.substr(0, sep.length) === sep || windows_root_rx.test(path)`
basedir_abs = `basedir.substr(0, sep.length) === sep || windows_root_rx.test(basedir)`
if path_abs
parts = path.split(/[#{sep_chars}]/)
leading_sep = `windows_root_rx.test(path) ? '' : #{path.sub(/^([#{sep_chars}]+).*$/, '\1')}`
abs = true
else
parts = basedir.split(/[#{sep_chars}]/) + path.split(/[#{sep_chars}]/)
leading_sep = `windows_root_rx.test(basedir) ? '' : #{basedir.sub(/^([#{sep_chars}]+).*$/, '\1')}`
abs = basedir_abs
end
%x{
var part;
for (var i = 0, ii = parts.length; i < ii; i++) {
part = parts[i];
if (
(part === nil) ||
(part === '' && ((new_parts.length === 0) || abs)) ||
(part === '.' && ((new_parts.length === 0) || abs))
) {
continue;
}
if (part === '..') {
new_parts.pop();
} else {
new_parts.push(part);
}
}
if (!abs && parts[0] !== '.') {
#{new_parts.unshift '.'}
}
}
new_path = new_parts.join(sep)
new_path = leading_sep + new_path if abs
new_path
end
def expand_path(path, basedir = nil)
sep = SEPARATOR
sep_chars = `$sep_chars()`
if `path[0] === '~' || (basedir && basedir[0] === '~')`
home = Dir.home
::Kernel.raise(::ArgumentError, "couldn't find HOME environment -- expanding `~'") unless home
leading_sep = `windows_root_rx.test(home) ? '' : #{home.sub(/^([#{sep_chars}]+).*$/, '\1')}`
::Kernel.raise(::ArgumentError, 'non-absolute home') unless home.start_with?(leading_sep)
home += sep
home_path_regexp = /^\~(?:#{sep}|$)/
path = path.sub(home_path_regexp, home)
basedir = basedir.sub(home_path_regexp, home) if basedir
end
absolute_path(path, basedir)
end
%x{
// Coerce a given path to a path string using #to_path and #to_str
function $coerce_to_path(path) {
if ($truthy(#{`path`.respond_to?(:to_path)})) {
path = path.$to_path();
}
path = #{::Opal.coerce_to!(`path`, ::String, :to_str)};
return path;
}
// Return a RegExp compatible char class
function $sep_chars() {
if (#{ALT_SEPARATOR} === nil) {
return Opal.escape_regexp(#{SEPARATOR});
} else {
return Opal.escape_regexp(#{SEPARATOR + ALT_SEPARATOR});
}
}
}
def dirname(path, level = 1)
return path if level == 0
::Kernel.raise ::ArgumentError, "level can't be negative" if level < 0
sep_chars = `$sep_chars()`
path = `$coerce_to_path(path)`
%x{
var absolute = path.match(new RegExp(#{"^[#{sep_chars}]"})), out;
path = path.replace(new RegExp(#{"[#{sep_chars}]+$"}), ''); // remove trailing separators
path = path.replace(new RegExp(#{"[^#{sep_chars}]+$"}), ''); // remove trailing basename
path = path.replace(new RegExp(#{"[#{sep_chars}]+$"}), ''); // remove final trailing separators
if (path === '') {
out = absolute ? '/' : '.';
}
else {
out = path;
}
if (level == 1) {
return out;
}
else {
return #{dirname(`out`, level - 1)}
}
}
end
def basename(name, suffix = nil)
sep_chars = `$sep_chars()`
name = `$coerce_to_path(name)`
%x{
if (name.length == 0) {
return name;
}
if (suffix !== nil) {
suffix = #{::Opal.coerce_to!(suffix, ::String, :to_str)}
} else {
suffix = null;
}
name = name.replace(new RegExp(#{"(.)[#{sep_chars}]*$"}), '$1');
name = name.replace(new RegExp(#{"^(?:.*[#{sep_chars}])?([^#{sep_chars}]+)$"}), '$1');
if (suffix === ".*") {
name = name.replace(/\.[^\.]+$/, '');
} else if(suffix !== null) {
suffix = Opal.escape_regexp(suffix);
name = name.replace(new RegExp(#{"#{suffix}$"}), '');
}
return name;
}
end
def extname(path)
`path = $coerce_to_path(path)`
filename = basename(path)
return '' if filename.empty?
last_dot_idx = filename[1..-1].rindex('.')
# extension name must contains at least one character .(something)
last_dot_idx.nil? || last_dot_idx + 1 == filename.length - 1 ? '' : filename[(last_dot_idx + 1)..-1]
end
def exist?(path)
`Opal.modules[#{path}] != null`
end
def directory?(path)
files = []
%x{
for (var key in Opal.modules) {
#{files}.push(key)
}
}
path = path.gsub(/(^.#{SEPARATOR}+|#{SEPARATOR}+$)/)
file = files.find { |f| f =~ /^#{path}/ }
file
end
def join(*paths)
if paths.empty?
return ''
end
result = ''
paths = paths.flatten.each_with_index.map do |item, index|
if index == 0 && item.empty?
SEPARATOR
elsif paths.length == index + 1 && item.empty?
SEPARATOR
else
item
end
end
paths = paths.reject(&:empty?)
paths.each_with_index do |item, index|
next_item = paths[index + 1]
if next_item.nil?
result = "#{result}#{item}"
else
if item.end_with?(SEPARATOR) && next_item.start_with?(SEPARATOR)
item = item.sub(/#{SEPARATOR}+$/, '')
end
result = if item.end_with?(SEPARATOR) || next_item.start_with?(SEPARATOR)
"#{result}#{item}"
else
"#{result}#{item}#{SEPARATOR}"
end
end
end
result
end
def split(path)
path.split(SEPARATOR)
end
alias realpath expand_path
alias exists? exist?
end
end