]> git.mdlowis.com Git - projs/tide.git/commitdiff
moved ctags project file detection logic from edit shell script into xedit binary.
authorMichael D. Lowis <mike@mdlowis.com>
Fri, 26 May 2017 22:33:51 +0000 (18:33 -0400)
committerMichael D. Lowis <mike@mdlowis.com>
Fri, 26 May 2017 22:33:51 +0000 (18:33 -0400)
TODO.md
docs/edit.1
docs/edit.1.md
docs/xedit.1
docs/xedit.1.md
edit
inc/edit.h
lib/utils.c
xedit.c

diff --git a/TODO.md b/TODO.md
index 94990bb15572ecb97d2eba17848d81b42813f3f2..000d7ce48dc69bcd9888b1165939eb8f28ec1051 100644 (file)
--- a/TODO.md
+++ b/TODO.md
@@ -2,25 +2,21 @@
 
 Up Next:
 
+* rename to tide
+* Change PageUp/Dn to move cursor by screenfuls
+* Add Ctrl+Shift+A shortcut to select all
 * ctrl+d with no selection does word selection instead of context
-* get rid of edit wrapper script
 * move by words is inconsistent. Example:
     var infoId = 'readerinfo'+reader.id;
-* rename to tide
-
-* Add a way to CD using a builtin
-* Ctrl+PageUp/Dn to move cursor by screenfuls
-* Ctrl+\ Shortcut to warp cursor to middle of current screen.
-* Find shortcut should select previous word if current char is newline
-* diagnostic messages can stack up if deselected and not resolved
-* highlight all matches of search term
+* Add a way to CD using a builtin (buffers will track original dir)
 * Ctrl+Shift+Enter copies indent of wrong line
-* jump to previous or next line with less indent
 * Shift+Insert should insert primary selection
 
 The Future:
 
+* highlight all matches of search term
 * Make Fn keys execute nth command in the tags buffers
+* jump to previous or next line with less indent
 * use transaction ids to only mark buffer dirty when it really is
 * refactor selection handling to buf.c to prepare for multiple selections.
 * 100% coverage with unit and unit-integration tests
@@ -33,6 +29,12 @@ The Future:
 * implement command diffing logic to optimize the undo/redo log
 * Status line should omit characters from beginning of path to make file path fit
 
+Maybe think about addressing these later:
+
+* Find shortcut should select previous word if current char is newline
+* Ctrl+\ Shortcut to warp cursor to middle of current screen.
+* diagnostic messages can stack up if deselected and not resolved
+
 # Auxillary Programs
 
 * Visual diff tool
index 9c17e58a42382da5c7ef823f6c6fd1dc11104dfd..6fd2d6704ca69342c2fe8d467e1f92aa9fa2ea61 100644 (file)
@@ -1,7 +1,7 @@
 .\" generated with Ronn/v0.7.3
 .\" http://github.com/rtomayko/ronn/tree/0.7.3
 .
-.TH "EDIT" "1" "March 2017" "" ""
+.TH "EDIT" "1" "May 2017" "" ""
 .
 .SH "NAME"
 \fBedit\fR \- convenience script for launching xedit(1) with a proper environment
@@ -10,7 +10,7 @@
 \fBedit\fR [\fIfile\fR\.\.\.]
 .
 .SH "DESCRIPTION"
-This script acts as a wrapper around xedit(1)\. It is responsible for setting up the environment variables and loading the rc file xedit(1) before launching a new instance of xedit(1) for each file provided on the command line\. If no files are provided, xedit(1) will be launched to edit a scratch buffer\.
+This script acts as a wrapper around xedit(1)\. It is responsible for setting up the environment variables and loading the rc file before launching a new instance of xedit(1) to edit the given files\. If no files are provided a new instance of xedit(1) will be launched with an empty edit buffer\.
 .
 .SH "FILES"
 .
index abec4e72a8fd81af3b4b84c58543ad9be2c5f129..f14df3a5036b066ecd0a339ff0ee09890b19448a 100644 (file)
@@ -7,39 +7,39 @@
 ## DESCRIPTION
 
 This script acts as a wrapper around xedit(1). It is responsible for setting up
-the environment variables and loading the rc file xedit(1) before launching a 
-new instance of xedit(1) for each file provided on the command line. If no files
-are provided, xedit(1) will be launched to edit a scratch buffer.
+the environment variables and loading the rc file before launching a
+new instance of xedit(1) to edit the given files. If no files are provided a new
+instance of xedit(1) will be launched with an empty edit buffer.
 
 ## FILES
 
 * `$HOME/.config/edit/editrc`:
-    Shell script loaded in current environment to make shell functions and 
+    Shell script loaded in current environment to make shell functions and
     environment variables available to xedit(1)
 
 ## ENVIRONMENT
-    
+
 * `BASH_ENV`:
-    Set to same value as $EDITRCFILE so that the file is loaded as a bash script 
+    Set to same value as $EDITRCFILE so that the file is loaded as a bash script
     in the event that the user shell is bash(1)
 
 * `DISPLAY`:
