iVim icon indicating copy to clipboard operation
iVim copied to clipboard

Execute commands (e.g. compile files) from iVim, locally.

Open holzschu opened this issue 7 years ago • 17 comments

The idea is, while you're editing a file, you might want to run an external tool on it (python, lua, latex...) This used to be impossible on iOS. With this modification, when you hit ":make" in Vim (or <D-R>), it calls OpenURL with the specific scheme "blinkshell://" and transfers the command to blinkshell (another app, see here: https://github.com/blinksh/blink ) who then executes the command. The URL looks like: "blinkshell://command%20flags%20name_of_the_file".

This only works if the file is inside the blinkshell sandbox, and has been "opened-in-place" (an iOS 11 fonctionnality). I extract the original name and position of the file from its mirrorURL, so blinkshell acts on the original file.

Obviously, direct commands such as "!ls" and "!pwd" also work, but again only inside blinkshell sandbox.

holzschu avatar Nov 09 '17 20:11 holzschu

Separate functionality added: when a function calls "system(rmdir /path/to/directory)" or "system(rm /path/to/file)", execute these calls locally using standard lib calls to rmdir() and removefile().

This is really useful when using netrw: the file explorer shows files, lets us edit them... but not delete directories. Also temporary directories created when editing are not always removed when the app crashes. This lets us clean up the working area ourselves.

It is a separate addition from the previous one. They can be merged separately if needed. Their only common point is "#define USE_SYSTEM".

holzschu avatar Nov 12 '17 20:11 holzschu

Here are some of my thoughts concerning the external command part:

  1. If I understand it right, blinkshell is a terminal app connecting to remote hosts via ssh or mosh. It doesn't really have a shell itself. And I see this method is heavily based on passing commands to it via the "blinkshell://" URL scheme.

  2. If this is the case. First, it is kind of confusing. In vim, users invoke local shell commands via the "!" way (such as :!ls). They are expecting those commands to work on the environment in which vim is situated. (e.g. :!ls to list the files right under the current working directory.) However, if we pass the commands to blink, they will be invoked on the remote host blink is connecting to. So, it would be another totally different environment.

  3. Secondly, it is sort of depending. It depends on the external app Blink. What if a user doesn't have it installed? And what if the URL scheme is changed some day?

  4. I tried to run some commands such as :!ls and :!pwd. They didn't work for me. (no results feedback)

  5. I see it uses mirrorURL. But I think its role maybe misunderstood: the mirror URL is for iVim managing resources 'open-in-place'd in other apps.

terrychou avatar Nov 13 '17 03:11 terrychou

