This is the mail archive of the cygwin mailing list for the Cygwin project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

File associations in Windows [was: Re: Invoking Cygwin vim from Windows Explorer]


On 2/9/2014 12:11 PM, carolus wrote:
> Is there some configuration that will let me open a text file
> in Cygwin vim by clicking on the file in an Explorer window?

I wonder if anyone else needs Windows file associations for sequences of Cygwin commands as well. If this is useful to many, maybe a nice utility can be whipped up. I ran into this with emacs-w32.exe which is the Cygwin emacs compiled for Win32 (not run under X).

(I require native Cygwin emacs, not the one downloaded from ftp.gnu.org, because version control things like bzr which are Python scripts aren't supported by Windows emacs, and because in general I want Cygwin, not Windows filenames, and so forth.)

The first problem is that Windows file associations have to be a single exe with no arguments. When you run that file (double click in Explorer), Windows passes the filename to that single .exe program.

The second problem is that it might need to be started from a full login shell (run from bash, after .bashrc and .bash_profile are loaded) to get right env vars and paths and other things to be set. No, I don't want to pollute Windows environment by duplicating everything I do in .bashrc and .bash_profile. So yes, I really need to run emacs from bash run as full login shell.

Why full login shell? When I run emacs-w32.exe, things like version control programs need the full login shell env vars, because checking the current directory under vc-dir doesn't run a shell, it runs "cvs" or "svn" or "git" directly. Without the full login shell, you don't have an env vars set. Fail.

No, I don't want to pollute my ~/.emacs with lots of (setenv "MYVAR" "myvalue") to mirror what's in .bashrc and .bash_profile, then monkeying with load-path and many other ugly hacks. Again, duplicating .bashrc and .bash_profile I dislike.

So in the end, my emacs start menu link is normally this:
Target: C:\Apps\Cyg\usr\local\bin\run.exe /bin/bash --login -i -c emacs
Start in: C:\Apps\Cyg\bin

(The patch for run.exe for quoting args better is accepted but not yet out there, so it's a locally compiled one for now. Because /usr/local/bin/run doesn't have the cygwin1.dll it won't start when located elsewhere. Ignore, secondary issue.)

The third problem is that the file passed to the Windows file association program is in Windows form, not Cygwin form with mounted filename substitutions (eg, I have /c for C:\). Many Cygwin programs if you pass C:\X\y will see C:Xy.

So to get a .txt file association to work with emacs-w32.exe, and also to get it to run under a full bash shell, and also to replace Windows with Cygwin file format, we need a single .exe that does all that. I ask, are others wanting to run random sequences of Cygwin programs as file associations? If so, maybe a little utility is in order.

I wrote a little utility of my own, a C++ program that essentially does:
cd C:\Apps\Cyg\bin
C:\Apps\Cyg\usr\local\bin\run.exe /bin/bash --login -i -c "emacs C:/X/My\ File.txt"

The "C:\X\My File.txt" replaced back with forward slashes, so slashed aren't lost to the Cygwin application, and escapes space with backslash space so it doesn't look like separate files to emacs.

After assembling where cygwin lives based on a personal env var "CYGROOT" into cygbin ostringstream:
    if (chdir (cygbin.str ().c_str ())) { ...error... }

After assembling the run argument as "runexe" ostringstream, and the bash login emacs argument as "cmd" ostringstream, in the end it did this, which might be useful for a little utility if someone wants to run with this:

    // Create an array with length 3 (2 plus null array terminator)
    char ** newAv = (char **)malloc (sizeof (char *) * 3);

    // First element of array is 'run'
    newAv[0] = (char *)malloc (strlen (runexe.c_str ()) + 1);
    strcpy (newAv[0], runexe.c_str ());

// Second element of array is the bash command to launch emacs with args
    newAv[1] = (char *)malloc (strlen (cmd.str ().c_str ()) + 1);
    strcpy (newAv[1], cmd.str ().c_str ());

    // Third element of array is null terminator
    newAv[2] = 0;

    // Report what we are doing in case someone is watching
    printf ("%s\n", newAv[1]);

    // Replace this process with 'run' process
    execve (newAv[0], newAv, env);

To get emacs to parse the C:\whatever as /c/whatever (since I mounted /c as C:\):

; When in cygwin, allow C:\whatever to turn into /c/whatever
(defun cygwin-name-hook (operation &rest args)
  "Turn Windows filenames into Cygwin filenames."
  ;; Handle all operations the same
  (let ((first (car args))
        (inhibit-file-name-handlers
         (cons 'cygwin-name-hook
               (and (eq inhibit-file-name-operation operation)
                    inhibit-file-name-handlers)))
        (inhibit-file-name-operation operation))
    (setq first (replace-regexp-in-string "^C:" "/c" first t))
    (setq first (replace-regexp-in-string "\\\\" "/" first t))
    (apply operation (cons first (cdr args)))))

(add-to-list 'file-name-handler-alist '("^[Cc]:" . cygwin-name-hook))

This also lets emacs be passed a Windows filename from places like compiler output errors, and it loads the right one.

For my C++ little utility I copied the emacs.ico and created a tiny LaunchEmacs.rc referencing it (so the "launch" file association looks like Emacs). Finally the Makefile was:

    i686-pc-mingw32-windres LaunchEmacs.rc -O coff -o LaunchEmacs.res
i686-pc-mingw32-g++ -static -mwindows -o LaunchEmacs.exe LaunchEmacs.cc LaunchEmacs.res

As you can see, this is a lot of work, and it may be useful to have Cygwin support file associations where some utility will go all the way with filename conversion, launching, full login shell support, and whatnot.

Are people interested?  Enough to start a little utility for this?

--
Problem reports:       http://cygwin.com/problems.html
FAQ:                   http://cygwin.com/faq/
Documentation:         http://cygwin.com/docs.html
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]