Open ttimbers opened 8 years ago
%%javascript
Jupyter.keyboard_manager.edit_shortcuts.add_shortcut('alt--', {
help : 'add assignment symbol',
help_index : 'zz',
handler : function (event) {
var target = Jupyter.notebook.get_selected_cell()
var cursor = target.code_mirror.getCursor()
var before = target.get_pre_cursor()
var after = target.get_post_cursor()
target.set_text(before + '<-' + after)
cursor.ch += 2
target.code_mirror.setCursor(cursor)
return false;
}}
);
y/n?
Note that bad things will happen if using this shortcut immediately before or after a linebreak. the get_pre_cursor
and get_post_cursor
methods seem to ignore the immediately adjacent newline character; the interested reader may be able to work around this, but this feels an awful lot like a bug IMO; for example, check the lengths of the strings returned by get_pre_cursor
, get_post_cursor
and get_text
; the pre and post add up to the total if the cursor is not adjacent to a newline, but falls short by one if it is. Not sure if this is by design or not, but definitely not what I would have expected from these methods.
Thanks for this solution @BillMills! I agree that it works in the most common use case (assigning a variable), and so when using it like this, you do not run into the newline character issue. But the newline character issue is very weird, and I agree that this looks like a bug and not an intentional design feature of the method...
note - since magics don't work when running the R kernel in Jupyter, you have to wrap the above code in IRdisplay::display_javascript("some javascript code")
Working code in Jupyter using the R kernel looks like this (note - I tweaked the code to create a space before and after the assignment symbol - similar to what R Studio does):
IRdisplay::display_javascript("Jupyter.keyboard_manager.edit_shortcuts.add_shortcut('alt--', {
help : 'add assignment symbol',
help_index : 'zz',
handler : function (event) {
var target = Jupyter.notebook.get_selected_cell()
var cursor = target.code_mirror.getCursor()
var before = target.get_pre_cursor()
var after = target.get_post_cursor()
target.set_text(before + ' <- ' + after)
cursor.ch += 4
target.code_mirror.setCursor(cursor)
return false;
}}
);")
To get this feature in all notebooks, you need to add the following code to a file called custom.js
whose path is ~/.jupyter/custom/custom.js
:
$([IPython.events]).on("app_initialized.NotebookApp", function () {
Jupyter.keyboard_manager.edit_shortcuts.add_shortcut('alt--', {
help : 'add assignment symbol',
help_index : 'zz',
handler : function (event) {
var target = Jupyter.notebook.get_selected_cell()
var cursor = target.code_mirror.getCursor()
var before = target.get_pre_cursor()
var after = target.get_post_cursor()
target.set_text(before + ' <- ' + after)
cursor.ch += 4
target.code_mirror.setCursor(cursor)
return false;
}}
);
return true;
});
essentially this is @BillMills solution wrapped in:
$([IPython.events]).on("app_initialized.NotebookApp", function () {
<your code>
return true;
});
@minrk @jdfreder @Carreau and @ellisonbg - can any of you comment on the bug identified by @BillMills in get_pre_cursor
and get_post_cursor
methods regarding their adjacency to line breaks? Specifically he has found that they seem to ignore the immediately adjacent newline character and this results in bad things happening if we use the shortcut we implemented immediately before or after a linebreak.
Since this shortcut would be WIDELY used by almost ALL R Jupyter users, I really think it would be worth our time to fix this upstream bug. Any thoughts/insights/fixes would be much appreciated!
Hum, it seem like it would be possible, and likely less brittle to register a keyboard shortcut with codemirror directly instead of going through the jupyter keyboard manager.
Plus if you like to have that only on the R kernel, it should be possible to ship it with the R kernel itself using the kernel.js
file that ship with the R kernel (if it ships one), so I guess that will likely interest @flying-sheep to ping on that and know if its worth including with the R kernel.
Something along the line of:
if (! doc.somethingSelected()){
var cur = doc.getCursor()
doc.replaceRange(' <- ', cur, cur, )
}
Will likely be more efficient, and less error prone, the question is how to propagate the keybinding directly to the code cells from configuration. I can try to have look, but maybe a bit later I need to finish a couple of things for this week-end.
This issue might have some extra hints about CodeMirror keymaps.
indeed i am interested.
i condensed it to this and it works. will be in IRkernel as soon as i got something else in:
const extra_keys = {
['Alt--'](cm) {
cm.replaceSelection(' <- ')
}
}
define(['base/js/namespace'], jupyter => ({
onload() {
for (let cell of jupyter.notebook.get_cells()) {
cell.code_mirror.setOption('extraKeys', extra_keys)
}
}
}))
just one question: will the onload event fire for new cells? if not, what event will?
it works! but badly, as the CodeMirror version is too old to know what a “word” in R is.
i need at least 5.13.0. when will notebook be upgraded to something above it?
It looks like the current notebook master has codemirror 5.14: https://github.com/jupyter/notebook/blob/85d7cfba224005d423ff27c0b8e961813ea5016b/bower.json#L8
jup, just found it too! is the next release 5.0? if so: it got a huge heap of open bugs :cry:
@ttimbers once you update the IRkernel package and re-run installspec
, you’ll have it :smile:
i also added a F1 shortcut to get help for the word under the cursor: https://github.com/IRkernel/IRkernel/blob/4d4193ff2a041650b24364ecee1493ce595e1b5c/inst/kernelspec/kernel.js
Good point. The 4.x branch still is at Codemirror 5.8: https://github.com/jupyter/notebook/blob/9e1459fbc540a70089cab25e9d8ef952f4eb4ca4/bower.json. I put in an issue at https://github.com/jupyter/notebook/issues/1686
thanks! that’s necessary because all getWordAt calls need this to work properly.
it’s also someone we know who laid the foundation to CodeMirror recognizing r words :smile: https://github.com/codemirror/CodeMirror/commit/877b2b1766a40bed35d5f035f15e01d8f9a66e4f
and @Carreau:
just one question: will the onload event fire for new cells? if not, what event will?
just one question: will the onload event fire for new cells
No.
if not, what event will?
None, but you should be able to also patch the CodeCell
class. Add a new key to CodeCell.options_default.cm_config.extraKeys
with your custom function, it will affect all the newly created cells.
Sidenote I think your snippet replace the "Backspace" : "delSpaceToPrevTabStop",
binding we set.
if so: it got a huge heap of open bugs
We are aware, @gnestor have started going through these and is doing doing a great job at moving things forward !
We are aware, @gnestor have started going through these and is doing doing a great job at moving things forward!
that’s awesome! and i wasn’t insinuating that it goes too slow or something!
None, but you should be able to also patch the CodeCell
sadly my code needs a reference to the specific cell, so it’s not that easy. the functions only get the codemirror instance as parameter, and those don’t reference the cell.
sadly my code needs a reference to the specific cell, so it’s not that easy. the functions only get the codemirror instance as parameter, and those don’t reference the cell.
Use Jupyter.notebook.get_selected_cell()
?
that’s awesome! and i wasn’t insinuating that it goes too slow or something!
I was not trying to imply you were, just that it should move faster now, and that you should not get surprised if you see @gnestor around !
i wouldn’t depend on a newly added cell to be selected.
i think there should be “cell added” and “cell removed” events, right? right now i have to hook into the edit_mode.Cell
event which fires much more often
anywho: @ttimbers and everyone listening: now it works on newly created cells, too: IRkernel/IRkernel@c7d29566834343ebf70e8c339272bf618640a73d
Thanks all! This new feature is great!!! Not to get demanding, but could the same strategy be used to add a shortcut for the pipe (%>%
) in the IRkernel for Jupyter? The RStudio short-cut for this is "Control + Shift + M" (Windows & Linux) and "Command + Shift + M" (Mac) . I would say this is the second most useful shortcut in R, and again R users would be forever grateful to Jupyter for providing this...
THat might be hard for these specific shortcuts as the browsers do not allow to override all the shortcuts, and I think Control-Shift-M is one of the ones we can't.
OK, good to know.
could you link me to a list of RStudio shortcuts? i’ll try out which ones will work and which don’t.
do you like the F1 shortcut? :wink:
@flying-sheep here's a link to all the RStudio short-cuts: https://support.rstudio.com/hc/en-us/articles/200711853-Keyboard-Shortcuts
All will not apply to Jupyter. The ones I think that would be good to add to Jupyter can be found under the heading of "Editing (Console and Source)"
And the F1 shortcut to get the documentation of the word under the cursor is pretty darn nifty! Thanks for this feature also!
OK cool, I’ll have a look at those.
i always wanted that F1 thing, that’s why i was so happy that you pointed me in the right direction with this issue. (also big thanks to @Carreau of course)
for the record:
ShiftCtrl_N_ is lockend, …-M works.
it’s defined here, im summary, F11 to exit fullscreen mode and everything manipulating and navigating tabs or windows is blocked:
[Shift]Ctrl(Q|N|W|T|↹)
oh, @ttimbers: did i tell you that i eventually added all shortcuts?
since i use cm.findWordAt
, jupyter/notebook#1921 needs to be pulled in order for F1 to work on names.with.dots
Hey @flying-sheep et al - this is really awesome. It makes jumping from Rstudio to jupyter a breeze.
I was just wondering if you could also add the cmd + shift + M
which is the pipe (%>%
) shortcut on mac OSX. It's definitely the most useful shortcut and not the second-most @ttimbers :-p.
I just went and replaced in the kernel file, and it works fine ! But I don't know how to make it platform dependent. The alternative would be to add both.
sure! so it’s “'Shift-Ctrl-M'”?
I'm wondering if this topic can be extended to some functionality like 'hint' or 'abbreviation', where when I type a keyword (say 'hd' for header) with a enter then it will show up the whole text strings that I intended to insert into the code body.
I want to be able to add a keyboard short-cut within a code cell during editing. Specifically, I want to recreate RStudio's 'alt--' short-cut that results in an in-place text insertion of '<-'.
I have been playing around with using %% javascript magic to do this. With the code below I can manage to get
<-
output to the output area, but there are two problem with this:current code:
Any help to point me in the direction of getting this working to further develop this feature would be greatly appreciated (the plan is to add the final working code to custom.js so it works in all my notebooks). Additionally, such a feature would be desired by any R user using Jupyter. Thanks!