Ask HN: Does anyone still use code snippets?
Does anyone of you still use code snippets where you can type a shortcut and if you accept, it completes e.g. „fun“ to a function stub or has that all been replaced with AI-based completion tools like Copilot?
I noticed that I still like them and rely on them and was wondering if that’s the same for someone else.
Emacs is my editor, and I have it configured to use snippets in two ways:
1. When loading an empty file it inserts boiler-plate based on mode (largely that is based on the filename suffix). So if I open a buffer "t.pl" it will insert "#!/usr/bin/perl", along with "use strict; use warnings;", etc.
2. Completion for LSP-modes via yasnippet. So in golang mode I type "iferr[TAB]" and it expands into "if err != .." and moves my cursor to the proper spot when I type TAB.
For scaffolding? I still use snippets (with tooling ofc).
Around 85% of the time, it seems like it takes me more time to write what I want to code in natural language to an AI prompt (and then correct it) than it would to actually code what I want.
The 15% of the time when I want something like "Write test cases to cover this module" is something a snippet couldn't do anyway.
> Around 85% of the time, it seems like it takes me more time to write what I want to code in natural language to an AI prompt (and then correct it) than it would to actually code what I want.
That's how it should be, actually 100%. If you need scaffolding (and snippets) it means your language doesn't have (or worse, can't have) the right abstractions in its library.
I am generally fine with duplicating some of the "scaffolding" between projects to aid with readability and have less magic when trying to understand the code.
Eg. most languages would enable you to build a custom library, but then it becomes non-obvious what's exactly happening to someone diving into the project, a most engineers never bother fixing/improving the original library, and you end up with crap on top to "work-around" the poorly understood behaviour.
Eg. recently, I've fixed an internal library holding multiple locks around one tiny block of async code, rendering the entire thing synchronous, which was being worked around by devs using multiprocessing or multithreading for a couple years. I've reduced that library code to basically a couple of functions, but my preference would be to actually copy-paste those 200 lines into every component using it — while you have the problem when you want to update it everywhere, your average engineer focused on solving a different business problem will be better equipped to handle it.
My personal gripe is with the abuse of @decorators in Python, which are side-effect pits of hell (yes, the code can look really nice).
I personally don't use snippets, but I do copy-paste some of that scaffolding between projects (though I am mostly a manager these days and hardly get any time to code, so take that with a huge grain of salt) — snippets as such never added much value to me.
IMHO What you describe is mostly a tooling problem. Current tooling doesn't let users to see the referenced/abstracted code as simply as the local code (for example, expand function definitions). So people tend to avoid abstracting it.
You're correct it could mean that, but alternatively:
- the use cases covered by the language could be so varied that it would be misguided to expect special functions for each of those cases
- what one programmer describes as scaffolding could be seen as essential part of the setup for others. I have seen essential parts been called "scaffolding" by beginners who had no idea this was not just "text that needs to be there", but it had implications for the whole thing.
> have seen essential parts been called "scaffolding" by beginners who had no idea this was not just "text that needs to be there"
https://en.wikipedia.org/wiki/Scaffold_(programming)
Nothing about scaffolding pertains to how important it is.
A good usecase for LLMs seems to me to be the quick exploration of unknown codebases.
My issue with the code they generate is mostly that the style of abstractions chosen is inconsistent and seems to replicate whatever was the source at any given point. Programming is still about understanding what is going on, not about just writing code, so either way you need to put in the brainwork to understand it.
But as a "just show me an example"-helper it can save you a lot of time, especially if you load highly undocumented and convoluted codebases into it.
In some cases I had the LLM hallucinate functions that would have been wonderful if they existed, but hey.
I have a snippet I religiously use to scaffold the go error log + return. I’d say the amount of snippets I use are less, and maybe eventually I will use none. But with that one I want predictability. I don’t want to have to review every error statement as I build.
I use https://emmet.io snippets to save a lot of typing all the time:
- You can just type a CSS selector (actually a superset of CSS), then expand it into the analogous HTML.
- In VS code if you select some HTML then hit ALT-W, you can enter an Emmet snippet that surrounds that HTML.
Examples: https://docs.emmet.io/cheat-sheet/
It’s integrated into Sublime Text. I use this all the time.
All the time. I write a lot of typescript and don't enjoy typing out brackets, so I have snippets like:
`af` expands to `() => `
`naf` expands to `export const foobar = () => {};`
The expanded snippets can be tabbed through as well
It feels like a big timesaver
I tried using Copilot a bit, but I found it tried to do too much. As often as it got things right it got them irritatingly wrong. Something pared back giving context sensitive snippets would do fine.
You can swap it to only run on shortcut. You get used to when it will save you time / be accurate relatively quickly. It's a nice little autocomplete that saves me time- but I couldn't stand the automatic mode.
Ah, thanks. I will look for that.
Oh absolutely. Though moreso when writing documents in Org mode. It comes with some macros - for example <s will expand into the stub for a code block.
Huh... well, now that you mention it I realize my most common "type bit and have it expand" snippets are ones I made for certain temporary stacktrace/debug statements. I guess as a project matures you spend more time debugging or modifying what's already there. Even when those modifications are something the IDE helps with, that process is often triggered differently, highlighting existing text and using a refactoring menu/shortcut.
When I am working on new stuff... Well, my typing is mostly on autopilot, I use the time to think about what I'm going to put next, or else I've reached a spot where I would be making decisions anyway, e.g. naming a method.
I am using Alfred's Snippets feature. I have registered several snippets of GH Markdown and HTML.
note - gh:
> [!NOTE] > Highlights information that users should take into account, even when skimming.
ruby - html:
<ruby>WORD<rp>(</rp><rt>CAPTION</rt><rp>)</rp></ruby>
I mostly use them to create new React components (index.tsx, x.component.tsx, x.module.scss, x.types.ts).
I also use the nest cli to create new modules, services, ... which are king of snippets also.
I still use snippets and, since I wholly reject generative AI from my life, I don't see it changing anytime soon.
AI for search of your own snippets (or eg Xcode bookmarks) is nice even if you don't end up using any generative AI output in your code
Nothing bigger than a foreach/switch snippet that's built in to in Rider.
The rest I can just do with whatever AI I'm currently using, they'll usually guess the variables right the first time too.
Lots of them, not only fu -> function, but whole blocks of code with parameters (snipmate style). A few of half-pages of code and then dozens of little expansions, for many filetypes.
This is a result of a process I call experience distillation. I notice what code I write often but tend to either forget (bash) or outthink much faster than I can type (common syntax, libs, boilerplate), and routinely add it to snippets in hope that it sticks. Then I learn to actually use it. Once in a while I delete the unused or reshape it for second attempt with the understanding why it failed the first time.
Only for memoized boilerplate, and that’s the way I’ve used them since I realized I could do it. “AI” hasn’t supplanted the practice for me at all for me, and I’m still surprised that apparently it had for most people. I can insert a template faster than a round-trip to an LLM.
That’s not to say that “AI” assisted coding isn’t useful -in fact it can be indispensable. For me, the value is mostly it being a seemingly perpetually slightly drunk, yet prescriptive, pair coding partner.
I’ve set a couple up for more custom things that Copilot won’t have, but tend to forget about them and end up just grabbing the code from another file or readme files I previously wrote.
I think a lot of the standard snippets from years past were already taken over by things like IntelliSense, or various other IDE plugins.
I use only one snippet both before and after integrating copilot (provided by my employer) into my workflow, which is for creating a empty arrow function (in JavaScript / TypeScript.)
Copilot have not been able to generate arrow functions when I intend to, in my experience. I found it pretty incompetent, and unable to provide relevant assistance if there is any bit of abstraction. YMMV.
I reckon my need for this specific snippet could be replaced with a more competent agent. I recently subscribed to cursor and so far it seems promising.
This puzzles me. `arg => expression`, `(args, …) => expression`, `arg => { block }`, `(args, …) => { block }`… they’re not hard or long to type, and there are the different forms of argument list and body, so that I imagine you’d want more than one snippet (at least for expression versus block, considering some style guides say “always parenthesise argument lists”), and the entire thing seems not at all worth it.
> which is for creating a empty arrow function
you have a snippet for four characters? `()=>`?
There's also brackets. More importantly, it is easier for me to type `afn` than `shift + 9`.
Interesting, I have not found this to be the case. Can probably get yourself a foot pedal and crank out those arrow fn snippets.
Same for me, I use "ar <tab>" in Intellij all the time.
I do, via luasnip. I type some things a lot and it's just second nature for me now. The snippets I use most don't do a lot, but save me from hitting enter and typing 'end', or from closing a HTML tag.
I have some configured to enter the names of colleagues I've paired with to commit messages in the format GitHub expects too.
LLM doesn’t always produce the same output. It’s also isn’t mutually exclusive with code snippets: you can generate the template with LLM and reuse it with snippets.
I use QOwnNotes and I sync my notes on my own NextCloud. I have been trying different editors and tools in the past. I even used Google Docs at one point but that sucked. It's not just code snippets it's also one-liners for the command line that I do not want to research again. I am not using this feature in my IDE as I switch IDE's per project. For some I use NetBeans, some Visual Studio Code.
I use snippets almost exclusively in markdown/latex, where typing math is at least twice as fast with snippets.
When doing some quick experiment in C/C++, scaffolding `int main ...` and classes is nice too.
In nicer languages I use snippets only if I forget syntax, than snippet serve as a quick reminder(e.g. for loop in lua)
I use snippets off & on. They came in very handy at a previous company I worked with. Curious on the other answers because I've had some vague ideas for making snippets better but haven't looked deeper into what else is out there and a little wary of AI.
I find snippets really useful compared to AI because you have placeholders. You simply have to press Tab to switch from one placeholder to another and fill your snippet with your own values.
Additionally, AI doesn't know how to produce the same output on each execution.
In Visual Studio for C#, ctor creates a constructor. I use that one all the time. Other than that, no.
Yes, I'd rather keep them than have to go ask an llm, it would be an extra step.
I think of what I do as more "code generation" than "snippets" though I guess that's something of a fine line
Only few, most of the things are done now with AI.
No snippets, no LLMs, no autocomplete.
Eep on the autocomplete. For me that's a must-have to enable clear code. Calling SomeFunctionWithAReallyDescriptiveName would get pretty painful pretty quickly if I had to type it out every time.
No clue if it's true, but this is why I assumed a lot of older computing stuff is often abbreviated to the point of obfuscation.
For things you write a lot, learning how to quickly autocomplete them can pay off.
I don't autocomplete everything, as picking things from a list is if not slower then at least more annoying than just typing that thing, but for common things it's helpful. For instance I type "game.ReplicatedStorage" all the time, so taking a few moments to learn that "game.reso<tab>" is the same has saved time.
What upped my motivation to learned some shortcuts was switching from one keyboard layout to another (qwerty->colemak) and having 20-30 WPM for a week. Typing everything was so painful that I could doubly appreciate it.
Almost Iron-Man coding by todays standards...
Not really. It's how it should be, except maybe autocomplete. If your code is predictable, it means it has low entropy and you are not using the right abstractions.
At that point you may as well use a typewriter
This is the way!
I don't use an LLM in my editor whatsoever. I use snippets all the time for repetitive things and common expressions.
If I ever do use llms it's for searching for something like "what kind of expression is this called: (i = 0; I < x; i++)" so that I can do better research myself.
yes i do
we dont use AI at my work
Are local models accepted or just unpopular?
Of course I use snippets over AI.
With AI, you never know what you'll get. OTOH snippets were created by hand by me. I know what to expect of them and what not to expect. They are always the same.
I actually never really understood how to use snippets (and honestly never really tried). Before AI I just used whatever code generator functions there were in Intellij and with AI it's trivial to get scaffolding and boiler plate that isn't covered by those code generators. I still use the code gen stuff for things like getters and setters or constructors though.
I could never get the hang of snippets, too much to learn and too inflexible. Copilot for life.