iVim
iVim copied to clipboard
Execute commands (e.g. compile files) from iVim, locally.
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.
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".
Here are some of my thoughts concerning the external command part:
-
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.
-
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.:!lsto 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. -
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?
-
I tried to run some commands such as
:!lsand:!pwd. They didn't work for me. (no results feedback) -
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.
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).
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.
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.
I reverted the entitlement file, and cancelled the whitespace-only changes.
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.
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.
Does that work better with ${PWD}?
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?
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.
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.
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.
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.
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.
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:

@terrychou What is the current status?