-    This variable is used to determine if we are running in an X11 environment. 
-    If $DISPLAY is not set then the contents of the $EDITOR variable is used to 
-    determine what editor to launch in lieu of xedit(1). If $EDITOR is not set 
+    This variable is used to determine if we are running in an X11 environment.
+    If $DISPLAY is not set then the contents of the $EDITOR variable is used to
+    determine what editor to launch in lieu of xedit(1). If $EDITOR is not set
     then vim(1) is launched instead.
-    
+
 * `EDITRCFILE`:
-    Contains the path of the shell script which is loaded before xedit(1) to 
-    setup the environment and define shell functions which can be called during 
+    Contains the path of the shell script which is loaded before xedit(1) to
+    setup the environment and define shell functions which can be called during
     an editing session.
 
 * `EDITOR`:
-    Used as a fallback for when not running in an X11 system (xedit(1) is of 
+    Used as a fallback for when not running in an X11 system (xedit(1) is of
     course X11 only).
 
 * `PATH`:
-    The $PATH variable is modified in order to add $HOME/config/edit/tools/ to 
+    The $PATH variable is modified in order to add $HOME/config/edit/tools/ to
     the path. This folder is a standard location in which user scripts and tools
     can be placed so they can be used from within xedit(1) without cluttering up
     the normal system path.
index 32ae155d7e0f08892ef5c915c04195f7d1b1ee91..bc2cd56953d470663bf87998d4c6e78a507c2fa6 100644 (file)
@@ -7,7 +7,7 @@
 \fBxedit\fR \- a text editor inspired by acme(1) from Plan 9 and Inferno
 .
 .SH "SYNOPSIS"
-\fBxedit\fR [\fIfile\fR]
+\fBxedit\fR [\fIfile\fR\.\.\.]
 .
 .SH "DESCRIPTION"
 \fBxedit\fR is a text editor inspired by the Acme editor from the Plan 9 and Inferno operating systems\. Unlike Acme, \fBxedit\fR is a single window, single file editor\. Instead of baking a window manager into the editor, this job is relegated to an X11 window manager\. It is recommended that \fBxedit\fR be used with a tiling window manager such as dwm(1) or spectrwm(1)\. These window managers will make dealing with multiple windows much easier and more efficient\.
index 65c2007b11ddbb2f8f714e16c5d58d2e28c22cbd..e24c0cd252d28c5599579553dca0d5f39a639e08 100644 (file)
@@ -2,7 +2,7 @@
 
 ## SYNOPSIS
 
-`xedit` [_file_]
+`xedit` [_file_...]
 
 ## DESCRIPTION
 
diff --git a/edit b/edit
index 2ce5ba5c683033c52dd30db38c97614d9895e369..42ae479d28d3ee41309f5f00bf0b0daa37875646 100755 (executable)
--- a/edit
+++ b/edit
@@ -1,41 +1,5 @@
 #!/bin/sh
 
-# exits with error message
-die() {
-    printf "error: %s\n" "$@"
-    exit 1
-}
-
-# search for a ctags file recursively up the directory tree from the file to be 
-# opened. If one is found, change the working directory of the new process to
-# the containing folder and launch xedit with the path of the file relative to  
-# the new working directory.
-edit_relative_ctags(){
-    origdir="$PWD"
-    case "$1" in
-        /*) origpath="$1" ;;      # absoulte path given
-        *)  origpath="$PWD/$1" ;; # relative path given
-    esac
-    path="${origpath##*/}"
-
-    # try to cd to the directory containing the file and attempt to walk the 
-    # tree backwars until we find a tags file. if one is found, open the file
-    # from that directory.
-    cd "${origpath%/*}" || die "could not open file: '$1'"
-    dir="$PWD"
-    while [ "$dir" != "" ]; do
-        if [ -f "$dir/tags" ]; then 
-            cd "$dir" && exec nohup xedit "$path" > /dev/null 2>&1
-        else
-            path="${dir##*/}/$path"
-            dir="${dir%/*}"
-        fi
-    done
-
-    # file is not part of a project. open it as-is
-    cd "$origdir" && exec nohup xedit "$1" > /dev/null 2>&1
-}
-
 # Add the editing tools directory to your PATH var so its contents may be used
 # while editing.
 export PATH="$HOME/.config/edit/tools:$PATH"
@@ -57,10 +21,6 @@ if [ -z "$DISPLAY" ]; then
     else
         "$EDITOR" "$@"
     fi
