On Thu, Nov 15, 2012 at 05:01:50PM +0100, Jasper Lievisse Adriaanse wrote:
> Hi,
> 
> One of the things lacking in mg was support M-x make-directory, which comes
> quite handy. This diff mimics the rather silent behaviour of Emacs: there's
> basically no feedback in case creating the directory failed for whatever
> reason. Should we be more verbose about it, or just stay in line with Emacs?
Here is a slightly updated diff which uses getbufcwd() and (in line with Emacs),
returns a permission denied message, as spotted by lum@.

Index: def.h
===================================================================
RCS file: /cvs/src/usr.bin/mg/def.h,v
retrieving revision 1.129
diff -p -u -r1.129 def.h
--- def.h       6 Nov 2012 18:04:10 -0000       1.129
+++ def.h       16 Nov 2012 22:09:16 -0000
@@ -335,6 +335,7 @@ void                 dirinit(void);
 int             changedir(int, int);
 int             showcwdir(int, int);
 int             getcwdir(char *, size_t);
+int             makedir(int, int);
 
 /* dired.c */
 struct buffer  *dired_(char *);
Index: dir.c
===================================================================
RCS file: /cvs/src/usr.bin/mg/dir.c,v
retrieving revision 1.19
diff -p -u -r1.19 dir.c
--- dir.c       13 Jun 2008 20:07:40 -0000      1.19
+++ dir.c       16 Nov 2012 22:09:16 -0000
@@ -9,6 +9,8 @@
  *             Modified for MG 2a by Mic Kaczmarczik 03-Aug-1987
  */
 
+#include <sys/stat.h>
+
 #include "def.h"
 
 static char     mgcwd[NFILEN];
@@ -73,5 +75,69 @@ getcwdir(char *buf, size_t len)
        if (strlcpy(buf, mgcwd, len) >= len)
                return (FALSE);
 
+       return (TRUE);
+}
+
+/* Create the directory and it's parents. */
+/* ARGSUSED */
+int
+makedir(int f, int n)
+{
+       struct stat      sb;
+       int              finished, ishere;
+       mode_t           dir_mode, mode, oumask;
+       char             bufc[NFILEN], *path, *slash;
+
+       if (getbufcwd(bufc, sizeof(bufc)) != TRUE)
+               return (ABORT);
+       if ((path = eread("Make directory: ", bufc, NFILEN,
+           EFDEF | EFNEW | EFCR | EFFILE)) == NULL)
+               return (ABORT);
+       else if (path[0] == '\0')
+               return (FALSE);
+
+       slash = path;
+       oumask = umask(0);
+       mode = 0777 & ~oumask;
+       dir_mode = mode | S_IWUSR | S_IXUSR;
+
+       for (;;) {
+               slash += strspn(slash, "/");
+               slash += strcspn(slash, "/");
+
+               finished = (*slash == '\0');
+               *slash = '\0';
+
+               ishere = !stat(path, &sb);
+               if (!finished && ishere && S_ISDIR(sb.st_mode)) {
+                       *slash = '/';
+                       continue;
+               }
+
+               if (mkdir(path, finished ? mode : dir_mode) == 0) {
+                       if (mode > 0777 && chmod(path, mode) < 0) {
+                               umask(oumask);
+                               return (ABORT);
+                       }
+               } else {
+                       if (!ishere || !S_ISDIR(sb.st_mode)) {
+                               if (!ishere)
+                                       ewprintf("Creating directory: 
permission denied, %s", path);
+                               else
+                                       eerase();
+
+                               umask(oumask);
+                               return (FALSE);
+                       }
+               }
+
+               if (finished)
+                       break;
+
+               *slash = '/';
+       }
+
+       eerase();
+       umask(oumask);
        return (TRUE);
 }
Index: file.c
===================================================================
RCS file: /cvs/src/usr.bin/mg/file.c,v
retrieving revision 1.84
diff -p -u -r1.84 file.c
--- file.c      30 Aug 2012 21:36:48 -0000      1.84
+++ file.c      16 Nov 2012 22:09:16 -0000
@@ -258,13 +258,14 @@ readin(char *fname)
                        dp = dirname(fname);
                        if (stat(dp, &statbuf) == -1 && errno == ENOENT) {
                                /* no read-only; like emacs */
-                               ewprintf("Parent directory missing");
+                               ewprintf("Use M-x make-directory RET RET to "
+                                   "create the directory and it's parents");
                        } else if (access(dp, W_OK) == -1 && 
                            errno == EACCES) {
                                ewprintf("File not found and directory"
                                    " write-protected");
                                ro = TRUE;
-                       } 
+                       }
                }
        }
        if (ro == TRUE)
Index: funmap.c
===================================================================
RCS file: /cvs/src/usr.bin/mg/funmap.c,v
retrieving revision 1.41
diff -p -u -r1.41 funmap.c
--- funmap.c    12 Oct 2012 21:13:46 -0000      1.41
+++ funmap.c    16 Nov 2012 22:09:16 -0000
@@ -198,6 +198,7 @@ static struct funmap functnames[] = {
        {csprevfile, "cscope-prev-file",},
        {cscreatelist, "cscope-create-list-of-files-to-index",},
        {revertbuffer, "revert-buffer",},
+       {makedir, "make-directory",},
        {NULL, NULL,}
 };
 
Index: mg.1
===================================================================
RCS file: /cvs/src/usr.bin/mg/mg.1,v
retrieving revision 1.71
diff -p -u -r1.71 mg.1
--- mg.1        13 Nov 2012 22:03:44 -0000      1.71
+++ mg.1        16 Nov 2012 22:09:17 -0000
@@ -662,6 +662,8 @@ Bind a key mapping in the local (topmost
 Unbind a key mapping in the local (topmost) mode.
 .It make-backup-files
 Toggle generation of backup files.
+.It make-directory
+Prompt the user for a path or directory name which is then created.
 .It mark-whole-buffer
 Marks whole buffer as a region by putting dot at the beginning and mark
 at the end of buffer.

-- 
Cheers,
Jasper

"Stay Hungry. Stay Foolish"

  • mg: make-directory Jasper Lievisse Adriaanse
    • Re: mg: make-directory Jasper Lievisse Adriaanse

Reply via email to