My Developer Tools: Live with the R&D team

Brett Champion from Wolfram Research shows his Mathematica setup with VS Code, custom debugging tools like wiretap for tracing calls, and a persistent personal package that adds utilities to the front end. He walks through his docked toolbar, timing helpers, and how he keeps multiple Mathematica versions for development.
Chapters
Hello, welcome to today's R and D Live presentation. My name is Brett Champion and I'm the manager for the visualization team here at Wolfram Research. And today we're going to be taking a look at some of the tools that I use and settings that I have for using Mathematica in the Wolfram language. And so let's go ahead and dive right in. Let's see. So we'll start off with a couple of miscellaneous items. So my primary editor these days for writing large amounts of Wolfram language code is Visual Studio code with the tab with the Wolfram language plugin installed. And so this gets me syntax coloring as well as some additional language checks and feedback and that sort of thing. Magnify this notebook while we're thinking of it. And additionally I'd like to have lots of old copies of Mathematica installed. And for my purposes I keep a folder in my doc that goes Back to version 12.2, up to development versions and experimental versions and whatnot. And so that allows me to go back and compare behaviors with old versions or previous versions and do historical exploration a little bit more easily. And as for my day to day setup, pretty much everything I do is configured to live in a package. It's auto loaded at launch. And this includes things like front end preferences within the company. The, you know, my package has been in version control for more than a decade, so it originally lived in our on premise CBS server. And then a few years after that we transitioned everything over to git. And so that's, I included my package in that transition. And so at the moment what we have here is a view of the package. The package is named after me, Brett C. It has a front end folder with an init.in it. It has a kernel folder with a minimal init M. It has a scripts folder with a couple of scripts that I use. And then tools split into different files, some of which we'll look at or some of the tools we'll look at today. Some of the tools are things that I've used in the past but are less necessary now, but I haven't gone to the effort to remove them from my toolkit. Excuse me a moment. Okay, so let's start by looking at what sorts of things I do, what sorts of tools I have for working in the kernel. And most of these are geared around debugging types of operations. And so the first two are very similar. Wiretap and timing trap. And wiretap. I mean, and these are both similar in that they both Use the same trick, the so called Villegas Gali pattern, to, you know, overload existing functionality to make it easy to inspect. Um, so, so basically you have a flag, you have a definition for a symbol that has a flag. And if the flag is one setting, you're going through this block of code and then it flips the value of the flag, at which point your normal, the normal evaluation of the function happens. And so it's a little bit of recursion. And so what wiretap does is it allows me to see what the inputs to a function were, even if, you know, I don't direct, you know, I'm not directly calling it. And so let's. This has been a little bit finicky in 13.2 and I haven't debunked it yet. I think maybe there was a change to how some down value stuff was done. But so I happen to know that feature space plot calls list plot under the hood. And so if we. Let's just do a call to feature space plot first. Did that run? Just make sure it ran there. It did run. Okay. And so now I'm going to wiretap list plot, which I know is being used here. Now if I do my call to feature space plot, I get a printout of what the exact call to list plot was. And so this, you know, in some ways is a very targeted, you know, type of trace. You could do a similar thing with trace print, but I sort of find this easier and then it persists and I just go about using, you know, list plot or you know, something that involves list plot normally. And I see what the differences are, you know, what the arguments are, what the options are, that sort of thing. And then it also shows me what the result from listplot was. And then we get the end result from our feature space plot at the end. Similarly, we have a timing trap and rather than try to undo the wiretap, I'm just going to quit the kernel and get back to a clean state. So feature space plot also calls dimension reduce. And it's simplest form, feature space plot is basically list plot of dimension reduce of your data with some stuff overloaded. So timing trap is going to do a similar thing as to wiretap, except instead of seeing all the arguments to the function, it's just going to tell me how long it took. And so dimension reduce in this take took about a second, a little bit less, just it's varying a little bit. But it should generally be the case that dimension reduce is sort of the Largest component of how long feature space plot takes. Everything else should be relatively small compared to that. And so the nice thing about these two functions and a lot of the things is it works well with a lot of what I do, especially as the manager for the visualization team, is they're useful during development itself as well. But they're also especially useful for triaging bug reports. Or somebody says this version, the most recent version, or a couple versions ago, I'm getting this message or this wrong behavior. And then these are tools that I can use in the shipping version of the product to see what the behavior was and poke at things and get an idea for what was going wrong without going into full blown debug mode. Let's see. So it should mention these tools are not in any particular order. So there's a mix of things that I find useful for debugging. There's things I find useful for working on documentation or other types of exploration. So I have option names, which is similar to options, except it doesn't care what the values are, it only cares what the options are. So if I do options of plot, I get this big long list of things with all the settings. If I do option names of plots, I have two S's there, then I just get the names without the settings. And additionally this allows a second argument where I can say I can specify a pattern. So here are all of the options to plot whose names themselves start with plot or if I want to know what the image ones are. So there's obviously image size, but also image margins, image padding, and image size raw. So I use this a lot and this one actually lives in the Wolfram function repository. I submitted it to there. So you can use the same functionality. There's a similar function which doesn't yet live in the function repository, which is property names. And so this is used for especially useful for things like entities where. Yeah, for the US I'm going to ask for all the properties that match GDP and we get a long, if moderately sized list of these. Or I can ask for the property names that involve the word gross and you'll notice that there's overlap. So GDP is in both of these. And the reason is, is that it's searching multiple forms of that property to see what matches this string. And so it's in particular it's checking the canonical name, which is gross Domestic Product. It is sort of closer to, sorry, Gross domestic product is what. So if we mouse over this entity, you see that the actual form, the input form of this is entity, property of country, gross domestic product. And then the label form is just gdp and the label form is coming from common name. And so we search both of these so you don't have to be quite as accurate in how was it phrased? Because sometimes it's very clear mapping from the common name to the canonical name and sometimes they look very different. And so this will search both of those forms. Another function which I wrote a long time ago is skeleton form. I find this especially useful for working with graphics. And it basically condenses down arrays of things. It is not perfect. And there are, you know, newer constructs in the language that I haven't yet taught skeleton form about. And so if I say skeleton form of plot, I see that it's graphics. And I've got an annotation for internal implementation purposes. We've got a directive RGB color. Yeah, thickness. We've got a line that is 565 tuples, pairs of numbers. And then we've got 25 options that are set. There are similar things in the function repository, so they're. I mean, at least there may be more. There is short input form which adds some syntax coloring for things like annotation that aren't visible, I think. And it, in this case it shows all the options rather than just saying, ok, there's a bunch of options and there's iconized view which takes the arrays of things and turns them into iconized forms with a description so that you can see what the structure is, but still have, I mean, be able to copy this out and do actual inspection on it. Whereas skeleton form is just a general structural thing and it. You'd lose the information about what the actual values are, that sort of thing. But I find this useful for sort of comparing what changed from one graphic to another, or finding where there's now an extra level of lists or something, or some other hard to spot change in structure and you know, the output of plot or something. Let's see. Then we'll look at doc Source. This one is really specific to me, but I included it because to some extent I think the concept isn't unique to me. So this is a function that takes a symbol name and opens the authoring notebook for the documentation for it. So if I look at Doc source of plot, then it opens this notebook that contains the raw version of how we author documentation for the Wolfram language. Obviously other people aren't going to be able to directly edit documentation for the Wolfram language, but there may be other sorts of things that you have that are very specific to you that you want to open. You have a collection of Excel spreadsheets or something that you want easy access to the path or to make it easier to specify their file names or something or any number of things. And I mean the great thing about Wolfram language is that you can extend it in this way and you can add your own functions and have the model load. And all these functions that you've seen me use so far are just there every time I launch Mathematica ready immediately to be used. I don't have to take any additional steps to, you know, using get or needs or something to use them. They're just there. And that's very convenient because when the just there, then you use, I mean, they're easy to use and you use them more. So this is Full Stack. And so to demonstrate this, I have a little package here. It's not the most interesting function, but I'm going to evaluate the sample code. So we have begin package. We're going to define a function that's called Random Scene. The implementation of this is going to be a little bit split up. So Random Scene of n is a 3D graphic of random tubes of N and random tubes of N is just this implementation. And so let's stick a. I think that should work that just for good measure because so if we evaluate this, then we evaluate Random scene of five. It didn't work. I got a message. And if I click the dot dot dot on the in front of the message then one of the things that we have here, yeah usually is Show Stack trace. And I use this a lot, I use Show Stack trace a lot to see where our message is coming from, what might be going wrong. Ok, so we've got a bad iterator non list iterator in a table. There's the table. If you imagine, you know, this package being a larger function or larger file, there may be multiple tables in that package. And this doesn't necessarily tell me how I got there. And the reason it doesn't is that by default the stack trace is pruned in a couple of ways. One is that it has a maximum byte count that it will of things that it will put on the stack or include in the stack trace. And, and two, it won't put a frame on the stack trace if it involves symbols that aren't in dollar context I mean that aren't on the context path. And so I have a function called Full Stack which disables that pruning. And now if I look at my stack trace. After having done that, I'm able to see more of the stack trace. So I can see that, you know, above the, the problematic table, you know, that was coming from, you know, probably this foobactic private backtick random tubes function. And now I know where to go look in a little bit more detail. And so this function is useful for package developers, package authors who need to trace the code into the internals of their definitions and stuff. So I'm going to go back up and fix this because I want to use random tubes. Let's see, there's that. Ok, that should be good. Now we can run this again. Random scene of five gives us five randomly colored tubes. And so this is going to lead us into two other functions I have as convenience things which are functions called OpenGL and metal. These are the main two 3D renderers we have on Mac OS, which is my primary platform. You could write similar functions for Windows or Linux using the renderers that are, you know, available or specific to those platforms. So direct 3D or Mesa or whatnot. And basically all these do is they say, you know, they specify how the front end should try to render, which rendering engine the front end should try to render the images with. And so I'm going to have, hahaha, interesting question. Is there a way to time how long the front end takes to render an expression? There is, and we're just about to get there. So here I have a scene it's effectively using, I guess it's not actually a little bit more complicated version of the random tubes. We've got a thousand random tubes, they've got random colors, random diameters. And if we make this a little bit wider we see that, you know, if I use Metal or if I use Open gl, they render pretty much exactly the same as far as I can tell. I haven't spotted any differences in these two images. And while we're here I'll point out another trick. So I wrapped this list in a style with image size multipliers goes to 1, 1, which means that the images won't shrink by default. So normally if you have a list of graphics, then they're magnified down a bit by default. And if you have them inside of a function then they get even smaller still. And you know, those two magnification scales are coming from this setting are coming from image size multipliers. And so this just is temporarily disabling that. I have not yet made a function to do this. You know, maybe I would have full size As a function name or something that was an alias for style of whatever common image size multipliers goes to 1, 1. But anyway, so on Mac we have metal and OpenGL as our main rendering engines for 3D. And they look the same, but there, you know, are differences in timing, you know, sometimes, sometimes there's differences in appearance as well. But so here I'm using an internal function called graphics backtick render timing, which is very much geared toward graphics, graphics, 3D type things. So it took a twentieth of a second to render the scene. And if I compare the timings for OpenGL and for metal, it's pretty clear that we're using Metal by default on Mac. I mean, there are some cases where a particular feature may force one renderer over the other. So if you're using some of the newer directives like blurring or shadowing or hat shading, those types of things, those will always use the OpenGL renderer because that's the place where it's implemented at the moment. And so, but I mean, this is a useful tool working with graphics for being able to tell how long something takes to render. I'm going to switch now to away from, you know, kernel stuff so much to scripts that I have installed in my package and we'll look a little bit at one of them. I'm not going to get into it in too much detail because it's a lot of code. It's, you know, specific to stuff that, you know, only applies in, you know, on the premises at Wolfram. And so. We'll look at one script. This is an installer script that installs a new version of Mathematica for me. So if I come here and I haven't check to see if this is going to do anything, but let's do Minstall Proto and so it's going to go off, check that there is a new build, it's going to start downloading the build, you know, all sorts of stuff. And the interesting thing is that, you know, sort of the convention that we've adopted within the company, or at least several of us have, is that the script that we use is very minimal. It has a little bit of boilerplates, you know, check that something is defined and then it calls that thing that's defined. And this function is written in top level Wolfram language. It's actually living in this file. You can see from the mini view that this file is much longer. This is the main part of it. And it's, you know, does some argument handling for the script. You know, allows some help features, that sort of thing. And the reason we set it up this way originally was that we were doing this for a packlet. And so the question is, you install the packlet, it comes with the script. You need to put your script on your path somehow. And so what we decided is we'll have the script itself be very lightweight and just call a function and then you can copy that script into your user, local bin, directory or wherever is appropriate for your system. And then if the packlet updates, you don't have to recopy the script. As long as we haven't changed what the calling function is, you know, the, the pack letter of the package could get updated multiple times and this block of code will still function and still do the right thing. Will it even do the updated thing? And so that's the reason that, you know, my script is, you know, sort of the script itself is very minimal. And then all the actual implementation is living somewhere else that allows for updates and whatnot. And so if we switch here, you know, now we have, it's finished, it downloaded and installed, it's unmounted. The drive that Mathematica was on, you know, all cleaned up to profiles gone. And you know, for the most part this was all written in top level Wolfram language code using file operations and that sort of thing with reasonably robust error handling. For did this copy succeed? Did you know, was there a build to install in the first place? That sort of thing. Let's see. So we'll come back here now we're going to look at my front end Edit M and so we'll peek up here. And this is, you know, I'm going to set a few things. There's not a lot that gets set on the front end side of my setup. There's a placeholder toolbar that gets put in place. I set up some remote evaluators, some alternate kernels so that I can run them from a notebook more easily. And then there's a few options I set. And these method options, you know, at the end here are the default settings. But, you know, we had an internal tool that liked to set message settings without always reliably setting them back. And so this just makes sure that every time I launch, you know, the system I get default message settings. And so we'll look at a few of the things I have. So the Doc Cell, you know, this is just a placeholder that starts out, you know, if necessary, and then it eventually gets replaced with the actual Doc Cell that you see up here as Long as things are working as they should be. One setting that I've used for literally decades and I find very useful is setting Evaluation Completion Action goes to show timing. And so if I do table, I don't actually see the results. So that took a little bit of time. But you know, how much did, how much time did that take? I forgot to wrap timing around it. And even if I had wrapped timing around it, then I would have the time comma, the value. And you know, that might complicate code that I want to do afterward. So I have this setting set in my option Inspector via my INIT M. And what that does is after every evaluation, it puts a little thing down in the corner that shows how long that evaluation took roughly. So that was 1.85 seconds in this case. If I do another evaluation, then that was pretty much instantaneous and I lose all ability to come back to see how long this one was. So there's no history to it, but it's sort of useful. For how long did that take? Sorts of questions or you evaluate something that you think should have been quick, but it instead takes a long time and. You abort it. And it's like, okay, I waited two minutes for that and still didn't get a result. And so I have this on all the time and I look at it multiple times a day. Additionally, let's see, in terms of auto completion, I use auto completion all the time. I was a religious user of auto completion pre version 6 when you had to manually invoke it with Command K or Control K. That keyboard shortcut is burned into my, you know, it's muscle memory and I still use it today even, you know, even though it's mostly not necessary. But one thing, one variation that I do have is, and this is an experimental feature right now, but it's, you know, it's not going to crash your front end or anything, which is to use a fuzzy matching algorithm. And what the fuzzy matching algorithm does is that I can write, I can type something like, let's scroll this DNZ or DNS plot or pl. I'll use Command K to bring the completion menu back up. And now I get a set of symbols that sort of match that. So density plot, density plot 3D, but also list density plot, even though I didn't start the L to start with. Likewise for geodensity plots, those sorts of things. I'm not going to go into what the rules are for what gets included in the completions because it's experimental and a little bit in Flux. But yeah, I can do that. I can do. If I do sdh, it's going to find smooth density histogram for me, even though I had no capital letters in that. And so this is a feature that's common in a lot of other environments and has been under development here with sort of various rounds of refinement, adjusting, And so feel free to try it out. And I should say that sort of the things that I'm showing you right now, the easiest way to initially set them is to bring up the option inspector and. Search for them. So if I search for like, matching algorithm, you can see that I'm set to fuzzy. The default is automatic, I guess. I don't know what binary or linear are. You know, if I search for. Evaluation complet. Right. So evaluation completion option has to be set at the notebook level at least. I guess you can have show timing or you could have it beep when it's done evaluating, or add a timestamp or scroll to the output. But I find show timing by far the most useful of the settings there. I mean, that said, you could have multiple of them. So there we have, you know, when that was evaluated and how long it took, which might be useful for some people. Excuse me. And then the other option I want to mention is one that I don't run by default but use occasionally, which is show frame rate counter. And so if I turn this on for this particular notebook that I do. A 3D plot, it's going to put a frame rate counter up here. I don't trust these numbers terribly, you know, other than like order of magnitude comparisons between things. So I'm getting allegedly about 60 frames per second rotating this plot on my screen at the moment. But it can be useful for, like, if things feel sluggish of, you know, sort of either confirming or confirming that, or checking to see whether it's sort of more in your imagination than not. So. So now we're going to look at my toolbar as the final customization that I have, and my toolbar is mine. Feel free to make your own toolbar with whatever functionality is most useful to you. As a bit of background, originally, I did not have a toolbar. Originally. What? So the motivation originally was that if I bring up my app switcher, which, okay, is going to show up on the stream, I mean, you see that I have 1, 2, 3, 4 copies of Mathematica open at the moment. And then the question is, which window is in which version, etc. And so in order to distinguish sets, you know Windows by what version they were running. I originally had startup code that would randomly set the background color on an instance. Yeah. So, I mean, it would literally do. Current incision. And so, you know, at the time, we didn't have random color, so it'd be like Q random. Probably didn't even have random real at the time. And then. I got something backwards. Tells you how often I use the second and third arguments of hue. Okay, I wanted the other one. So every notebook would have a different pastel color to it, Which was really useful for being able to tell, okay, here's all my version 5, here's all my version 5.1 type of stuff. It turned out to also be really useful for detecting when the kernel had crashed because the color was random and it was being set during kernel startup. And so if my kernel crashed, then it would rerun this code and all my notebooks would go from pink to blue or whatever. And then when we got docked cells, it was like, okay, we can be a little bit more sophisticated than that. And so then I started constructing a Doc cell and putting it at the top of the notebooks and using color still to identify things. And so, as I mentioned before, I have four copies of Mathematica running at the moment, and they all have different toolbars. Pastels are still sort of mainline, intended for release types of builds, and they have, you know, dark colors on pastel backgrounds. The prototype builds have white, white elements on more vibrant colors. White on gray are things that I've built myself. So they aren't automated builds in any way. And then if you remember, at the very beginning, the front minute, M set up a toolbar, and it's just a very basic one here. And, you know, so what happened in this case is at the time that I launched this front end, I didn't have any more kernel licenses available at that point. And so because the kernel couldn't start, it just put this in place. And so this has two buttons, you know, remove the toolbar and add the toolbar. So it should be the case that if I click on that now, I think I have the license available. And we can see that this is a version of 12.3, you know, an old version of Mathematica. So as for what I have in the toolbar, See, like I said, it's a lot of things that are specific to me or specific to things within the company. And so I'm not going to, you know, show you all of my toolbar code because it's not going to be useful for the most part. So the first section is various files that I want to get to. Relatively easy. So this is like a. This is kind of like open recent, except it's more like open important and things don't age out of it as you open other notebooks. This tells me where this is. You know what build this is. You know where it lives on my file system. So this is in the 13.2 directory of my Mathematica's folder. So this is 13.2, 8 0-85764 or 8. 4, that version of Mathematica. This one is telling me what the build number is effectively gets duplicated with that. But it also has a tooltip on it that has a sort of a more detailed but short form of what the build is. And it's a button that I can click and then paste, which is useful internally for reporting, you know, bugs because I can put this in an email or a bug report for qa and they know exactly what build that is. It's a Mac build 13.2 and that's what the. What the build ID for it is. This tells me what day the build is from. If I mouse over it, I get the time as well. These three buttons are window resize, types of things that are less useful these days. But it used to be that Mac OS would not automatically resize Mathematica windows when you dragged them from one screen to another. And so what you would have happen was that if I was on, like, if I created a notebook on a large screen and dragged it onto a smaller screen, parts of it might be off screen, especially the corner that made it easy to resize, which I mean also was at, you know, in the era when Mac OS did not allow you to resize from any edge. And so this was designed to sort of always bring, you know, this corner into, you know, make it fit on, you know, the screen that the notebook was on. This button is a copy paste or thing. So let's. Do it. Not going to try to do it with that. But. So if I have let's do. This thing, then this uses some code from Stack Exchange that will. Let's ignore the timestamps that I added on copy in a form that is suitable for pasting into something like Stack Exchange or Community. So it has, you know, for, you know, everything is for space indented to get it into the pre formatted code type. The result is commented out. You know, it's not trying to do anything with the superscripts or the fractions. And so this would Go. You know, this is your sort of text safe for some environments that I use semi regularly. Public is a drop down menu that is letting me choose which instance of a Wolfram cloud I want to be using. This button just puts in a little timestamp or date stamp I should say for notebooks where I want to know when I started working on them. This brings up these dashboard that we use for interacting with git. This will rasterize output. So if I, you know, think that something is big or I don't I want to have it locked in place, I can select this, hit this button. Do I have to select it that way? Oh, it's actually the smart one I think. Right. So. So this is what is using an internal is using the same rasterization basically as what we use for documentation so that it rasterizes if it would save space and doesn't rasterize otherwise. And then this is the little share icon that uploads the notebook to a shared file system. Which I'm not going to click because I can't remember exactly what the path is off the top of my head. I don't do it quite often enough. And so those are, you know, the toolbar contains things and operation, you know, information that I need or want and operations that I want to do, you know, fairly regularly. And let's see. So there's a question. Can the toolbar have dynamic elements, for example, a slider. There are limitations on doc cells and I have to admit I don't exactly remember what they are. So my answer would be try it. I mean there are certain. So there are buttons here, there's tooltips here. Tool tips are, you know, partially dynamic. You know, this is a pop up menu or maybe an action video I think. I don't know if we have anything that has sliders. Yes, they can involve sliders because. Is that has a slider unless it's not actually a slider. But. But I mean this toolbar does have something that looks like a slider. So you should be able to use sliders in your toolbar. Let's see. So how is the toolbar made? Let's take a quick look at it. So toolbar actually lives in this file. And we'll see if I can find where the below it. Or above it. Okay, so my implementation of it is that I have a function that if evaluated we'll do set options on front end session. So the difference between dollar front end and dollar front end session is that if you set options on dollar front end it will try to write that out to your event M&$front end session doesn't try to save the states when the front end exits. It's just a, you know, it's just for that launch of the system, not everything after it. And so this prevents like the notebook coming up and initially saying that it's 13.0 and then flipping to 13.2, for example. And then what I do for constructing these things is the docked cells have to be cell objects. I mean, you know, cell type things, box up, you know, box language things. And so I put in, you know, the, the initial part. So cell of box data. And then I use two boxes to convert normal types of things, normal language constructs into the necessary boxes. And so I use a grid to lay everything out because then I could have dividers between certain things. There's a docked cell style that I use for the cell object that sets a little bit of color and font type stuff. And then I overload the font because I like this particular font. And the background is obviously telling me information about what type of build and what build it is. And so we come back here. So let's do a little example of constructing a toolbar. And yeah, I'm not going to do this entirely from scratch, but hopefully from this you'll sort of get an idea of what the process is whenever I've have something that I want to add to the toolbar. And so, You know, as, as the simplest case, we're just going to put, you know, something very basic in the toolbar. So, you know, in this case I'm gonna, I'm using current value doc cells equal instead of set options DOC cells goes to. They're roughly equivalent. Either one will work. And in this case I'm doing it for just this window, not the entire front end session. So, you know, so cell box data, two boxes and then have my grid construct and I'm just, you know, having a rogue with the word hello in it. Yeah, so I'll evaluate that and you sort of see what the, you know, doc cell style gives us. It's just a little bit of text, light gray background, that sort of thing. So, so let's look at having some real content for, For our toolbar. And so what I'm going to do is I'm going to add a button that is going to open a documentation source notebook for me. So it's going to be using this doc source function that we looked at earlier. And so we have a bunch of code here. And I mean obvious, I Am not going to make any claim that I wrote this code in this, you know, in this direction. You know, there were little tests of, you know, how does this work? You know, refreshing my memory, you know, so notebook read of button notebook. It was after me testing notebook read a little bit. So I have a pause five notebook read. So if I have. If I evaluate this and I have nothing selected, what's going to happen after five seconds? Okay, notebook read returned an empty list. If I evaluate this and select input form, you know, it read input form. And if I look at the input form of that result, we see that it's actually the string input form. That's fine. Doc Source is going to work with that either way. You know, at the moment, I have not dealt with anything like, you know, what happens if I have a list or, you know, something more complicated. And, you know, dealing with those cases would just, you know, make this longer in obvious ways, and it would just sort of depend on what Doc Source was able to take. You know, maybe it should be able to take a list of things. I think at the moment it doesn't. It's very simple. But it's not a function that's being used for production use anywhere. It's just my little utility. And hopefully I know how to use it or I know what cases I'm planning to use it in. So we're going to read the selection from the notebook. If the selection is empty, if we haven't selected anything, then I'm going to. I'm going to put up a dialog and ask for something. So what happens if I hit cancel? Okay, that is going to return canceled. If I click that button, that also gives me canceled. If I do plot, that gives me plot. And I think in this case that's the string form. I mean, the symbol form, not the string form. I could use input string instead. But I know that Doc source works on either the string or the symbol form of the name. And so we're gonna do. We're gonna put up a dialog. If we have don't have something selected, we're gonna go through the selection. If it's not canceled, then we're going to call doc source on the selection. And if something was selected, then we're in this branch of the code and we're going to call Doc source on the selection. And so I'm going to stick that in a function. And so I have that function. I'm going to make it the argument of a button. Usually for my toolbar, I create little graphics in black and white or white that can be made in black and white or white and black. In this case, I'm just using a red book emoji since the front end supports emoji now. And that's a lot faster than creating a little graphic. And I'm going to put a tooltip on it because I like things to have tool tips to help me remind, help, remind me what an abstract little picture does. So we do that. I'm gonna test it out. You don't have to construct things this way, but I find it more efficient to do it this way and easier to test, easier to sort of double check how things are, build things up before sticking it in the toolbar and having to keep reloading a kernel or whatever to see the changes. Ok, so I select something, I hit the button, there's the documentation source notebook for notebook read, nothing selected. It's going to pop up the thing. I hit cancel, nothing happens. I do this, I do density plot 3D. There's that notebook, Everything's looking good. A couple of additional comments. For this button, I've specified the appearance to be none because for the most part that's how things, how icons work in toolbars. You don't tend to have a lot of extra chrome around them, which is what would happen. And the button has to be. Queued in this case because it can't be done preemptively. If it was preemptive, then, you know, input would run into trouble because it would like, you know, try to time out and kill the evaluation before you had a chance to actually type anything in the input field. So now that we have doc button, I'm going to come up here, change. Hello to doc button. Now I have the button in my toolbar. You see that the, this is more complicated than what was put here. But if I do pause and I hit this, there's the docs for pause, etc. And then, you know, going from there, you add, you know, things to your toolbar as you feel the need for them. As you find yourself doing things a lot from within the system of whether it's, I want, you know, to open doc, you know, certain documentation pages regularly or certain notebooks or applying styles or pasting, you know, some sort of content or something, whatever you find useful. I mean, the programming is sometimes a little bit more advanced because it tends to get into more front end programming that people aren't necessarily as familiar with. You know, in terms of, you know, reading from state or writing, you know, programmatically writing things into a notebook in a specific place or something. You know, that sort of thing isn't necessarily what people normally are programming in the language. And so it may be a little bit of a learning process. But don't start by trying to write the entire toolbar. I'm familiar with the box language, and I wouldn't try to write, you know, in this form. You know, I wouldn't try to write tag, box, grid, box, and blah, blah, blah, blah, blah. You know, we have two boxes that does the conversion for us automatically and make use of that. So I think that covers about most of the things I wanted to cover. See if we have other questions that I can answer for a few minutes. Let's see. So there's one question, you know, unrelated to my tools, but related to my day job, so to speak, how to create an image of nested concentric circles of varying color. Now, so, okay, so it's going to be a graphic, and we're going to want multiple circles. So let's make a table. And we're going to have circles, and we're going to have colors, and the colors are all going to be different. So we're going to need to group the color with the circle. Let's just use random color for now. And then we'll do a circle. We need to specify what the origin is because we want to control the radius. We'll just do the radiuses. Circle that. Okay, so we're in there. We'll say the Radius goes from 1 to 10, and then we have, you know, sort of nested concentric circles. If the, you know, and then you can do things like, you know, change with the thicknesses. So. Absolute thickness, say 3. So this will be about 3 points thick. All of them get a bit thicker. And if you have some other way of how you would compute the colors for the I circle, this would change appropriately. And let's see. So I think that looks like about all the questions we've had so far. Hopefully people found this enlightening and useful, and possibly everybody was waiting to see how I did the toolbar. And I hope that was relatively easy way to follow. And, you know, with the toolbar, start small and build up, you know, there were points, you know, so the initial toolbar was basically just, you know, information about the build. So, you know, where it was, what the build number was when it was made, and then as I felt the need or desire to have more functionality available at the click of a button, you know, I'd spend half an hour here and there writing a bit of code or figuring out how to do it. So, so cool. And thank you for watching. Enjoy the rest of your day. And, and there will be, you know, additional R and D live streams in the future. If you like this type of, this type of content of, you know, what people do to make the system their own and useful for them, let us know and maybe we'll have more with other people contributing what their setups are. So thank you very much.
More from Guy

Cheryl Strauss Einhorn | The Human Edge: Smarter Decisions in the Age of AI | Talks at Google

Rachel Glennerster | Innovation and the Center for Global Development | Talks at Google

Rebecca Winthrop | Rethinking the Purpose of Education in the Age of AI | Talks at Google

Dr. Robert Wachter | A Giant Leap: How AI Is Transforming Healthcare... | Talks at Google






