Feature #643

__DIR__

Added by Thomas Sawyer over 6 years ago. Updated about 4 years ago.

[ruby-core:19315]
Status:Rejected
Priority:Normal
Assignee:Yukihiro Matsumoto

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

History

#1 Updated by Ryan Davis over 6 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

#2 Updated by Dave Thomas over 6 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

#3 Updated by Martin Dürst over 6 years ago

=begin
Just some alternatives for everybody. What about
DIRDIR_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

#4 Updated by Nobuyoshi Nakada over 6 years ago

=begin
Hi,

At Tue, 14 Oct 2008 04:20:18 +0900,
Nikolai Weibull wrote in :

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

#5 Updated by Thomas Sawyer over 6 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

#6 Updated by Thomas Sawyer over 6 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

#7 Updated by Thomas Sawyer over 6 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

#8 Updated by Koichi Sasada over 6 years ago

  • Assignee set to Yukihiro Matsumoto

=begin

=end

#9 Updated by Yuki Sonoda over 6 years ago

  • Target version set to 2.0.0

=begin

=end

#10 Updated by Yui NARUSE over 5 years ago

  • Status changed from Open to Rejected

=begin

=end

Also available in: Atom PDF