Tumgik
#it also just appends the post you make directly to the top of the currently-displayed posts behind it even if it's not meant to go there
front-facing-pokemon · 8 months
Text
Tumblr media
#RIP to the legacy post editor. you will be missed. while queueing this post and the last one it's removed the option for me to switch to the#old one and is making me use the new one. which is like not bad. it's not a bad editor. i just don't like change as most tumblr users don't#it also just appends the post you make directly to the top of the currently-displayed posts behind it even if it's not meant to go there#which is a little bit scary when i'm on the queue page and i click “add to queue” for a post that's supposed to go up on august 18th#to see it immediately appear above mega metagross. the legacy post editor didn't do that. it made you refresh the page if you wanted to see#your own new post on the dashboard. which i think was better!! honestly!! i've never Made a post using the new editor to see how it behaves#only ever queued up FFP using this thang. but that's also bc i feel like i don't post very much. i need smth Interesting to say when i post#on my main blog i mean. i don't make extraneous posts on here (usually) unless i'm answering an ask or something. which. still have yet to#miss one to this day. going strong#bibarel#can you tell idk what to say about this guy. what are they‚ water-type? big chance i'm fucking wrong and they're just pure normal#OKAY i was right. normal/water. semi-interesting typing and i get why they're a water-type. but. i never use. bibarel. even as a kid who#didn't understand or care about competitive. i knew bibarel was not very strong. it's a route 1 normal-type fucker. and maybe it's like#better than i think or something but tbqh it's a sinnoh 'mon and i already have another sinnoh water-type that has my heart. buizel#so bibarel was not so much in the cards for me. bro i should do like. a mono-type run of a pokémon game one day. that would be fu#do folks do that? is that a challenge run that actually exists? nuzlockes exist so i don't see why not. okay i'm doing it. my next replay o#any pokémon game is hereby decreed to be a water-type mono-type run. i may or may not liveblog it on my main blog#and it may or may not be nuzlocke. we shall see#hell maybe i'll stream it. maybe that could be fun. i don't know of *anyone* who would be interested in that but it tends to help me#actually go about completing games when i have someone there like. waiting for me to do so
49 notes · View notes
readevalprint · 4 years
Text
Previewing images in and out of SLIME REPL
As any Common Lisp coder knows, a REPL is an incredibly useful tool. It can be used not just for development, but for running all sorts of tasks. Personally, I don’t bother making my Lisp tools into executable scripts and just run them directly from SLIME. As such, any operation that requires leaving the REPL is quite inconvenient. For me, one such operation was viewing image files, for example in conjunction with my match-client:match tool. So lately I’ve been researching various methods to incorporate this functionality into the normal REPL workflow. Below, I present 3 methods that can be used to achieve this.
Open in external program
This one’s easy. When you want to view a file, launch an external process with your favorite image viewer. On Windows a shell command consisting of the image filename would launch the associated application, on Linux it’s necessary to provide the name of the image viewer.
(defvar *image-app* nil) ;; set it to '("eog") or something (defun view-file-native (file) (let ((ns (uiop:native-namestring file))) (uiop:launch-program (if *image-app* (append *image-app* (list ns)) (uiop:escape-shell-token ns)))))
Note that uiop:launch-program is used instead of uiop:run-program. The difference is that launch- is non-blocking - you can continue to work in your REPL while the image is displayed, whereas run- will not return until you close the image viewer.
Also note that when the first argument to run/launch-program is a string, it is not escaped, so I have to do it manually. And if the first argument is a list, it must be a program and a list of its arguments, so merely using (list ns) wouldn't work on Windows.
Inline image in REPL
The disadvantage of the previous method is that the external program might steal focus, appear on top of your REPL and disrupt your workflow. And it’s well known that Emacs can do everything, including viewing images, so why not use that?
In fact, SLIME has a plugin specifically for displaying images in REPL, slime-media. However it's difficult to find any information on how to use it. Eventually I figured out that SWANK (SLIME's CL backend) needs to send an event :write-image with appropriate arguments and slime-media’s handler will display it right in the REPL. The easiest way is to just send the file path. The second argument is the resulting image’s string value. If you copy-paste (sorry, “kill-yank”) it in the repl, it would act just like if you typed this string.
(swank::send-to-emacs '(:write-image "/path/to/test.png" "test"))
Tumblr media
You can even send raw image data using this method. I don’t have anything on hand to generate raw image data so here’s some code that reads from a file, converts it to a base64 string and sends it over SWANK.
(with-open-file (in "/path/to/test.png" :direction :input :element-type '(unsigned-byte 8)) (let* ((arr (make-array (file-length in) :element-type '(unsigned-byte 8))) (b64 (progn (read-sequence arr in) (cl-base64:usb8-array-to-base64-string arr)))) (swank::send-to-emacs `(:write-image ((:data ,b64 :type swank-io-package::png)) "12345"))))
Note that the first argument to :write-image must be a list with a single element, which is itself a plist containing :data and :type keys. :data must be a base64-encoded raw image data. :type must be a symbol in swank-io-package. It's not exactly convenient, so if you're going to use this functionality a helper function/macro might be necessary.
Image in a SLIME popup buffer
Inline images are not always convenient. They can't be resized, and will take up as much space as is necessary to display them. Meanwhile EMACS itself has a built-in image viewer (image-mode) which can fit images to width or height of a buffer. And SLIME has a concept of a "popup buffer" which is for example used by macroexpander (C-c C-m) to display the result of a macro expansion in a separate window.
Interestingly, slime-media.el defines an event :popup-buffer but it seems impossible to trigger it from SWANK. It is however a useful code reference for how to create the popup buffer in ELisp. This time we won't bother with "events" and just straight up execute some ELisp code using swank::eval-in-emacs. However by default, this feature is disabled on Emacs-side, so you'll have to set Emacs variable slime-enable-evaluate-in-emacs to t in order for this method to work.
Also Emacs must be compiled with ImageMagick for the resizing functionality to work.
Anyway, the code to view file in the popup buffer looks like this:
(defun view-file-slime (file &key (bufname "*image-viewer*")) (let ((ns (namestring file))) (swank::eval-in-emacs `(progn (slime-with-popup-buffer (,bufname :connection t :package t) (insert-image (create-image ,ns)) (image-mode) (setf buffer-file-name ,ns) (not-modified) (image-toggle-display-image)) ;; try to resize the image after the buffer is displayed (with-current-buffer ,bufname (image-toggle-display-image)))))) ))
Arriving to this solution has required reading image-mode's source code to understand what exactly makes image-mode behave just like if the image file was opened in Emacs via C-x C-f. First off, image-mode can be a major and a minor mode - and the minor mode is not nearly as useful. slime-with-popup-buffer has a :mode keyword argument but it would cause image-mode to be set before the image is inserted, and it will be a minor mode in this case! Therefore (image-mode) must be called after insert-image.
Next, the buffer must satisfy several conditions in order to get image data from the filename and not from the buffer itself. Technically it shouldn't be necessary, but I couldn't get auto resizing to work when data-p is true. So I set buffer-file-name to image's filename and set not-modified flag on.
Next, image-toggle-display-image is called to possibly resize the image according to image-mode settings. It’s called outside of slime-with-popup-buffer for the following reason: the buffer might not yet be visible and have any specific dimensions assigned to it, and therefore resizing will do nothing.
Here's an example of how calling this function looks in Emacs.
Tumblr media
The position of the popup buffer depends on whether the original Emacs window is wide enough or not. I think it looks better when it's divided vertically. Use M-x image-transform-fit-to-height or M-x image-transform-fit-to-width to set up the auto-resizing method (it gets remembered for future images). Unfortunately there's no way to fit both height and width, at least with vanilla Emacs. I prefer fit-to-width because in case the image is too tall, it is possible to scroll the image vertically with M-PgDn and M-PgUp from the other buffer. Unlike other image-mode buffers, this buffer supports a shortcut q to close itself, as well as various SLIME shortcuts, for example C-c C-z to return to the REPL.
That’s it for now, hope you enjoyed this overview and if you happen to know a better way to display images in Emacs, I would be interested to hear about it.
2 notes · View notes
Link
 Creating an XEvent session
