diff --git a/vimception.js b/vimception.js index d8f4ca4..9e91b28 100644 --- a/vimception.js +++ b/vimception.js @@ -1,9 +1,3 @@ - -var cmd = IPython.keyboard_manager.command_shortcuts; -var edit = IPython.keyboard_manager.edit_shortcuts; -var def_cmd = IPython.default_command_shortcuts; -var def_edit = IPython.default_edit_shortcuts; - // get the code mirror editor of a curently selected cell function C() { return IPython.notebook.get_selected_cell().code_mirror; }; @@ -23,7 +17,7 @@ function getCSS(path) { $('', { rel: 'stylesheet', type: 'text/css', - href: path, + href: path }).appendTo('head'); } @@ -31,29 +25,33 @@ function getCSS(path) { // just using this answer from SO // http://stackoverflow.com/questions/11803215/how-to-include-multiple-js-files-using-jquery-getscript-method +require(['codemirror/lib/codemirror','codemirror/keymap/vim', 'codemirror/addon/search/search', + 'codemirror/addon/search/searchcursor', 'codemirror/addon/wrap/hardwrap', 'codemirror/addon/selection/active-line', + 'codemirror/addon/dialog/dialog'], function init_vimception(CodeMirror) { + var p = "/static/components/codemirror/addon/"; -$.when( +//$.when( // Grab the CodeMirror vim keymap -$.getScript(p + "../keymap/vim.js"), +//$.getScript(p + "../keymap/vim.js"), // also make search work via / -$.getScript(p + "search/search.js"), -$.getScript(p + "search/searchcursor.js"), +//$.getScript(p + "search/search.js"), +//$.getScript(p + "search/searchcursor.js"), // TODO: hook-up gq to perform a harwrap -$.getScript(p + "wrap/hardwrap.js"), -$.getScript(p + "selection/active-line.js"), +//$.getScript(p + "wrap/hardwrap.js"), +//$.getScript(p + "selection/active-line.js"), -$.getScript(p + "display/fullscreen.js"), -getCSS(p + "display/fullscreen.css"), -getCSS(p + "dialog/dialog.css"), -$.getScript(p + "dialog/dialog.js"), +//$.getScript(p + "display/fullscreen.js"), +getCSS(p + "display/fullscreen.css"); +getCSS(p + "dialog/dialog.css"); +//$.getScript(p + "dialog/dialog.js"), - $.Deferred(function( deferred ){ - $( deferred.resolve ); - }) -).then(function success(){ + //$.Deferred(function( deferred ){ + //$( deferred.resolve ); + //}) +//).then(function success() console.log('Great success'); @@ -61,13 +59,13 @@ IPython.CodeCell.options_default.cm_config.foldGutter = true; IPython.CodeCell.options_default.cm_config.gutters = ["CodeMirror-linenumbers", "CodeMirror-foldgutter"]; IPython.Cell.prototype.at_top = function () { - var cm = this.code_mirror; - var cursor = cm.getCursor(); - if (cursor.line === 0) { - return true; - } - return false; - }; + var cm = this.code_mirror; + var cursor = cm.getCursor(); + if (cursor.line === 0) { + return true; + } + return false; +}; IPython.Cell.prototype.at_bottom = function () { @@ -86,30 +84,70 @@ function all_cm(f) { to('vim'); -function vim_up(event) { + +function vim_up(env, event) { + //debugger; var cell = IPython.notebook.get_selected_cell(); - if (cell && cell.at_top() && cell.code_mirror.options.keyMap === 'vim') { - console.log('inside the business logic k'); - event.preventDefault(); - IPython.notebook.command_mode() - IPython.notebook.select_prev(); - IPython.notebook.edit_mode(); - return false; - }; + if (cell.code_mirror.options.keyMap === 'vim-insert' && cell.code_mirror.state.vim.insertMode) { + cell.code_mirror.replaceSelection(event.shiftKey ? String.fromCharCode(event.keyCode).toUpperCase() + : String.fromCharCode(event.keyCode).toLowerCase()) + return true; + }else{ + if (cell && cell.at_top() && cell.code_mirror.options.keyMap === 'vim') { + //console.log('inside the business logic k'); + //event.preventDefault(); + IPython.notebook.command_mode(); + IPython.notebook.select_prev(); + IPython.notebook.edit_mode(); + var newcell = IPython.notebook.get_selected_cell(); + + if ( newcell.code_mirror.state.vim.insertMode ) { + // do magic here to get out of insert mode + CodeMirror.Vim.handleKey(newcell.code_mirror, ''); + } + return false; + } else { + cell.code_mirror.execCommand('goLineUp'); + return false; + //return CodeMirror.Pass; + } + } } -function vim_down(event) { - var cell = IPython.notebook.get_selected_cell(); - if (cell && cell.at_bottom() && cell.code_mirror.options.keyMap === 'vim') { - event.preventDefault(); - IPython.notebook.command_mode() - IPython.notebook.select_next(); - IPython.notebook.edit_mode(); - return false; - }; +function vim_down(env, event) { + //debugger; + var cell = IPython.notebook.get_selected_cell(); + if (cell.code_mirror.options.keyMap === 'vim-insert' && cell.code_mirror.state.vim.insertMode) { + cell.code_mirror.replaceSelection(event.shiftKey ? String.fromCharCode(event.keyCode).toUpperCase() + : String.fromCharCode(event.keyCode).toLowerCase()) + return true; + } else { + if (cell && cell.at_bottom() && cell.code_mirror.options.keyMap === 'vim') { + //event.preventDefault(); + IPython.notebook.command_mode(); + IPython.notebook.select_next(); + IPython.notebook.edit_mode(); + var newcell = IPython.notebook.get_selected_cell(); + + if ( newcell.code_mirror.state.vim.insertMode ) { + // do magic here to get out of insert mode + CodeMirror.Vim.handleKey(newcell.code_mirror, ''); + } + return false; + } else { + cell.code_mirror.execCommand('goLineDown'); + return false; + //return CodeMirror.Pass; } + } +} + +var cmd = IPython.keyboard_manager.command_shortcuts; +var edit = IPython.keyboard_manager.edit_shortcuts; +var def_cmd = IPython.keyboard_manager.get_default_command_shortcuts(); +var def_edit = IPython.keyboard_manager.get_default_edit_shortcuts(); -var m = '(vim) ' +var m = '(vim) '; var edit_shortcuts = { 'k' : { help : m + 'up a line, even across cells', @@ -120,17 +158,18 @@ var edit_shortcuts = { help : m + 'down a line, even across cells', help_index : 'AA', handler : vim_down - }, + } }; - var command_shortcuts = { - 'c' : { +/* + 'y' : { help : m + def_cmd['y'].help, help_index : 'AA', handler : def_cmd['y'].handler } +*/ }; @@ -145,13 +184,17 @@ cmd.add_shortcuts(command_shortcuts); // there's a problem here, Ctrl-[ is already handled by CodeMirror by the time we // (IPython.keyboard_manager) get it CodeMirror issues signals on mode change, // so we have to hook into that to get Ctrl-[ -edit.remove_shortcut('Ctrl-['); -edit.remove_shortcut('Esc'); +//edit.remove_shortcut('Ctrl-['); +try { + edit.remove_shortcut('Esc'); +} catch(err) { + console.log("Error removing Esc shortcut; ignoring"); +} CodeMirror.commands.leaveInsertOrEdit = function (cm) { if ( cm.state.vim.insertMode ) { // do magic here to get out of insert mode - CodeMirror.keyMap['vim-insert']['Esc'](cm); + CodeMirror.Vim.handleKey(cm, ''); } else { IPython.notebook.command_mode(); IPython.notebook.focus_cell(); @@ -173,15 +216,19 @@ all_cm( function (cm) { IPython.TextCell.options_default.cm_config.extraKeys['Ctrl-['] = 'leaveInsertOrEdit'; IPython.CodeCell.options_default.cm_config.extraKeys['Esc'] = 'leaveInsertOrEdit'; IPython.TextCell.options_default.cm_config.extraKeys['Esc'] = 'leaveInsertOrEdit'; -}) +}); // On blur, make sure we go back to command mode for CodeMirror (in case user clicked away) // TODO: Make this permanent - how to get CodeMirror to do this for new cells created after all_cm( function (cm) { cm.on('blur', function(cm) { // TODO: I wish I understood a better way to do this, but fake pressing Escape work - CodeMirror.keyMap['vim-insert']['Esc'](cm); - CodeMirror.keyMap['vim']['Esc'](cm); + try { + CodeMirror.keyMap['vim-insert']['Esc'](cm); + } catch (err) {} + try { + CodeMirror.keyMap['vim']['Esc'](cm); + } catch (err) {} cm.setOption('styleActiveLine', false); if (cm.getOption("fullScreen")) { cm.setOption('fullScreen', false); @@ -193,17 +240,21 @@ all_cm( function (cm) { } }); cm.on('focus', function(cm) { - cm.setOption('styleActiveLine', true); + // RW - Changed to false. I don't like it. + cm.setOption('styleActiveLine', false); }); }); // 'i' by default interrupts the kernel (what Ctrl-C does at the terminal) -cmd.remove_shortcut('i'); +//cmd.remove_shortcut('i'); cmd.add_shortcut('i', def_cmd.enter); +// Delete this crap -- I want my copy / paste back +delete CodeMirror.keyMap['vim']['Ctrl-C']; + // not quite what we want - 'i' requires a double-tap // add documentation for this. -cmd.add_shortcut('ctrl-c', function(e) { IPython.notebook.kernel.interrupt(); return false}); +cmd.add_shortcut('ctrl-i' /* was ctrl-c */, function(e) { IPython.notebook.kernel.interrupt(); return false}); function focus_last(e) { @@ -247,33 +298,44 @@ function combo_tap(combo, action) { reset(); }; cmd.add_shortcut('shift-g', focus_last); -combo_tap('gg', focus_first); +//combo_tap('gg', focus_first); +cmd.add_shortcut('g,g', focus_first); // XXX: the way combo tap is currently implemented, this won't work // need a more generic mechanism for combo-taps with common prefixes // combo_tap('gq', f(); //cmd.remove_shortcut('d'); // cut -combo_tap('dd', def_cmd['x'].handler); +//combo_tap('dd', IPython.notebook.cut_cell); +cmd.add_shortcut('d,d', "ipython.cut-selected-cell"); +//$.proxy(function() { + // console.log("Here!"); IPython.notebook.cut_cell(); + // }, + // IPython.notebook)); // copy -combo_tap('yy', def_cmd['c'].handler); +//combo_tap('yy', IPython.notebook.copy_cell); +try { + cmd.remove_shortcut('y'); +} catch (err) {} +cmd.add_shortcut('y,y', "ipython.copy-selected-cell"); // paste -cmd.add_shortcut('p', def_cmd['v']); +cmd.add_shortcut('p', "ipython.paste-cell-after"); +cmd.add_shortcut('shift-p', "ipython.paste-cell-before"); // undo -cmd.add_shortcut('u', def_cmd['z']); +cmd.add_shortcut('u', "ipython.undo-last-cell-deletion"); // Join (merge down with cell below) -cmd.add_shortcut('shift-j', def_cmd['shift-m']) +cmd.add_shortcut('shift-j', IPython.notebook.merge_cell_below); //edit.add_shortcut('k', def_edit['up'].handler); //[edit.add_shortcut('j', def_edit['down'].handler); CodeMirror.prototype.save = function() { IPython.notebook.save_checkpoint() -} +}; function focus_last(e) { var cells = IPython.notebook.get_cells(); @@ -288,7 +350,7 @@ function focus_first(e) { cmd.add_shortcut('shift-g', focus_last); -combo_tap('gg', focus_first); +//combo_tap('gg', focus_first); // get rid of the default Ctrl-W binding // this only works for Firefox @@ -301,6 +363,7 @@ $(document).ready(function() { }); }); +/* window.addEventListener("beforeunload", function( event ) { var press = jQuery.Event("keypress"); press.ctrlKey = false; @@ -309,10 +372,10 @@ window.addEventListener("beforeunload", function( event ) { event.returnValue = "\nXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"; event.returnValue +="\nX Chrome sucks at captruring Ctrl-W, sorry X"; event.returnValue += "\nXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"; -}); +});*/ // update the keyboard shortcuts -IPython.quick_help = new IPython.QuickHelp(); +//IPython.quick_help = new IPython.QuickHelp(); //IPython.CodeCell.options_default.cm_config.styleActiveLine = true; @@ -338,13 +401,15 @@ all_cm( function (cm) { //setTimeout(function() {IPython.notebook.get_selected_cell().set_input_prompt('vim');}, 200) +/* $("#ipython_notebook").find('img').remove('#vim'); $("#ipython_notebook").append('') + + 'position: absolute; left: 51px; top: -10px; height: initial;">'); $("#vim").click( function () {$(this).hide()}); +*/ // XXX: Autowrapping is kind of broken - you can write a line that will have @@ -360,37 +425,34 @@ $("#vim").click( function () {$(this).hide()}); // }); //}); -}, function failure() { - alert('le sucks, something went wrong'); - }); // at_top and at_bottom methods for ipython-vimception - /** - * @method at_top - * @return {Boolean} - */ - Cell.prototype.at_top = function () { - var cm = this.code_mirror; - var cursor = cm.getCursor(); - if (cursor.line === 0 && cm.findPosV(cursor, -1, 'line').hitSide) { - return true; - } else { - return false; - } - }; - - /** - * @method at_bottom - * @return {Boolean} - * */ - Cell.prototype.at_bottom = function () { - var cm = this.code_mirror; - var cursor = cm.getCursor(); - if (cursor.line === (cm.lineCount()-1) && cm.findPosV(cursor, 1, 'line').hitSide) { - return true; - } else { - return false; - } - }; +/** + * @method at_top + * @return {Boolean} + */ +Cell.prototype.at_top = function () { + var cm = this.code_mirror; + var cursor = cm.getCursor(); + if (cursor.line === 0 && cm.findPosV(cursor, -1, 'line').hitSide) { + return true; + } else { + return false; + } +}; + +/** + * @method at_bottom + * @return {Boolean} + * */ +Cell.prototype.at_bottom = function () { + var cm = this.code_mirror; + var cursor = cm.getCursor(); + if (cursor.line === (cm.lineCount()-1) && cm.findPosV(cursor, 1, 'line').hitSide) { + return true; + } else { + return false; + } +};