-elif [ 0 -eq $# ]; then
-    (nohup xedit > /dev/null 2>&1) &
 else
-    for f in "$@"; do
-        edit_relative_ctags "$f" &
-    done
+    (nohup xedit "$@" > /dev/null 2>&1) &
 fi
index 8aabb01c0d7faba88ea534f09231c1f8f2623b70..af2e8ba9fe060032a92192bd81f7b8fb3268485e 100644 (file)
@@ -14,6 +14,11 @@ char* stringdup(const char* str);
 char* fdgets(int fd);
 char* chomp(char* in);
 uint64_t modtime(char* path);
+char* getcurrdir(void);
+char* dirname(char* path);
+bool try_chdir(char* fpath);
+char* strconcat(char* dest, ...);
+bool file_exists(char* path);
 
 /* Buffer management functions
  *****************************************************************************/
index 3d74cbb80f89f95f690d711f0a2c5eb2f35261e1..ceebd3ec7ee56e6c27f1bf37ec32e5f6f4f8832b 100644 (file)
@@ -40,7 +40,8 @@ FMap mmap_readwrite(char* path, size_t sz) {
     int fd = open(path, O_CREAT|O_RDWR, 0644);
     if (fd >= 0) {
         ftruncate(fd, sz);
-        void* buf = mmap(NULL, pagealign(sz), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);        if (buf != MAP_FAILED) {
+        void* buf = mmap(NULL, pagealign(sz), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
+        if (buf != MAP_FAILED) {
             file.buf = buf;
             file.len = sz;
         }
@@ -104,3 +105,46 @@ uint64_t modtime(char* path) {
         return 0u;
     return (uint64_t)status.st_mtime;
 }
+
+char* getcurrdir(void) {
+    size_t size = 4096;
+    char *buf = NULL, *ptr = NULL;
+    for (; ptr == NULL; size *= 2) {
+        buf = realloc(buf, size);
+        ptr = getcwd(buf, size);
+        if (ptr == NULL && errno != ERANGE)
+            die("Failed to retrieve current directory");
+    }
+    return buf;
+}
+
+char* dirname(char* path) {
+    path = stringdup(path);
+    char* end = strrchr(path, '/');
+    if (!end) return NULL;
+    *end = '\0';
+    return path;
+}
+
+bool try_chdir(char* fpath) {
+    char* dir = dirname(fpath);
+    bool success = (dir && *dir && chdir(dir) >= 0);
+    free(dir);
+    return success;
+}
+
+char* strconcat(char* dest, ...) {
+    va_list args;
+    char* curr = dest;
+    va_start(args, dest);
+    for (char* s; (s = va_arg(args, char*));)
+        while (*s) *(curr++) = *(s++);
+    va_end(args);
+    *curr = '\0';
+    return dest;
+}
+
+bool file_exists(char* path) {
+    struct stat st;
+    return (stat(path, &st) < 0);
+}
diff --git a/xedit.c b/xedit.c
index 5d659a6359d0dcda4b50ca81d7717d6838e38119..e91798aa7050d9551850a4bc03e9ed07cf404b9b 100644 (file)
--- a/xedit.c
+++ b/xedit.c
@@ -5,6 +5,7 @@
 #include <ctype.h>
 #include <win.h>
 #include <shortcuts.h>
+#include <unistd.h>
 
 #define INCLUDE_DEFS
 #include "config.h"
@@ -526,6 +527,54 @@ void onshutdown(void) {
     quit();
 }
 
+void edit_relative(char* path) {
+    char *currdir = NULL, *currpath = NULL, *relpath = NULL;
+    char* origdir = getcurrdir();
+
+    /* search for a ctags index file indicating the project root */
+    if (try_chdir(path)) {
+        currdir  = getcurrdir();
+        currpath = calloc(strlen(currdir) + strlen("/tags") + 1, 1);
+        relpath  = calloc(strlen(currdir) + strlen("/tags") + 1, 1);
+        while (true) {
+            /* figure out the current path to check */
+            strconcat(currpath, currdir, "/tags", 0);
+            if (file_exists(currpath)) {
+                /* move up a dir */
+                char* end = strrchr(currdir,'/');
+                if (!end) break;
+                char* temp = stringdup(relpath);
+                strconcat(relpath, end, temp, 0);
+                free(temp);
+                *end = '\0';
+            } else {
+                break;
+            }
+        }
+    }
+
+    /* cd to the project directory or the original working directory and open
+       the file relative to the new working directory */
+    if (currdir && *currdir) {
+        char* fname = strrchr(path, '/')+1;
+        if (*relpath)
+            strconcat(currpath, relpath+1, "/", fname, 0);
+        else
+            strconcat(currpath, fname, 0);
+        chdir(currdir);
+        view_init(win_view(EDIT), currpath, ondiagmsg);
+    } else {
+        chdir(origdir);
+        view_init(win_view(EDIT), path, ondiagmsg);
+    }
+
+    /* cleanup */
+    free(currdir);
+    free(currpath);
+    free(relpath);
+    free(origdir);
+}
+
 #ifndef TEST
 int main(int argc, char** argv) {
     /* setup the shell */
@@ -536,7 +585,15 @@ int main(int argc, char** argv) {
     char* tags = getenv("EDITTAGS");
     win_settext(TAGS, (tags ? tags : DefaultTags));
     win_setruler(RulePosition);
-    view_init(win_view(EDIT), (argc > 1 ? argv[1] : NULL), ondiagmsg);
+    /* open the first file in this instance */
+    if (argc > 1)
+        edit_relative(argv[1]);
+    /* spawn a new instance for each remaining file */
+    for (int i = 2; i < argc; i++) {
+        OpenCmd[1] = argv[i];
+        cmdrun(OpenCmd, NULL);
+    }
+    /* now create the window and start the event loop */
     win_setkeys(Bindings);
     win_loop();
     return 0;