Creating a new XEvent template, now called a session, can be done in different ways. One of the ways is to create the session with a SQL statement, while this has become easier than before we're going to use the GUI because this is still simplest.
To create a new session, open the Management folder and then Extended Events. Now, right-click on Sessions and you'll see that you have two options to create a session, New Session and New Session Wizard. The only difference that I can see is that the user interface is a little bit different but the end result is the same. Just keep in mind that the user interface to edit a session is the same user interface as using the New Session wizard, that's why the following images are all made with the New Session option.
Tumblr media
The first screen asks for general info, and you got the option to start from a predefined template. For now, we'll stick with a blank template.
Tumblr media
On the second screen, Events, we select the events that we want to capture. Because I'm interested in the query performance, I select the rpc_completed and sql_batch_completed events.
Tumblr media
With the Configure button in the top right corner, we can open a new window to include the fields we want to append to the captured event. Besides the default fields, I've also added client_app_name, collect_system_time, database_name, sql_text, and task_time. This has to be repeated for each event.
Tumblr media
Sometimes we're only interested in a subset of the captured, for example if we only to capture queries with a high read count. To exclude events in the event log, we can add a filter via the filter screen.
Tumblr media
The third screen allows us to store the captured events. This can be helpful if you want to capture events for a longer period without having the live view on. Besides the option to save the raw event data, you also can save an aggregated view of the data, for example in the form of a histogram.
Tumblr media
The fourth, and last, screen is the advanced screen. For me, the defaults are fine.
Tumblr media
Live view
With the session configured, we can open up the live data view by right-clicking on the created session.
Tumblr media
This opens up an almost identical view of the beloved SQL Profiler. When the events have occurred, it will be shown on this screen.
Tumblr media
At first sight, this doesn't look as useful as the SQL Profiler. To display more data, select an event and this will open a detailed view at the bottom. Right-click a field row to add it to the live data view table.
Tumblr media
This gives us the following result, a view like we're used to with the SQL Profiler.
Tumblr media
To display the same view the next time you open the data viewer, save the current display settings.
Tumblr media
To edit the session, right-click the session and click on Properties. This opens the same wizard as before, where you can make modifications to the existing session.
Target data
It's also possible to start a session without the live view. Because we're storing the captured events to an even file we can view and analyze these events in the Target Data view. To open up this view, right-click the event file and select View Target Data. This opens the same view as the live data view.
Tumblr media
My setup
As I said at the start of this blog, it's also possible to create a session via a SQL statement. The SQL statement below is the exported version of the session created in this blog post.
CREATE EVENT SESSION [Tuner] ON SERVER ADD EVENT sqlserver.rpc_completed(SET collect_statement=(1) ACTION(package0.collect_system_time,package0.event_sequence,sqlos.task_time,sqlserver.client_app_name,sqlserver.client_hostname,sqlserver.database_id,sqlserver.database_name,sqlserver.plan_handle,sqlserver.session_id,sqlserver.sql_text,sqlserver.transaction_id)), ADD EVENT sqlserver.sql_batch_completed( ACTION(package0.collect_system_time,package0.event_sequence,sqlos.task_time,sqlserver.client_app_name,sqlserver.client_hostname,sqlserver.database_id,sqlserver.database_name,sqlserver.plan_handle,sqlserver.session_id,sqlserver.sql_text,sqlserver.transaction_id)) ADD TARGET package0.event_file(SET filename=N'Tuner') WITH (MAX_MEMORY=4096 KB,EVENT_RETENTION_MODE=ALLOW_SINGLE_EVENT_LOSS,MAX_DISPATCH_LATENCY=30 SECONDS,MAX_EVENT_SIZE=0 KB,MEMORY_PARTITION_MODE=NONE,TRACK_CAUSALITY=ON,STARTUP_STATE=OFF) GO
Conclusion
When I read that the SQL Profiler was deprecated, I was worried because it was one of the tools that I knew I could always rely on. I was worried that the new profiler wouldn't be as good as the old one. Now, that I've been using XEvents and the data view for a week, I feel reassured. From now on, I will use XEvents and the data viewer instead of the SQL Profiler and I'm looking forward to the tricks that I haven't discovered yet.
It isn't a big change in terms of using the profiler. If you're used to working with the SQL Profiler, you will be able to use the new data view in just a couple of minutes. I've spent most of the time into setting up the session to replicate the setup I was using with the SQL Profiler. When I was happy with the initial setup and stared to use the data view it felt like I was using the profiler back again, but then directly in SQL Server Management Studio instead of in a separate profiler window.
For more info, see the Extended Events docs, and the official guides.
Improvements
I'm also happy with the improvements they made to the data view, where we can do more than before. With the SQL Profiler, we had to import the collected events before we could analyze the captured data properly. Now, it's all baked into the data viewer:
it's possible to sort the data view when we stop the live data feed
the data view can be grouped (via Grouping and Aggregation in the toolbar at the top), this can give us a useful overview really fast.
Tumblr media
using XEvents doesn't impact the performance of the SQL Server as much as it used to be. Personally, I never experienced hiccups when I turned on the SQL Profiler, but according to the docs, the XEvents aren't as heavy on the server.
selecting events and fields now have a search box, making it easier to create a session
it's easy to track events with the saved (aggregated) data from a session and gain insights of the system, for example if you want to track deadlocks
0 notes