Skip to content

Commit

Permalink
Merge pull request #2 from ardagnir/commandline
Browse files Browse the repository at this point in the history
Commandline
  • Loading branch information
ardagnir committed Apr 16, 2014
2 parents 80d9ecf + f0b400a commit 15cc25f
Show file tree
Hide file tree
Showing 3 changed files with 129 additions and 23 deletions.
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,14 @@ Pterosaur is at an alpha stage right now. It is already useful if you do a lot o

##Requirements
- Pterosaur requires Pentadactyl and Vim(your version needs to have +clientserver).
- Pterosaur requires [eventloop.vim](https://github.com/ardagnir/eventloop.vim)
- Pterosaur assumes you are using Linux. It might work on OS X.

##Setup
**Step 1:** Install pterosaur using your Vim plugin-manager. For pathogen-compatible managers:
**Step 1:** Install pterosaur and eventloop.vim using your Vim plugin-manager. For pathogen-compatible managers:

cd ~/.vim/bundle
git clone http://github.com/ardagnir/eventloop.vim
git clone http://github.com/ardagnir/pterosaur

**Step 2:** Add pterosaur.js to ~/.pentadactyl/plugins/
Expand All @@ -37,7 +39,6 @@ Pterosaur runs an actual vim instance in the background and routes keystrokes th

- Escape leaves textboxes while in insert mode, but does nothing in normal mode.
- Some editors (like github outside of zen-mode) do weird things with text that make text manipulation difficult. Usually, pterosaur will fail into normal(vimless) text entry, but for some types of weirdness it will completly refuse to enter text at all.
- If you map another key to /, :, or ? in vim's normal mode, pterosaur won't show you the ex command you are typing until you hit enter.
- The code to handle multiple windows is hacky. If you create multiple windows at the same time, pterosaur might break and lose some of your keys.
- Mouse support is limited. Currently, you can click anywhere in a textbox to move the cursor there in insert mode. Eventually, mouse selection will be supported as well.

Expand Down
69 changes: 61 additions & 8 deletions plugin/pterosaur.vim
Original file line number Diff line number Diff line change
Expand Up @@ -21,21 +21,40 @@ if exists("g:loaded_pterosaur")
finish
endif

function! SwitchPterosaurFile(line, column, file, metaFile)
let s:fromCommand = 0

function! SwitchPterosaurFile(line, column, file, metaFile, messageFile)
augroup Pterosaur
sil autocmd!
sil autocmd FileChangedShell * echon ''
sil autocmd TextChanged * write!
sil autocmd TextChanged * call VerySilent("write!")

"Adding text in insert mode calls this, but not TextChangedI
sil autocmd CursorMovedI * write!
sil autocmd CursorMovedI * call VerySilent("write!")
sil exec "autocmd CursorMoved * call <SID>WriteMetaFile('".a:metaFile."', 0)"
sil exec "autocmd CursorMovedI * call <SID>WriteMetaFile('".a:metaFile."', 0)"

sil exec "autocmd InsertEnter * call <SID>WriteMetaFile('".a:metaFile."', 1)"
sil exec "autocmd InsertLeave * call <SID>WriteMetaFile('".a:metaFile."', 0)"
sil exec "autocmd InsertChange * call <SID>WriteMetaFile('".a:metaFile."', 1)"
augroup END

try
ElGroup! pterosaur

ElGroup pterosaur
ElSetting timer 4
ElCmd call CheckConsole()
ElCmd call OutputMessages()
ElGroup END
catch
call system('echo e > '.a:metaFile)
call system('echo Pterosaur requires eventloop.vim to read the VIM commandline. >> '.a:metaFile)
endtry

let s:metaFile = a:metaFile
let s:messageFile = a:messageFile

bd!

sil exec "edit! "a:file
Expand All @@ -60,23 +79,57 @@ function! s:WriteMetaFile(fileName, checkInsert)
let vim_mode = mode()
endif

sil exec '!echo '.vim_mode.' > '.a:fileName
call system('echo '.vim_mode.' > '.a:fileName)

let pos = s:GetByteNum('.')
if vim_mode ==# 'v'
sil exec '!echo -e "'.(min([pos,s:lastPos])-1)."\\n".max([pos,s:lastPos]).'" >> '.a:fileName
call system('echo -e "'.(min([pos,s:lastPos])-1)."\\n".max([pos,s:lastPos]).'" >> '.a:fileName)
elseif vim_mode ==# 'V'
let start = line2byte(byte2line(min([pos,s:lastPos])))
let end = line2byte(byte2line(max([pos,s:lastPos]))+1)
sil exec '!echo -e "'.start."\\n".end.'" >> '.a:fileName
call system('echo -e "'.start."\\n".end.'" >> '.a:fileName)
elseif (vim_mode == 'n' || vim_mode == 'R') && getline('.')!=''
sil exec '!echo -e "'.(pos-1)."\\n".pos.'" >> '.a:fileName
call system('echo -e "'.(pos-1)."\\n".pos.'" >> '.a:fileName)
let s:lastPos = pos
else
sil exec '!echo -e "'.(pos-1)."\\n".(pos-1).'" >> '.a:fileName
call system('echo -e "'.(pos-1)."\\n".(pos-1).'" >> '.a:fileName)
let s:lastPos = pos
endif
endfunction

function! CheckConsole()
if mode()=="c"
call system('echo c > '.s:metaFile)
call system('echo '.shellescape(getcmdtype().getcmdline(), 1).' >> '.s:metaFile)
if s:fromCommand == 0
ElGroup pterosaur
ElSetting timer 2
ElGroup END
endif
let s:fromCommand = 1
elseif s:fromCommand
call system('echo '.mode().' > '.s:metaFile)
let s:fromCommand = 0
ElGroup pterosaur
ElSetting timer 4
ElGroup END
endif
endfunction

"Don't even redirect the output
function! VerySilent(args)
redir END
silent exec a:args
exec "redir! >> ".s:messageFile
endfunction

"This repeatedly flushes because messages aren't written until the redir ends.
function! OutputMessages()
redir END
exec "redir! >> ".s:messageFile
endfunction

let g:loaded_pterosaur = 1

let &cpo = g:save_cpo
unlet g:save_cpo
78 changes: 65 additions & 13 deletions pterosaur.js
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ function update(){
if (pterosaurCleanupCheck !== options["fullvim"])
cleanupPterosaur();

if (!options["fullvim"] || dactyl.focusedElement.type === "password" || modes.main !== modes.INSERT && modes.main !== modes.AUTOCOMPLETE && modes.main !== modes.VIM_NORMAL) {
if (!options["fullvim"] || (dactyl.focusedElement && dactyl.focusedElement.type === "password") || modes.main !== modes.INSERT && modes.main !== modes.AUTOCOMPLETE && modes.main !== modes.VIM_NORMAL) {
if(pterFocused && modes.main !== modes.EX) {
cleanupForTextbox();
pterFocused = null
Expand All @@ -78,13 +78,42 @@ function update(){

let val = tmpfile.read();

let messages = messageTmpfile.read();
if (messages && messages!=="\n")
{
//window.alert(messages)
//TODO: If another message is written right now, we could lose it.
messageTmpfile.write("");
//TODO: We don't neccesarily want singleline, but without it we lose focus.
dactyl.echo(messages,commandline.FORCE_SINGLELINE);

//We've clearing the entered command. Don't need/want to clear it later and lose our message.
lastVimCommand=""
}
let metadata = metaTmpfile.read().split('\n');
vimMode = metadata[0]
if (vimMode === "n" && modes.main === modes.INSERT)
modes.push(modes.VIM_NORMAL)

if (vimMode === "i" && modes.main === modes.VIM_NORMAL)
modes.pop()
vimMode = metadata[0];
if (vimMode === "e")
dactyl.echo("ERROR: "+metadata[1])
else if (vimMode === "n" && modes.main === modes.INSERT)
{
//Clear --INSERT-- echoed from vim messages
dactyl.echo("")
modes.push(modes.VIM_NORMAL);
}
else if (vimMode === "i" && modes.main === modes.VIM_NORMAL)
modes.pop();

if (vimMode === "c") {
if(metadata[1] !=="" && metadata[1] != lastVimCommand)
{
lastVimCommand = metadata[1]
dactyl.echo("VIM COMMAND " + metadata[1], commandline.FORCE_SINGLELINE);
}
}
else if(lastVimCommand) {
dactyl.echo("")
lastVimCommand=""
}

if (textBox) {
if (savedCursorStart!=null && textBox.selectionStart != savedCursorStart || savedCursorEnd!=null && textBox.selectionEnd != savedCursorEnd ) {
Expand Down Expand Up @@ -125,10 +154,16 @@ function cleanupForTextbox() {
tmpfile.remove(false);
if (metaTmpfile && metaTmpfile.exists())
metaTmpfile.remove(false);
if (messageTmpfile && messageTmpfile.exists())
messageTmpfile.remove(false);
tmpfile = null
}

function setupForTextbox() {
//Clear lingering command text
if (vimMode === "c")
io.system("printf '\\x1bi' > /tmp/pterosaur_fifo"); //<ESC>i

pterFocused = dactyl.focusedElement;
savedText = null;
savedCursorStart = null;
Expand Down Expand Up @@ -171,20 +206,25 @@ function setupForTextbox() {
let origGroup = DOM(textBox).highlight.toString();
tmpfile = io.createTempFile("txt", "-pterosaur"+buffer.uri.host);
metaTmpfile = io.createTempFile("txt", "-pterosaur"+buffer.uri.host+"-meta");
messageTmpfile = io.createTempFile("txt", "-pterosaur"+buffer.uri.host+"-messages");
if (!tmpfile)
throw Error(_("io.cantCreateTempFile"));

if (!metaTmpfile)
throw Error(_("io.cantCreateTempFile"));

if (!messageTmpfile)
throw Error(_("io.cantCreateTempFile"));

if (!tmpfile.write(text))
throw Error(_("io.cantEncode"));

var vimCommand;

vimCommand = 'vim --servername pterosaur --remote-expr "SwitchPterosaurFile(<line>,<column>,\'<file>\',\'<metaFile>\')"';
vimCommand = 'vim --servername pterosaur --remote-expr "SwitchPterosaurFile(<line>,<column>,\'<file>\',\'<metaFile>\',\'<messageFile>\')"';

vimCommand = vimCommand.replace(/<metaFile>/, metaTmpfile.path);
vimCommand = vimCommand.replace(/<messageFile>/, messageTmpfile.path);
vimCommand = vimCommand.replace(/<file>/, tmpfile.path);
vimCommand = vimCommand.replace(/<column>/, column);
vimCommand = vimCommand.replace(/<line>/, line);
Expand All @@ -200,15 +240,23 @@ modes.INSERT.params.onKeyPress = function(eventList) {

let inputChar = DOM.Event.stringify(eventList[0])

if (/^<(?:.-)*(?:BS|lt|Up|Down|Left|Right|Space|Return|Del|Tab|C-h|C-w|C-u|C-k|C-r)>$/.test(inputChar)) {
/*if (commandLock > COMMAND_MODE_SYNC)
{
commandBuffer += inputChar;
return;
}
*/

if (/^<(?:.-)*(?:BS|Esc|lt|Up|Down|Left|Right|Space|Return|Del|Tab|C-h|C-w|C-u|C-k|C-r)>$/.test(inputChar)) {
//Currently, this also refreshes. I need to disable that.
if (inputChar==="<Space>")
io.system("printf ' ' > /tmp/pterosaur_fifo");
else if (inputChar==="<BS>")
io.system("printf '\\b' > /tmp/pterosaur_fifo");
else if (inputChar==="<Return>") {
io.system("printf '\\r' > /tmp/pterosaur_fifo");
return PASS;
if (vimMode !== "c")
return PASS;
}
else if (inputChar==="<Tab>")
return PASS;
Expand All @@ -223,10 +271,11 @@ modes.INSERT.params.onKeyPress = function(eventList) {
else if (inputChar==="<lt>")
io.system("printf '<' > /tmp/pterosaur_fifo");
}
else if (/\:|\?|\//.test(inputChar) && vimMode!='i' && vimMode!='R')
/*else if (/\:|\?|\//.test(inputChar) && vimMode!='i' && vimMode!='R')
{
CommandExMode().open("vimdo " + inputChar);
}
*/
else {
if (inputChar == '%')
io.system('printf "%%" > /tmp/pterosaur_fifo');
Expand Down Expand Up @@ -260,8 +309,8 @@ function cleanupPterosaur()

io.system("mkfifo /tmp/pterosaur_fifo");

//TODO: This is an ugly hack. Also, the cat is necessary
io.system("$(while killall -0 firefox; do sleep 1; done) | cat > /tmp/pterosaur_fifo &");
//TODO: This is an ugly hack.
io.system("(while killall -0 firefox; do sleep 1; done) > /tmp/pterosaur_fifo &");

//TODO: Also an ugly hack. Also the --remote is only there because on some computers vim won't create a server outside a terminal unless it has a --remote.
io.system('sh -c \'while [ "$(vim --servername pterosaur --remote-expr 1)" != 1 ] && killall -0 firefox; do vim --servername pterosaur +"set autoread" +"set noswapfile" +"set shortmess+=A" --remote /tmp/pentatdactyl-pterosuar </tmp/pterosaur_fifo > /dev/null; done\' &');
Expand Down Expand Up @@ -306,6 +355,9 @@ var vimMode = 'i';
var pterFocused = null;
var tmpfile = null;
var metaTmpfile = null;
var messageTmpfile = null;
var textBox;
var lastVimCommand = "";


let timer = window.setInterval(update, 100);

0 comments on commit 15cc25f

Please sign in to comment.