I understand your issues. They all come from sandbox limitations: an app can only work on apps inside its sandbox. Open-in-place is a small workaround, but it only applies to opening the file, and to the file itself (the permission does not extend to its directory, so there's no way to access other files, or create a file).

If I understand you, you would prefer to have the commands inside the iVim binary, working on the files inside the iVim sandbox. I can do that too (I did for rmdir, for example).

holzschu avatar Nov 13 '17 12:11 holzschu

Here is a revised attempt. All commands are now executed inside of iVim's sandbox. The commands currently available are: ls touch rm cp ln link mv mkdir rmdir chown chgrp chflags chmod du df chksum sum stat readlink compress uncompress gzip gunzip.

Of these, the ones that I found really useful are:

  • rmdir, because the tmp directory tends to get crowded with directories that vim doesn't know how to remove (because vim calls the system for rmdir, but not for rm). In netrw, typing "D" calls rmdir on the directory. As with the system rmdir, it only works if the directory is empty.
  • gzip/gunzip, because (with autocmd) it allows vim to edit gzipped files, and gzip the modified file after writing. I think there is a vim plugin for that.

The other commands are mostly available as a proof of concept. You will need the file_cmds_ios framework, from my port of blinkshell (https://github.com/holzschu/blink , in the AppleSource/file_cmds-264.50.1 directory ). I haven't found how to share the source between the two github repositories, sorry.

holzschu avatar Nov 18 '17 17:11 holzschu

I've only skimmed most of the above and don't know github's UI all that well, so apologies if this has already been discussed or even addressed in commits, but the change to the entitlements file doesn't look right to me, and there seem to be some whitespace-only changes to vim/src/os_unix.c which seem like a bad idea with regards to any potential future merges with/updates from the main Vim codebase.

sedm0784 avatar Nov 20 '17 15:11 sedm0784

I reverted the entitlement file, and cancelled the whitespace-only changes.

holzschu avatar Nov 20 '17 17:11 holzschu

Could I convince you to give a second look to this PR? Differences are much smaller, commands are executed inside iVim sandbox. Several commands, such as curl, scp, ssh, rmdir, bring useful features to iVim.

holzschu avatar Feb 10 '18 15:02 holzschu

There is a problem with the script get_frameworks.sh: the "${BASH_SOURCE%/*}/Frameworks" would be "/Frameworks" when $BASH_SOURCE is empty. Which would lead to non-existing directory.

terrychou avatar Feb 11 '18 03:02 terrychou

Does that work better with ${PWD}?

holzschu avatar Feb 11 '18 16:02 holzschu

The file the script downloads is release.tar.gz but it untars ios_system.framework.tar.gz which doesn't exist. This doesn't stop the script, but the libraries don't get unpacked. I manually untared and moved the lib files.

When the script runs, I get a bunch of patch warnings when it's going through the python code and I'm not sure if I should be saying yes or no to them. Since the libraries are prebuilt now, I'm not sure if this is an issue anymore.

Just to be sure, python and lua directories are created next to the ivim directory, not inside it. Is this correct?

drbarrett avatar Feb 11 '18 19:02 drbarrett

I fixed the script. If the directory for python has already been patched once, applying the patch a second time will result in warnings. As you said, the packages are now precompiled. The only reason we need the source of Python and Lua is because, with FEAT_PYTHON enabled, the source file if_python.c needs to include Python.h, which in turn includes a lot of Python headers (and the same for Lua). Python and Lua directories are currently created next to the iVim directory, yes. That can easily be changed. On my settings, they are shared between different projects.

holzschu avatar Feb 11 '18 20:02 holzschu

I have been using this PR and just found out that the outputs of the shell commands only appears in the console (I couldn't get any feedback when used without connecting to the debugging console.). And this is why I felt confused.

terrychou avatar Mar 03 '18 03:03 terrychou

These are Unix commands: they read stdin, and write to stdout. Most of the time, when iVim starts a command (e.g. if I press "D" in netrw to delete a directory, or type ":make", or ":pyf file") the output of the command is redirected to a file, and after the command is executed that file is parsed by the Vim command to output meaningful error messages. This works.

If we type ":!ls", however, the output is sent to stdout and stdout is not sent back to the status line (because, so far, nothing was writing to stdout so there was no need to do it). Since it works on other GUI version, it could be fixed, but I don't know how to do it.

holzschu avatar Mar 03 '18 09:03 holzschu

Update: not seeing the result of the command on screen (unless it's been redirected to a file) is a consequence of using #define USE_SYSTEM. On the other hand, we get minimal changes to the Vim code. I'm going to investigate if I can fake fork() so that we get command results on screen.

holzschu avatar Mar 04 '18 15:03 holzschu

This version (06620e1) makes the commands output their results on the Vim screen (while keeping the ability to save to files). It works by faking fork()/exec(), which makes bigger changes to the source code. It uses an extra file, ios_error.h. To get it, either: re-run get_frameworks.sh or get it with curl -OL https://github.com/holzschu/ios_system/releases/download/v1.1/ios_error.h.

png image

holzschu avatar Mar 04 '18 18:03 holzschu

Just for your information, with the latest version (working around fork()/exec()), it is possible to run @Shougo's vimproc with minimal modifications (https://github.com/holzschu/vimproc.vim) and therefore vimshell (https://github.com/Shougo/vimshell.vim) giving an interactive terminal window inside iVim: img_0071 img_0072 img_0073

holzschu avatar Mar 08 '18 20:03 holzschu

@terrychou What is the current status?

kkebo avatar Apr 27 '19 17:04 kkebo