Often in Jupyter I'd move to different parts of the notebook to look at something, and when I am done I want to jump back to where I was working on previously. Right now I'd have to navigate to the closest Markdown section (through the Jupyter Notebook Extensions) and move up or down to get to where I was. Is there a way to jump directly to the last cell that I have made an edit (preferably through keyboard shortcut)? Thanks!
Ideally this would be a built-in shortcut of course, but in the meantime:
Option 1: Custom JavaScript
If you get a browser extension like Custom JavaScript for Websites 2 (open-source), then you can use this code to record a stack of scroll position histories and jump backwards with Ctrl+Shift+X:
// Visit JupyterLab in browser and click the Custom JS browser extension icon and then paste this:
if(location.href.startsWith("http://localhost:8888/lab")) {
let scrollLocationsHistories = new Map();
let scrollBinHeight = 100;
window.addEventListener("keydown", (e) => {
let notebookEl = document.querySelector(".jp-mod-searchable .jp-NotebookPanel-notebook");
if(!scrollLocationsHistories.has(notebookEl)) scrollLocationsHistories.set(notebookEl, [])
let scrollLocationsHistory = scrollLocationsHistories.get(notebookEl);
if(e.ctrlKey && e.shiftKey && e.key === "X") {
if(scrollLocationsHistory.length > 0) {
e.preventDefault();
let origScrollPos = notebookEl.scrollTop;
notebookEl.scrollTo(0, scrollLocationsHistory.pop()*scrollBinHeight);
let newScrollPos = notebookEl.scrollTop;
if(Math.abs(origScrollPos-newScrollPos) < scrollBinHeight && scrollLocationsHistory.length > 0) {
notebookEl.scrollTo(0, scrollLocationsHistory.pop()*scrollBinHeight); // jump back again because last edit position was close to current position
}
console.log("Scroll History (newest locations at end):", scrollLocationsHistory.map(v => v*scrollBinHeight))
}
} else if(!e.ctrlKey && !e.shiftKey && document.activeElement.tagName.toLowerCase() === "textarea") {
let scrollBin = Math.round(notebookEl.scrollTop/scrollBinHeight);
if(scrollLocationsHistory[scrollLocationsHistory.length-1] !== scrollBin) {
scrollLocationsHistory.push(scrollBin);
if(scrollLocationsHistory.length > 500) scrollLocationsHistory = scrollLocationsHistory.slice(-250);
}
}
});
}
It's just an initial prototype, but it seems to work quite well so far. You may want to adjust it a bit - e.g. scrollBinHeight causes nearby edits that are within scrollBinHeight pixels of one another to not create a second history entry. You'll need to edit http://localhost:8888/lab to match the URL that you want to enable it on. If you're reading this long after I've written it, then you may also need to change document.querySelector(".jp-mod-searchable .jp-NotebookPanel-notebook") (i.e. the main scrolling element of the active notebook) in case they've updated the HTML class names, or HTML structure.
Option 2: Fold Often
Another possible option (which may be impractical depending on your use case) is to get used to folding cells that you're not currently working on. That makes it much easy to quickly scroll between cells that you're working on.
Option 3: Search Hack
If you're working on a particular cell but often have to jump to another one, you can add a comment like #vv (or any random easy-to-type string) to both of those cells and then whenever you need to jump between them, just press Ctrl+F and then Enter. The first time you do this you'll obviously need to type vv in the search box, but after that it'll be remembered (unless you use the search for another string). The disadvantage of this approach is that you need to "prune" the #vvs from cells that you're no longer working on.
echap to go to command mode, then Ctrl + z will undo your last change, which will bring the focus on the last edited cell. ctrl + y will redo the last modification.
(Only tested on python3 kernel)
EDIT Actually if you press ctrl + z just once, you only get the focus part, without modifying your cell. Then press enter to go to edit mode, which scrolls the page to the active cell.
Related
Pls help me
A few weeks ago it came out of gamemaker 2.3, practically in the gamemaker language they changed the scripts into functions, but now after converting the files to be able to reopen them, I double-checked all the scripts and etc but anyway when I start it it remains a black screen, however it doesn't give me any compilation errors or whatever, what could be the problem?
Ps.
I might sound stupid, but if someone has the same program as me I can pass the project to them so they can see the scripts for themselves, so basically it's just the base and there is only the script to make the player walk and for collisions, I know that no one would want to waste time, but I ask the same
Its possible that your code is stuck in an infinite loop, here's an example of what that might look like:
var doloop = true
while(doloop == true){
x += 1
y += 1
}
the "doloop" variable is never changed within the while loop, so it is always equal to true and the loop never ends. Because the code never finishes looping, it can never get around to drawing anything, so you end up with a black screen. The easiest way to check for these is to put a breakpoint/debugging point at the beginning and just after every while/for/do/ect loop and debug it. e.g. (I am using asterisks "*" to represent breakpoints)
var doloop = true
* while(doloop == true){
x += 1
y += 1
}
*
When you get to one of the loops remove the first breakpoint and hit the "continue" button in the debugger. If it (it being the computer) takes an longer than it should to hit the second breakpoint (as in, you wait for a ten seconds to or two minutes (depends on how complex the code is) and it still hasn't hit the second breakpoint), then you should replace the breakpoint at the beginning of the loop to check and make sure it is still in there. If it is still in the loop, then that is likely where the code is getting stuck. Review the loop and everywhere any associated variables are set/changed, and you should be able to find the problem (even if it takes a while).
Majestic_Monkey_ and the commentors are correct: use the debugger. It's easy and it's your friend. Just place a red circle on the very first line of code that runs, and click the little bug icon and you can step through your code easily.
But to address your specific issue (or if anyone in the future has this issue): scripts have changed into files that can have many functions. Where you used to have
//script_name
var num = argument0 + argument1;
return num;
You would now have
function script_name(a, b) {
var num = a + b;
return num;
}
All you have to do is create a decleration for your new function:
function my_function_name(argument_names, etc...)
Then wrap all your old code in { }, and replace all those ugly "argument0" things with actual names. It's that easy. Plus you can have more than one function per script!
Is there a way to get the next or previous tag in AwesomeWM Lua Config?
Reason :- I want to get the next or previous tag to set the focused clients tag to it and then move to the tag.
I know there is awful.tag.viewnext which moves to the next tag but unsure about how to get the tag it will move to to set this on a client.
Thanks in advance
Well... yes, there is a way, but there is not a completely trivial one.
First, let's look at the default config. What existing functionality has to get next/previous tags? That is the mouse wheel on the taglist:
https://github.com/awesomeWM/awesome/blob/7a759432d3100ff6870e0b2b427e3352bf17c7cc/awesomerc.lua#L160-L161
So, how does awful.tag.viewnext and viewprev get the next tag? These functions just call viewidx with an idx of 1 or -1, e.g.:
https://github.com/awesomeWM/awesome/blob/7a759432d3100ff6870e0b2b427e3352bf17c7cc/lib/awful/tag.lua#L1494
So, awful.tag.viewidx can do what we want. How does it do it?
It gets a table of all un-hidden tags, finds the index of the currently selected tag and then uses gears.math.cycle to compute the index of the tag with the requested offset.
https://github.com/awesomeWM/awesome/blob/7a759432d3100ff6870e0b2b427e3352bf17c7cc/lib/awful/tag.lua#L1452-L1469
For you, something like the following should do the trick:
function get_tag_at_offset(i, s)
s = screen[s or awful.screen.focused()]
local tags = s.tags
local showntags = {}
for _, t in pairs(tags) do
if not awful.tag.getproperty(t, "hide") then
table.insert(showntags, t)
end
end
for k, t in ipairs(showntags) do
if t == sel then
return showntags[gears.math.cycle(#showntags, k + i)]
end
end
end
The above function can be used like get_tag_at_offset(1) to get the next tag and with argument -1 for the previous. Where possible, I would recommend to also pass in a screen via the second argument.
Also, all of this is completely untested and just written on the spot. There could very well be typos and other mistakes in here.
So what I currently want to do is pretty much implement rofi in awesome.
The reason I want to do this and I don't just use rofi is because I want to learn how to 'auto-generate' widgets in awesome.
This will come in handy later when I'll implement things like network widgets that when clicked, shows you a panel, shows you the wifi hotspots available as rows, etc etc. So it's just for me to learn how awesome works better. But also, I want a program launcher.
And also, before someone suggests it, I already know that there's a built-in launcher in awesome, and I also know that there's this. This is not what I'm looking for. I want to have the same thing thing rofi and dmenu have: I want to have suggestions pop up when you press keys. and I want to be able to click on the suggestions, etc.
What I want is something like this: uhhhh
So what I'm having problems is this: how do I auto-generate the rows? I want to be able to specify in only one place how many rows I want, and have awesome do the rest.
I've looked through Elv's github and I found radical and even though what he made is a menu system, I thought that I could use some of his code to do what I want. But I can't for the love of god figure out how it works. No offense to him, but it's not all too well docummented, even for users, and for actually explaining how the code works there's no docummentation.
So My question is: How can I make this work? How would I go about making the widgets that act as the rows automatically?
TL;DR:
i want to write a program launcher like rofi in awesome
i want to be able to specify only in one place the number of rows
therefore, (((I think))) I need to automatically generate widgets as rows somehow, how can I do it?
EDIT:
What I want is to be able to create the rows of my launcher automatically. I know I can hardcode the rows myself, have each row have a different id and then I can write a function that on each keypress, will update each widget with the most relevant matches. So it would be something like (not tested at all):
local wibox = require("wibox")
local awful = require("awful")
local num_rows = 10
local row_height = 40
-- set the height of the background in accordance to how many rows there are,
-- and how high each row should be
local prompt_height = row_height * num_rows
local prompt_width = 300
-- make a widget in the middle of the screen
local background = wibox({
x = awful.screen.focused().geometry.width / 2 - prompt_width / 2,
y = awful.screen.focused().geometry.height / 2 - prompt_height / 2,
width = prompt_width,
height = prompt_height,
bg = "#111111",
visible = false,
ontop = false
})
local rofi_launcher = wibox.widget({
widget = background,
{
-- get a flexible layout so the searchbox and the suggestion boxes get
-- scaled to take up all the space of the background
layout = wibox.layout.flex.vertical,
{ -- the prompt you actually type in
-- set id here so we can adjust its ratio later, so the magnifying
-- glass will end up on the right, and the texbox will take up the left side
id = "searchbox_and_mangifying_glass",
layout = wibox.layout.ratio.horizontal,
{
-- set id so we can use it as a prompt later
id = "searchbox",
widget = wibox.widget.textbox,
},
{
widget = wibox.widget.imagebox,
icon = '~/path/to/magnifying_glass_icon.svg',
},
},
{ -- this is where I actually create the rows that will display suggestions
{ -- row number 1
-- make a background for the textbox to sit in, so you can change
-- background color later for the selected widget, etc etc.
widget = wibox.widget.background,
{
-- give it an id so we can change what's displayed in the
-- textbox when we press keys in the prompt
id = "suggestion_1",
widget = wibox.widget.textbox,
},
},
{ -- row number 2
-- background, again
widget = wibox.widget.background,
{
-- id and textbox again
id = "suggestion_2",
widget = wibox.widget.textbox,
},
},
-- and another 8 (according to the `num_rows` variable) of the same two
-- textboxes above. This is exactly my problem. How can I make these
-- textboxes automatically and still be able to interact with them to
-- display suggestions on the fly, as the user types keys into the prompt?
},
},
})
If this is not clear enough please do let me know what you don't understand and I will update my question.
Equally untested as your code, but this creates a tables of textboxes instead of using the declarative layout to create all these textboxes:
[SNIP; For shorter code I removed some stuff at the beginning]
local textboxes = {}
local widgets = {}
for i = 1, num_rows do
local tb = wibox.widget.textbox()
local bg = wibox.widget.background(tb)
bg:set_bg("#ff0000") -- The original code did not set a bg color, but that would make the bg widget useless...?
tb.id = "suggestion_" .. tostring(i) -- This is likely unnecessary, but the original code set these IDs, too
table.insert(textboxes, tb)
table.insert(widgets, bg)
end
local rofi_launcher = wibox.widget({
widget = background,
{
-- get a flexible layout so the searchbox and the suggestion boxes get
-- scaled to take up all the space of the background
layout = wibox.layout.flex.vertical,
{ -- the prompt you actually type in
[SNIP - I did not change anything here; I only removed this part to make the code shorter]
},
widgets
},
})
-- Now make the textboxes display something
textboxes[3].text = "I am the third row"
textboxes[5].text = "I am not"
This is what Standard Editor looks like:
This is what Assistant Editor looks like:
This is a problem because whether I click on the eye icon or the + next to (6 times), it shows me a graph only: I was wondering if there would be a way to show more useful output?
Edit: When I show the debug area, it doesn't show any output there:
You can access the console by the menu
View > Debug Area > Show Debug Area
There's also a little upper arrow icon in the bottom left of the Playground, and the SHIFT+CMD+Y shortcut.
In the console you will be able to see not only the error messages but also anything you print.
To be able to see the output in the preview panel you have to place the statement you want to see on a separate line, and break down the logic on separate lines up to some point.
In your case, for example:
let arr = [1,2,3,4,5]
let triple = arr.map({
(i:Int) -> Int in
return i*3
})
Here with let triple ... not being on the same line as the closure anymore, the Playground is able to preview it.
And by clicking on the + on the right side, you can now unfold the special panel where all values are visible:
Ive started using Aptana 3 today and really like it,
However I'm struggling to find out if I can code fold to specific levels.
For example I can push Ctrl+Shift+Divide and will collapse EVERYTHING imaginable.
Including the class.
lets just say my doc is as follows:
class Kill_model extends Game_Model{
function shoot(){
//code
//code
//code
//code
//code
}
function respawn(){
//code
//code
//code
//code
//code
}
function spectate(){
//code
//code
//code
//code
//code
}
}
The default will collapse to
class Kill_model extends Game_Model{}
I've been using PHPEdit in the past, and like to "Fold to Level 2"
This gives me the appearance of
class Kill_model extends Game_Model{
function shoot(){}
function respawn(){}
function spectate(){}
}
I was wondering if its possible to just fold down to level 2, by level 2 I assume it means 2 levels deep. Level 1 = Class, level 2 = functions within.
Many thanks.
Ok, so level folding is available in Aptana, it just isn't built into PHP editing, only Source editing. To add it to PHP, you can go to Commands > Source > Edit this Bundle, and the Commands > PHP > Edit this Bundle and copy Source/commands/folding.rb to PHP/commands/folding.rb (this will be a new file). If you do not have Option and Command keys (Mac, I believe), you will want to change the keybindings in this file to something else, like Control and Alt. You will find the keybinding in the folding.rb file looking something like this:
with_defaults :input => :none, :output => :discard, :key_binding => "OPTION+COMMAND+0" do
and a second time like this:
cmd.key_binding = "CONTROL+ALT+" + level.to_s
Just change the OPTION to CONTROL and the COMMAND to ALT, and you will have a new Ctrl+Alt+ shortcut once you restart Aptana.
See my second answer for more direct info... I thought I'd leave this one in case it helps someone with a similar but not quite the same problem...
I can't speak for the keyboard shortcut because I don't know where numpad_divide is on my laptop (no numpad) - but if you look under Window > Preferences > Aptana Studio > Editors > PHP, you can choose to initially fold "these elements" - if you check "Functions" I think you may get the folding you are looking for. However, I do not think this preference will affect the behavior of Ctrl+Shift+Divide aka Collapse All.
There is also a command to collapse the current block (Ctrl+Numpad_minus) but I think this would be less useful to you.
You may also find the Quick Outline helpful, if you are looking for a short overview of the available classes and functions in your file. This can be accessed with Ctrl+O (or right click > Quick Outline).
Edit: Playing around with Aptana today I found, under Commands > Source > Folding > Toggle Foldings at Level > Level <x>. There appears to be a shortcut associated with each level, Alt+1, Alt+2, etc. but it doesn't work for me. I also don't see an option to configure a shortcut for these commands, but you can theoretically make your own.