Feature #643
closed__DIR__
Added by trans (Thomas Sawyer) about 16 years ago. Updated over 13 years ago.
Description
=begin
There is an snippet of code found in many Ruby scripts, especially testing scripts. It is...
File.dirname(FILE)
For something so common --and something that can not, by its very nature, be put into a reusable method, it is annoying to have to repeatedly calculate the current scripts location. So I respectfully request that a future version of Ruby provide a built-in reference that can be used instead:
DIR
This will improve readability, remove the need for extra variables to store this information, and at the very least, save us a good many keystrokes.
=end
Updated by zenspider (Ryan Davis) about 16 years ago
=begin
On Oct 13, 2008, at 11:27 , Thomas Sawyer wrote:
DIR
This will improve readability, remove the need for extra variables
to store this information, and at the very least, save us a good
many keystrokes.
yes.
I frequently need to do:
File.dirname(File.dirname(__FILE__))
so I'd like
__DIRDIR__
can we also have
__DIRDIRDIR__
while you're in there?
=end
Updated by pragdave (Dave Thomas) about 16 years ago
=begin
On Oct 13, 2008, at 4:51 PM, Phil Hagelberg wrote:
If we don't want to add another toplevel constant, another way to
handle
this gracefully would be to have the default argument for File.dirname
be the caller's FILE. At least 90% of the File.dirname invocations
that I write have FILE as their argument, so this would remove a
good deal of redundancy.
But with relative_require, suddenly most of those use cases evaporate,
no?
Dave
=end
Updated by duerst (Martin Dürst) about 16 years ago
=begin
Just some alternatives for everybody. What about
DIR__DIR__DIR instead of DIRDIRDIR?
Seems easier to count the levels. For those who
want to type less, maybe we can choose
DIR_DIR_DIR as a compromize?
Anyway, I think one problem with using File.dirname,
in particular repeatedly, is that it's rather long.
And the reason it's long is that it's not really
object-oriented.
So we should work towards something like FILE.dir.dir.dir,
which is easier to read and much shorter.
Regards, Martin.
At 04:08 08/10/14, Ryan Davis wrote:
On Oct 13, 2008, at 11:27 , Thomas Sawyer wrote:
DIR
This will improve readability, remove the need for extra variables
to store this information, and at the very least, save us a good
many keystrokes.yes.
I frequently need to do:
File.dirname(File.dirname(FILE))
so I'd like
DIRDIR
can we also have
DIRDIRDIR
while you're in there?
#-#-# Martin J. Du"rst, Assoc. Professor, Aoyama Gakuin University
#-#-# http://www.sw.it.aoyama.ac.jp mailto:duerst@it.aoyama.ac.jp
=end
Updated by nobu (Nobuyoshi Nakada) about 16 years ago
=begin
Hi,
At Tue, 14 Oct 2008 04:20:18 +0900,
Nikolai Weibull wrote in [ruby-core:19319]:
I realize that I'm responding to a joke, but wouldn't it perhaps be
nice if File.dirname took an optional second argument that allowed you
to specify how many levels up you want to go?
I like this idea too.
I actually implemented this at work, simply because I was doing a lot
of nested File.dirname calls.
This is my patch.
Index: file.c
--- file.c (revision 19773)
+++ file.c (working copy)
@@ -2523,4 +2523,32 @@ rb_path_last_separator(const char *path)
static char *
+path_last_nth_separator(const char *pstart, const char *pend, int nth)
+{
- enum {lastmax = 16};
- char *lastbuf[lastmax];
- if (nth <= 0) return (char *)pend;
- do {
- int lastidx = 0;
- const char *path = pstart;
- while (path < pend && *path) {
-
if (isdirsep(*path)) {
-
const char *tmp = path++;
-
while (isdirsep(*path)) path++;
-
if (!*path) break;
-
lastbuf[lastidx++ % lastmax] = (char *)tmp;
-
}
-
else {
-
path = CharNext(path);
-
}
- }
- if (lastidx < nth) return NULL;
- if (nth <= lastmax) return lastbuf[(lastidx - nth) % lastmax];
- pend = lastbuf[lastidx % lastmax];
- } while ((nth -= lastmax) > 0);
- return (char *)pend;
+}
+static char *
chompdirsep(const char *path)
{
@@ -3060,4 +3088,6 @@ rb_file_s_basename(int argc, VALUE *argv
}
+static VALUE rb_file_dirname(VALUE fname, int nth);
+
/*
- call-seq:
@@ -3073,11 +3103,22 @@ rb_file_s_basename(int argc, VALUE *argv
static VALUE
-rb_file_s_dirname(VALUE klass, VALUE fname)
+rb_file_s_dirname(int argc, VALUE *argv, VALUE klass)
+{
- VALUE fname, level;
- int nth;
- rb_scan_args(argc, argv, "11", &fname, &level);
- nth = NUM2INT(level);
- FilePathStringValue(fname);
- return rb_file_dirname(fname, nth);
+}
+static VALUE
+rb_file_dirname(VALUE fname, int nth)
{
const char *name, *root, *p;
VALUE dirname;
- FilePathStringValue(fname);
- name = StringValueCStr(fname);
- name = RSTRING_PTR(fname);
root = skiproot(name);
#ifdef DOSISH_UNC
@@ -3088,5 +3129,21 @@ rb_file_s_dirname(VALUE klass, VALUE fna
name = root - 1;
#endif
- p = strrdirsep(root);
- if (nth < 0) {
- const char *tmp = p = root;
- while (++nth < 0) {
-
while (isdirsep(*tmp)) tmp++;
-
if (!(tmp = nextdirsep(p = tmp))) break;
-
p = tmp;
- }
- }
- else if (nth == 0) {
- p = chompdirsep(root);
- }
- else if (nth == 1) {
- p = strrdirsep(root);
- }
- else {
- p = path_last_nth_separator(root, name + RSTRING_LEN(fname), nth);
- }
if (!p) {
p = root;
@@ -3209,5 +3266,5 @@ rb_file_s_split(VALUE klass, VALUE path)
{
FilePathStringValue(path); /* get rid of converting twice */
- return rb_assoc_new(rb_file_s_dirname(Qnil, path), rb_file_s_basename(1,&path));
- return rb_assoc_new(rb_file_dirname(path, 1), rb_file_s_basename(1,&path));
}
@@ -4709,5 +4766,5 @@ Init_File(void)
rb_define_singleton_method(rb_cFile, "absolute_path", rb_file_s_absolute_path, -1);
rb_define_singleton_method(rb_cFile, "basename", rb_file_s_basename, -1);
- rb_define_singleton_method(rb_cFile, "dirname", rb_file_s_dirname, 1);
- rb_define_singleton_method(rb_cFile, "dirname", rb_file_s_dirname, -1);
rb_define_singleton_method(rb_cFile, "extname", rb_file_s_extname, 1);
rb_define_singleton_method(rb_cFile, "path", rb_file_s_path, 1);
--
Nobu Nakada
=end
Updated by trans (Thomas Sawyer) about 16 years ago
=begin
On Oct 13, 6:02 pm, Dave Thomas d...@pragprog.com wrote:
On Oct 13, 2008, at 4:51 PM, Phil Hagelberg wrote:
If we don't want to add another toplevel constant, another way to
handle
this gracefully would be to have the default argument for File.dirname
be the caller's FILE. At least 90% of the File.dirname invocations
that I write have FILE as their argument, so this would remove a
good deal of redundancy.But with relative_require, suddenly most of those use cases evaporate,
no?
Pretty much, but it would take a #relative_load and a
File.relative_read to really cover all common uses. But there are
always those outlay cases too. The thing about DIR is that it is
generally useful for all cases, whereas #relative_require has a single
specific use.
T.
=end
Updated by trans (Thomas Sawyer) about 16 years ago
=begin
On Oct 13, 3:08 pm, Ryan Davis ryand-r...@zenspider.com wrote:
On Oct 13, 2008, at 11:27 , Thomas Sawyer wrote:
DIR
This will improve readability, remove the need for extra variables
to store this information, and at the very least, save us a good
many keystrokes.yes.
I frequently need to do:
File.dirname(File.dirname(FILE))
so I'd like
DIRDIR
can we also have
DIRDIRDIR
while you're in there?
It's one thing to be sarcastic, it is another to be untruthful. If you
are actually using File.dirname(File.dirname(FILE)) "frequently",
then you need to rethink your design. But I know you are a better
coder than that. So you're simply not being sincere, and thus not
making a valid point.
T.
=end
Updated by trans (Thomas Sawyer) about 16 years ago
=begin
On Oct 15, 11:00 am, Aaron Patterson aa...@tenderlovemaking.com
wrote:
Yes Ryan. Please stop the lies. It hurts us all.
I did not say Ryan lied. I said he was being insincere in his response
to my suggestion.
Unfortunately, via your blog (http://tenderlovemaking.com/) I came
upon Ryan's lovely post:
http://blog.zenspider.com/2008/10/ranty-mcrantalots-reply-to-a-d.html
In which he does lie, and slanders and otherwise exhibits deplorable
behavior.
It's no wonder Zed Shaw left as he did. If this is what an influential
portion of the Ruby community has boiled down to --a clique of
miscreant bullies, I wouldn't be surprised if more follow suite.
T.
=end
Updated by ko1 (Koichi Sasada) about 16 years ago
- Assignee set to matz (Yukihiro Matsumoto)
=begin
=end