Ask HN: Programmers who don't use autocomplete/LSP, how do you do it?

355 points by zackoverflow ↗ HN
I am totally fascinated by programmers who don't use many of the IDE features I take for granted today: autocomplete, language servers, and recently copilot

So to the devs who don't use these tools, how do you do it? Do you just remember every type and field in a codebase? What does your flow look like?

One example is that I cannot live without the language server go-to-definition feature. What do you do if you need to look up the definition/implementation of some function which is in some other file?

651 comments

[ 4.3 ms ] story [ 158 ms ] thread
Yes, lots of memorization with an occasional Google search. When you program a lot you just remember things.
More specifically, when you program a lot on your own without these tools, you just remember things.

Using a concise language and style helps, too.

I use vim with ctags. vim has good autocomplete but I don't use it much -- I rely on memory and looking things up in the docs. With ctags I can jump to definition/implementation of a function.

ctags has worked since the early 1990s.

Check out this video: How to do 90% of what plugins do with just vim.

https://youtu.be/XA2WjJbmmoM

Same. ctags all the way!
I'm curious: what language are you working on where ctags are useful?

I spent years fighting with those to try to have a satisfying setup that worked, but found ctags to be high maintenance (always breaking in some way, not context-aware on untyped languages, index getting obsolete quickly and taking forever to update...), and I never looked back since trying coc.vim.

I've used it extensively with c++, rust and python, and to a lesser extent with a handful of other languages

Non context aware is a problem. For python I had to add `--python-kinds=-i` to `~/.ctags` so that it ignores imports when generating the tags.

I've also bound `<leader>t` to `:tn<cr>` and `<leader>r` to `:tp<cr>` so I can easily go back and forwards between tags if there is more than one match.

(comment deleted)
I've found that regular non-language-aware autocomplete is sufficient for me, plus recursive greps through repos. Referencing my app's data structures in another editor window is useful too.

I use JavaScript and Python. Because they are dynamically typed, I never had full confidence in IDE-like tools in my text editors. I see those languages as flimsy foundations to add IDE tooling to, I would always experience situations where the editor had no idea what type something was. So I stopped bothering entirely.

I don't use any of these out of ignorance first, laziness second, and incompetence third.

I didn't know about them, and I had spent a lot of time with the documentation and code of everything I touched (language, dependencies, etc). Looking things up reinforces this. The value of a feature such as autocomplete is marginal to me as a function of the effort I have to make to learn how to use it properly, the frustration of using it improperly, and the added steps to fix a blunder, so I just don't bother with it.

I also have a habit of having the documentation/book/code of a dependency open nearby and doing my look-ups there.

A lot of time is spent refining existing code, debugging, optimizing, refactoring, etc...

I remember getting excited about zsh plugins that do this and that. More recently, fancy neovim plugins with demos on YouTube. Only to try them and they don't fucking work. Even cloned directly from their repo, there's always a missing dependency or font or program they need. Such a frustrating waste of time.
On the other hand, plugins imply a plugin architecture which means we can make our plugins that others could hate on. It is how life goes :-D
CS department at my alma mater was very, very theoretical and we were encouraged to just write code in text editors. After that I got into programming for CAD software which had rudimentary editors as well. Basically I just memorized a bunch of stuff and always had a second monitor with the docs open. These days I use autocomplete but I still largely code the same way, and for better or worse I’m set in my ways — at least when I’m using libraries I’m familiar with. If I’m messing around with something completely new then sure, I’ll make extensive use of autocomplete.
Earlier in my career, I would often turn those features off. It was the late 1990s, and computers were much slower, and as a result, I didn't like the lag that some of those features would cause. As such, I learned to work without them.

These days of course computers have no issues. However, I've moved to a completely Docker Compose driven workflow, but for various reasons, I've run into issues getting LSPs etc working correctly. From time to time I'll take a stab at getting it working again, with some success, but rarely do I have that kind of free time (I typically work on small teams)

Just FYI: in some languages (like Go iirc) you need to add the subfolder of your monorepo to the workplace in order to LSP to work properly, at least on VSCode.
(comment deleted)
Thanks, I'll take a look and see if that helps.
For me it is actually a disturbance, especially autocomplete. So yes, I need to remember stuff, but if I cannot or just don't know the codebase, I look it up very quickly and then can learn more from looking at the specific code.

At the start of learning rust I used a bit more help from the IDE, but now not anymore.

For me it is just easier to have a much deeper knowledge instead of "only" have knowledge about the tools. A good example was when I used SVN back in the days, I only used a GUI and always struggled if something does not work out. I had basically no idea, what is really going on. So when Git became the new normal I forced myself to use the command line only and because of that I can always help myself (with Git atleast :D).

Certainly not something for everyone, but it works for me :).

Same as driving in the city without Waze. Replying to an email in German without Google Translate. There are a bunch of reasons, one of them is because I like it.
You should try turning off those features yourself for at least a month and see what happens ;) You’ll learn the answers yourself, much better than us trying to explain them.

You’ll learn where all the reference docs live for your language, libraries, and frameworks, and along the way you’ll learn more by actually reading the docs.

You’ll learn the value of good project organization and file naming, and explicit import statements.

And you’ll learn that the speed of typing, even long method names, is not the limiting factor of your productivity.

I use Rust, so explicit imports are required. However, I fail to understand this point

> You’ll learn where all the reference docs live for your language, libraries, and frameworks, and along the way you’ll learn more by actually reading the docs.

With neovim/LSP, I have a key binding (Kg) that opens a small window within the editor with the rustdocs. Not only this is faster than going to the browser, typing the type name, opening the docs, looking up the method but also it ensures that I am looking at the docs of the correct version that my code base is using.

I don't really understand the aversion to using these tools. They are "auto-complete" and not generative complete. This means you need to know what you are going to type for them to help you.

Do you have your neovim config public?
Not really, as I have API keys and other stuff in it unprotected. However, I used this as a base (https://github.com/ayamir/nvimdots) and heavily modified it. There is a user directory (lookup the user_template) where you can config everything out of the base.
If you browse through the doc, you will find yourself reading the doc.

If your code editor looks up the doc, you find yourself reading what the code editor shows you.

Wikipedia, (real) historians have some aversion to using it. No argument, it is convenient.

Which is why I mentioned that I am coding in Rust. They are the same docs.
I think the point they are making is that you only read what is shown you instead of seeing the full docs and being encouraged to follow rabbit holes and browse nearby info. Speaking for myself, this has been one of the largest boosters in my own career: visits to a docs page that led to me basically reading the whole docs.
I am not sure if we are speaking about the same thing. LSP can give you type hints. What I am doing is that I am opening a "window" in my editor that has the full docs. You can browse through it freely. The issue with "non-Rust" languages is that the docs will be on a website. On most Rust projects (90%+), the libraries will use the Docs system which makes the docs fully available on LSP.
I believe the distinction is that if you have to manually browse the docs and navigate to the method of interest, you might see something else interesting along the way.

Whereas if your editor takes you directly to the method in question, you miss that opportunity.

If I want to read through the doc, I'll just do that, and I frequently do it with all dependencies that I'm directly interacting with. As fun and informative as it is, personally I don't want to do this exercise every time I need a peek at the documentation of a class or function, in the same way I don't take a detour into the mountain every time I get out of my house, as much as I enjoy hiking.
> The issue with "non-Rust" languages is that the docs will be on a website.

We have tooling for offline docs of course. See dash (macOS) or zeal (win/linux)

> you only read what is shown you instead of seeing the full docs and being encouraged to follow rabbit holes and browse nearby info.

I can use a convenient shortcut to go as deep as I want in the codebase, including libraries. Meanwhile crowd with clinical case of tool aversion will spend time fuzzy-searching and manually sifting through text.

Who's encouraged to explore more?

(comment deleted)
> I don't really understand the aversion to using these tools

No one is yucking your yum, it's not an aversion, it's that we don't need them, it never really occurs to us to use them, just like it never occurs to you to not use them. You make it sound like people who don't use them are fumbling and tripping over themselves and aren't actually writing any software.

> it never really occurs to us to use them, just like it never occurs to you to not use them.

This doesn't really make sense, either. How do you not consider the right tool for the job? Do you just use whatever you learned to code and never really bothered to consider that you might be more or less productive with different tools? LSPs don't always offer a productivity increase in all contexts—they seem to be mostly useless for dynamic languages like ruby and lisp and javascript—but I have a hard time imagining a programmer that couldn't benefit from them in the right context.

And they're just a straight-up improvement from iterative compilation and ctags, the latter of which never really worked very well in the first place.

My great-grandmother never used a mixer when making cakes or bread, long after mixers were available, and she was able to pump out treats and full meals without batting an eye, the best anyone ever had.

I don't have a problem with my "productivity", whatever that means. I'm not trying to write code faster, my own experience is that writing code faster leads to shitter code. I'm not hindered by my tools, and most of my programming time is spent thinking and understanding, and none of these tools have afforded me better thinking or understanding, and often times they get in the way of my thinking.

Yes, very zen. How does your pairing partner feel about this?
> I'm not trying to write code faster, my own experience is that writing code faster leads to shitter code.

I'm wondering who these programmers are who are sitting down for eight hours a day, pumping out perfect code at 200wpm without any breaks. I suspect they might not exist.

I was more suspicious that they refuse to engage in the concept of productivity at all. Why bother using computers in the first place, then? There are more beautiful things in the world to contemplate than code.
Your typing speed is not the limiting factor in productivity. You have to think carefully, plan a solution, then put out code without errors. Not using LSPs helps you accurately model the code in your head ahead of time and increases your accuracy. It's slower at first but much faster in the end. Because your typing speed was never the limiting factor in your productivity.
I didn't setup the tool to write code "faster". I setup the tool mostly to reduce RSI because I wouldn't need to use the mouse as browsing docs with vim only uses the keyboard. I do agree that you can't write code "faster"; whatever that means but that was never my purpose.

You should give these tools a try. From my perspective it's like someone sitting on a small wooden chair and you are proposing an Aeron. Yes, they are both chairs and you'll be sitting and perform the same task but boy the ergonomic chair will save you from some real back-pain.

> wouldn't need to use the mouse as browsing docs with vim only uses the keyboard

I recommend adding a Vim keybindings extension to your browser.

> I setup the tool mostly to reduce RSI because I wouldn't need to use the mouse as browsing docs with vim only uses the keyboard.

Meanwhile some of us already had setups broader than that in scope: I use vim, a tiled window manager with vim-like keybindings, and Tridactyl to control Firefox with vim-like keybindings. Can do just about everything without touching the mouse, including browsing HN and other sites.

(comment deleted)
I also cook and bake and I am using a mixer. And other tools too, like a food processor, a thermometer, scales, a dishwasher. Could I make do without them? Sure, as I have in the past. I understand my tools and how to apply them; I chop small amounts of ingredients and I don't wash my knives in a dishwasher. But I recognize the value of the tools. With them, my results are consistent and higher quality.

Plus, I have more time and energy for writing code later. Or other activities.

I admire consummate professionals who can immerse themselves in the craft. I can't do it. I still put out great work - definitely not the best ever - and the tools lessen my mental and physical burden. I have more energy that I can spend elsewhere.

We replaced the punchcards and terminals and line editors with different tools because the trade-offs were worth it. Maybe we can keep adapt new tooling in a similar matter when it makes sense.

i avoid using autocomplete because it forces me to think about every single thing i’m doing.

every line of code is a liability. every line of code needs to be thought about. every line of code is precious.

spamming autocomplete means i’m not thinking about what i’m doing, even the simple stuff like writing a for loop statement.

I don't use autocomplete, either. Most of what an LSP gives you is more data to scan semantics faster.

> every line of code is a liability. every line of code needs to be thought about. every line of code is precious.

I personally think this is ridiculous. It's code. It's just formal instructions. You process them and move on. It's not describing the face of god. If you need to think so much write less clever code.

Great, another pragmatic programmer producing sphagetti
Code is read more often than written. It's not make the computer do something and done.

The right kind of clever results in "oh, it can be that simple?", not "what the hell is that line noise?"

it’s nice to be able to fall asleep and someone else does the reply you wanted to do. you saved me a job. =p
That doesn't mean you stare at it in stupefied awe. If you can't remember what you're working on you close your computer and walk away.
i never said i stared at code in a stupefied awe. that’s your stuff, not me.

the point i was trying to convey with the phrases was my ideal attitude when writing code.

this code matters. lets think about it, get it done right and not throw it over the fence for the poor schmuck who comes along in two years time after we’ve all left.

i’ve been that schmuck. it was horrible. i don’t want to put other people through that. ever. (this is now my stuff, but hopefully explains some of the attitude).

our attitudes, intentions and motivations count when it comes to code quality. look after your code and it will look after you.

that’s what i feel. you feel different? that’s fine.

What does this have to do with a language server? It is not a tool that blinds you, nor one that puts a gun to your head and forces you to ship prematurely.

I'm just very confused how the conversation took a turn away from pragmatism and towards the aesthetic.

> > every line of code is a liability. every line of code needs to be thought about. every line of code is precious.

> I personally think this is ridiculous. It's code. It's just formal instructions. You process them and move on. It's not describing the face of god. If you need to think so much write less clever code.

you called my attitudes to writing code ridiculous. i thought i’d provide you some information on why i hold that attitude. maybe it might help you understand. maybe you may consider your own attitudes as a result.

it seems to me that you are not ready yet.

> This doesn't really make sense, either. How do you not consider the right tool for the job?

The thing people keep trying to explain is that when it comes to this stuff, there isn't a "right tool" for every job and every programmer. You like LSPs? Great, use 'em. You don't like them, and you can be just as productive without them? Great, turn 'em off.

So many people yelling at each other over personal preferences. It's not enough to have the tool and use it, you need everyone else to use it too? Why? To validate your own use of the tool? If you really truly believe it gives you an edge, great. I don't think it gives me one, and anyway, not everyone fights with the blade.

One group sees the other as a person backpacking with a bespoke gadget for every little thing, wearing a 60lb rucksack while they are wearing a 20lb ultralight pack and have a multi-tool that serves 90% of their needs.

One group sees the other as a person with a reel-mower proclaiming they don’t need a tractor mower, while they can mow much less grass a day.

Both groups are right, and both are wrong. Depending on what you’re doing, it can make sense to use heavyweight tools, lightweight tools, little tooling, or lots of tooling. If you’re hired into a big codebase written over the course of ten years, skipping tools that will help you make sense off it is probably not the right choice. If you’re building a system from scratch, then those same tools might inoculate you to the dangers of having a poorly organized codebase. If you need to debug a server remotely, bring productive in vim and basic command line tools could be invaluable. But if your debugging stuff, you could have saved yourself hours by turning on a debug port and stepping through the code in a debugger.

The arguments everyone is having look to be about whether it’s worth it to learn how to use tools. The answer is yes, but everyone has their identity caught up in their pet workflows.

Personally, the biggest benefit I get from LSPs is just proactively letting me know compiler errors before running the compiler (and I miss this working in extremely dynamic situations, like macro-heavy lisps). I definitely would side-eye someone who willingly eschewed that. But the rest of your points are well stated from my perspective
Yeah I use LSPs in vim and this is where I've landed.

Really great for quickly showing you errors and providing passive feedback. I also autocorrect linter errors on save.

But everything else about how I do work is basically unchanged; I haven't found autocomplete to be worth it.

And then you'll turn it back on and feel the lifting of a significant mental burden.

Autocomplete has never been about the speed of typing things, and always about finding and recalling abstractions that you sort of know but haven't committed to strong memory yet.

Or for switching between many languages without having to work on remembering if it's lowercase, lower, tolower, lcase, or to_lower this time.
(comment deleted)
>And you’ll learn that the speed of typing, even long method names, is not the limiting factor of your productivity.

This is the fundamental truth that those pushing AI as a replacement for programmers miss (intentionally or not).

What does replacing programmers have to do with typing speed? You mean the stuff copilot does was never the limiting factor of productivity? I agree, but copilot is not replacing programmers; replacing programmers is more than typing and proponents know that. It might get there.

I still don't understand how it would hurt if you can focus on the parts that do influence your productivity and have the rest appear automatically. But that's just me.

> This is the fundamental truth that those pushing AI as a replacement for programmers miss (intentionally or not).

I think this blend of comment shows a good dose of ignorance discussing the role of AI as a replacement for programmers.

It's not like PMs are suddenly seeing engineers vanish from software projects. It's that AI makes developers so much more productive that you only need a subset of them to meet your work requirements.

To give you an example, AI tools can indeed help you write whole modules. Yes, code can be buggy. Yet, the "typing" part is not what developers benefit from AI. Developers can iterate way faster on designs and implementations by prompting LLMs to generate new components based on new rewuirements, which saves you the job of refactoring any code. LLMs can instantly review changes and suggest ways to improve it, which would require either reading up on the topic or asking a fellow engineer on payroll to spend their time doing the same job. LLMs can explain entire codebases to you without asking a single question to veteran engineers in the team. LLMs can even write all your unit tests and rewrite them again and again as you see fit. LLMs can even recommend best practices, explain tradeoffs of approaches, and suggest suitable names for methods/variables based on specific criterias.

This means AI can do a multitude of jobs that previously you needed a whole team to do, and for that you no longer need whole teams to do a job.

Was this comment written by a bot? The concluding paragraph style and general length suggest to me it was.
It wasn't, and if it did I would wager it would write it more elegantly and coherently than me. That goes to show how much I use Claude/Copilot/ChatGPT at my job.
Maybe you should read less AI-authored texts; you’re evidently starting to copy its style.
> It's that AI makes developers so much more productive that you only need a subset of them to meet your work requirements.

my experience so far is that it takes away the upfront thinking and leads to a mess of code that I then have to sit down with them and try to work through.

So what Ai models are usable for producing a navigatable structure?

I wasnt aware of any that could

> LLMs can instantly review changes and suggest ways to improve it, which would require either reading up on the topic or asking a fellow engineer on payroll to spend their time doing the same job.

If we train ourselves out of being able to do these tasks, won't we find it harder to recognise when the AI makes mistakes?

> If we train ourselves out of being able to do these tasks, won't we find it harder to recognise when the AI makes mistakes?

We are not skipping these tasks. We are using tools to help us avoid doing drudge work that can be automated away.

Code linters eliminate the need to prettify code. Do developers find it harder to recognize indentation inconsistencies? Syntax highlighters simplify picking up code constructs. Do developers find it harder to read code? Template engines simplify generating new source files with programming constructs. Do developers find it harder to read code? Heck, auto complete helps developers write whole code blocks faster. Do developers find it harder to write a function?

I think those first two are not like the third. I think it's highly likely that developers who rely on AI to write code for them find it harder to write a function themselves, yes.
So, your argument is that AI does not replace programmers, it just... replaces programmers?
> So, your argument is that AI does not replace programmers, it just... replaces programmers?

I pointed out the fact that AI does not replace programmers. You still need people between keyboards and chairs delivering code and maintaining systems.

What AI does is make developers far more efficient at their job.

If you have employees that do their work in less time, they do not get more free time. They get more work. The moment their workforce is more productive, employees start to need fewer employees to deliver the same volume of work.

Counter argument - I did this for years with neovim in all my side projects, and now I have a fast minimal autocomplete set up I enjoy it a lot more. Turns out I never did memorise the entire API surface of rust, and enjoy the editor suggesting functions.
None of these need the absence of those features.

I do all of these, I also use auto complete, all LSP features and then some. And ofc copilot etc too.

It is pretty bad because coworkers use LSP / fuzzysearch and they will not do naming in a way that's more easy for the brain.
Autocomplete is more for discoverability than saving on typed characters, letting you rely less on documentation and more on the actual interface you're interacting with
I’m curious as how it lets you rely less on documentation. If you don’t know what you’re looking for then how will you know you chose the right thing?

The classic example of getting this wrong is probably C# developers using IEnumerable when they should’ve used IQueryable.

Can you elaborate on this? I'm one of C# developers who operate predominately in the Unity3d slums. This isn't familiar to me.

The closest thing coming to mind to me is mixing up IEnumerable and IEnumerator when trying to define a coroutine.

IQuerable Inherits IEnumerable and extends it with functionality to lessen the memory loaded when querying a collection (typically when reading from a database). Using IEnumerable can increase memory usage significantly compared to IQuerable.

Not every C# developer knows the difference, in my region of the world it’s an infamous mistake and is often the first thing you look for when tasked with improving bottlenecks in C# backends. On the flip-side, using IQuerable isn’t very efficient if what you wanted was to work on in memory collections.

There is an equally infamous somewhat related issue in Python with list vs generators. Especially common when non Python developers work with Python.

Ah this explains why I'm not familiar with misusing IQueryables. My domain is predominately in memory.

Thank you for the explanation.

> The classic example of getting this wrong is probably C# developers using IEnumerable when they should’ve used IQueryable.

Or literally any function from the standard library in C++, which will likely have undefined behaviour if you look at it wrong and didn't read the docs.

I have a theory that autocomplete actually increases the API surface area. One of the reasons Java has so many classes and such a huge sprawl is because Java got good tooling pretty early compared to other languages.
That's exactly the problem: You don't know the code. You're relying on autocomplete to tell you what the signature of the function you're looking for is.

I rely less on documentation because I've got it all memorized due to not relying on autocomplete.

Surely you didn't memorize the entire 3rd party ecosystem of a programming language?
I memorize everything I work with. Knowing my tools makes me a better developer.
I mean, maybe? But if you hover over the function you just completed, the same LSP will also show you the documentation.

This is how I personally use it for discovery, anyway. The other day I was writing some Rust code and needed to remove a prefix from a &str. I tried a few common names after ‘.’ to see what would autocomplete, before finding that Rust calls this idea “trim_start_matches”. I then wanted to know what happens if the prefix wasn’t present, so I just hovered my mouse over it to read. Now, if I was writing Rust a lot, I would end up memorizing this anyway. I’ve never not written Python without a similar tool involved, yet I have a pretty close to encyclopedic knowledge of the standard library.

I feel similarly about go-to-definition. I often use it the first time I’m exploring code, or when I am debugging through some call stack, but I also always do read where I actually end up, and do form a mental map of the codebase. I’m not sure I buy either the contention in this thread that these “crutches” make developers uniformly worse, or that removing them would make all poor developers suddenly more disciplined

But imho it does a disservice to new developers because they rely more on the exploratory aspect. At least that's how I remember it from doing C# in Visual Studio many years ago. You have a general idea of what you want, you type object dot and scroll the auto-complete list to find the method you think you need. And even if you can make it work after fiddling with it for ten, fifteen minutes, you can't be sure that's the best way to do it. And then you never want to go read the docs and learn the mental model and the patterns behind the library or framework. I believe it will only get worse with AI-generated completions.
Also about less context switching. If autocomplete gives me a full method name that I kind of remember, it saves me a trip to the browser and coming back, which saves a lot of time and avoid a family of errors when they add up.
No but speed of lookup is definitely a limiting factor. And with rust goto definition also goes to the doc comment so I can easily read the docs in my IDE
I agree on turning it off to find out. I disagree with almost all of your takes though. If you work without it, I would similarly suggest turning it in for a month.

> You’ll learn where all the reference docs live for your language, libraries, and frameworks, and along the way you’ll learn more by actually reading the docs.

I know where they are. I use them every day. But reaching for them to check every argument if every function I use is a waste of time. It als only works for stuff that has a full suite of documentation. If you’re using an internal library you’re very likely searching the code anyway.

> good project organisation, file naming and explicit import statements.

Good file naming is a crutch for a lack of tooling to explore and modify at a project level. Good project organisation doesn’t require you to disable tooling with semantic knowledge of your project. And explicit imports are a (necessary) distraction m.

> And you’ll learn that the speed of typing, even long method names, is not the limiting factor of your productivity.

It has nothing to do with the speed of typing and it never has. It has everything to do with working at the abstraction level I want to work at - my codebase. It’s using the tooling that means I think about “I have an X and I need it to do Y. “ rather than “let’s go context switch to the browser to figure out if it’s len, count, size, chars”

A good corollary is a linter - it’s incredibly important to the project, knowing and understanding the rules and why they exist is very helpful and would benefit everyone on the team. But a computer can do it for us, and let us focus on writing the code rather than ensuring we have tabs instead of spaces.

I upvoted both you and GP.

There are times when the "programming" job is best done with vim or even just a notebook in a quiet place.

Other times, an LLM or IDE can help get a new project going faster. Especially if you are unfamiliar with the language or framework. But in the latter case, do review the output until you understand it. So far even the best LLM will make subtle bugs, but unless its in a language you know well, you might have a hard time spotting them!

An LLM is like having an over eager junior dev with an eidetic memory who hasn’t slept in a week. It’s a superpower (minus the human rights issue) most of the time unless you’re not keeping an eye on it.

I’ve replaced so many tiny manual processes with python and batch scripts, and rewritten them in go when speed became an issue because of Claude and ChatGPT. I know enough to spot the glaring issue. I’m never going to sit down and write a batch file that installs my toolchain as it’s not done enough to warrant my time. But Claude will, and now our build machines use the same scripts and it means everyone is in the same environment (c++ on windows so our options are limited here)

>If you work without it, I would similarly suggest turning it in for a month.

In the past when I've tried to use IDEs, I've often given up within minutes because they would keep doing things that disrupt my flow - like popping up an entire menu of autocomplete suggestions in a way that obscures other code I'm trying to read, or autotyping a close bracket that I would have typed anyway by muscle memory, or not making it clear how to move the cursor past something it auto-typed, or interrupting me with warnings that something won't compile when I haven't finished typing it....

Okay, now stick with it for a month.
I’ve been coding for 2 decades. Autotyping anything is something I always find incredibly disruptive, regardless of how long I spend with tools that do this.
> In the past when I've tried to use IDEs, I've often given up within minutes because they would keep doing things that disrupt my flow

All the things that can be turned off/tuned. Strange that you don't spend the time learning the tool you admonish others for using

I don't in any way "admonish others for using" IDEs and I have no idea where that accusation came from.

And no, of course I'm not going to spend time learning an IDE that someone else recommended to me. I spend my tool-learning time on tools that I selected because I expected them a priori to be useful for me.

Autoclosing parens, brackets, braces -- one of the most annoying things to me, for example in tools like JupyterLab, but also in IDEs.
Yeah that's something I disable in every tool I touch. Especially when I'm typing something like foo(), by the time any autocomplete inserts that closing parenthesis, I will have already typed it, and now I'm distracted.

I don't mind suggestions if they are unobtrusive, but anything that interrupts my typing is an immediate no-no.

My editor inserts them and “smartly” overwrites them. If you type it yourself it will ignore it and move the cursor. You can hit delete and it will remove the added parenthesis, or you can keep typing and it will leave it there for you.

It’s been configurable as an option to have those in every editor I’ve used for about 15 years

This is also exactly my take. I've been coding over 40 years, long before autocomplete was really a thing, and that's probably the main reason I find autocomplete and all the stuff that pops up in modern IDEs to be annoying for all the reasons you described.

Autocomplete and all the other bells-and-whistles just get in my way, most of the time. It's literally the first thing I disable for myself when I install a new developer machine. The few times I set up a new machine and don't disable it, I am reminded why I want to disable it very quickly.

Exactly this. The last of my projects recently moved off of RHEL7, and I am ecstatic that I have a new enough version of vim to use LSP everywhere. I know how to navigate code and documentation manually. I know how to cobble together a poor man's version with ctags and scripts. And it is all a huge waste of time. I'm using an editor that is famed for letting you do everything with the keyboard more efficiently than you could with a mouse. That encourages you to navigate using hjkl for the slight speed improvement over moving your hand to the arrow keys. That has all sorts of ways to perform bulk editing actions faster than manually, and lets you write macros when that isn't fast enough. And yet having keyboard shortcuts that speed up code navigation that I am doing constantly is somehow a bad thing that I should eschew to build character? Forget that!
I don't need to turn it off to find out - I've worked in enough untyped languages (Python, Ruby) or badly set up ones (C++) where code intelligence tools don't work to know what it's like, and none of your points are true.

1. I know where the reference docs live already. Auto-complete doesn't obviate that need.

2. Again auto-complete doesn't completely obviate the need to navigate by file name/path (though it does reduce it), so I already know that is valuable.

3. The speed of typing sometimes is a limitation. I'm not a slow typer but sometimes there are situations where you just have to type out something tedious, and you're not doing anything other than typing. Yes even with fancy Vim/multiple cursor editing. Auto-complete speeds that up a little, but Copilot sometimes speeds it up a lot. You should try it.

For example for printf debugging, with copilot you can pretty much just type `dbg!` and hit tab. Much faster.

You also missed some significant advantages:

1. go-to-definition makes navigation much faster

2. type inlays make understanding the code much faster

3. auto-complete makes looking up method names much faster (is it .starts_with or .has_prefix? .contains, .has, .any, or .some?)

The only upside of not using LSP tooling is that sometimes it can bring your computer to it's knees, whereas plain text editing will always be fast. Easily worth it though.

untyped languages (Python, Ruby)

Both of those languages are strongly typed.

It seems you're confusing the fact that the type checking happens at runtime (that is to say, that they are dynamically typed) to mean that they're "untyped", but that's just not the case.

If one is confused about the languages one is using at this level, then modern tooling features aren't likely to help much.

I'm not confusing anything. It's relatively common to call the use of dynamically typed languages without static type hints "untyped". I'm pretty sure you knew what I meant and are just trying the classic "you used this word in a way I don't agree with therefore you're wrong".
Untyped has an actual meaning, for example, most assembly languages are untyped, same goes for Forth and probably others.

Then there's dynamic and weakly typed, ie. JavaScript. Dynamic and strongly typed, Ruby. Static and weakly typed, C. Static and strongly typed, Rust.

It was very clear from the context that I was not talking about Forth or Assembly.
Those terms have actual meaning, I've never heard Python or Ruby referred to as untyped. Because they both definitely have types and are in fact strongly typed.

Like, no one would call Ocaml untyped if you used type inference and didn't spell them out yourself... Or if you used the auto keyword everywhere in C++... The Ruby and Python runtimes both definitely enforce types.

> I've never heard Python or Ruby referred to as untyped

Well, now you have! Here are some examples:

https://0xda.de/blog/2024/03/untyped-python-sucks/

https://lucumr.pocoo.org/2023/12/1/the-python-that-was/

In fairness I think it is a fairly recent linguistic shift, probably because there's no debate between weakly typed and strongly typed - strongly typed is oblivious the right answer. Instead the debate is between dynamically-typed-without-static-type-annotations and statically-typed-or-dynamically-typed-with-static-type-annotations, but obviously people need a more succinct term for that.

> Like, no one would call Ocaml untyped if you used type inference and didn't spell them out yourself... Or if you used the auto keyword everywhere in C++... The Ruby and Python runtimes both definitely enforce types.

Static type inference still counts as having static types. That's totally different to dynamic typing without static type annotations ("untyped").

Of course it's Python people who come up with this nonsense...
Do you have a better name suggestion?
They said it in their first comment: dynamic typing
Not a good option - then you'll get a whole different set of pedants saying that Python is always dynamically typed, which I think is a lot more reasonable than quibbling over the use of "untyped" to describe Forth.
Adding type annotations doesn't make Python statically typed. Type annotations are borderline meaningless, they're basically just a type of documentation that helps your tools spit out better suggestions and makes your tools yell at junior developers.

Python isn't taking advantage of type annotations to produce better compiled code or anything, it's still a dynamic language that infers types at runtime.

Yeah that's exactly what I was saying. So what word would you use to mean "dynamically typed without static type annotations"?

> your tools yell at junior developers.

Oh you're one of those...

> one of those...

If by one of those you mean a solopreneur who doesn't have any junior devs to yell at then yes. If I wanted to use static types I'd use an actual statically typed language with all of the performance benefits (Go, Java, Rust, Haskell, Ocaml, etc...).

Using a dynamically typed/interpreted language with type annotations is literally the worst of all worlds...

It's relatively common to call the use of dynamically typed languages without static type hints "untyped".

And it's relatively common for people to be simply wrong, or to be careless in their word choice in regard to lots of other matters.

I'm pretty sure you knew what I meant and are just trying the classic "you used this word in a way I don't agree with therefore you're wrong".

It wasn't, i.e. I wasn't considering the possibility that that was what you meant. This is the first time I've encountered this broken usage of the term.

To think that some people are still writing code like in the 70's.

Not using productivity tools is just hurting you. I don't know what sort of misplaced sensation of superiority doing things the hard way may bring to you, but please don't give bad advice like this to young people. If they want to experience writing code without the help of modern tools, they can just use one of the so many languages whose tooling sucks: Nim, D, Odin, Zig come to mind (not criticizing them, but they still have a lot of work to do, and I know that they're all investing on doing it because yeah, everyone wants it). Nearly every single developer who uses those tools complain about tooling if they have used better tooling before (e.g. Rust, Dart, Java, Kotlin, C#).

When I have top-notch tools, I can write code that's a lot more advanced than when I don't (and I know that too well because I still insist on using those languages with bad tooling, unfortunately for me as it's a pain sometimes), because everything becomes much, much easier: docs, navigation, inline warnings, auto-suggestions (for languages that you're not too familiar with that's a godsend, love IntelliJ for Java, Clippy for Rust, for example). You actually learn from those things (as opposed to continue learning things that don't matter). Don't be a software ludite.

To think that some people are still writing code like in the 70s.

This is a muddled hyperbolization. These features barely existed (in terms of widespread use) even 10 years ago, but everyone got along just fine, even founded FAANG-scale companies without them, and so on. Yet you're making it sound like if you aren't using them, then you're basically still writing COBOL.

Not using productivity tools is just hurting you.

The commenter very clearly isn't saying you shouldn't use them. And their point had nothing to do with any "sensation of superiority".

They simply meant that -- yes, it is possible to not only be productive, but highly productive without these tools -- and that if you just tried to get along with them for a while, you just might learn a thing or two. For example, if one is even the slightest bit hesitant as to how one would go about resolving one of the issues that the OP asked about, without the help of modern tooling features:

   What do you do if you need to look up the definition/implementation of some function which is in some other file?
Then one definitely has some important learning to do.
It's actually not always trivial, that was one of the complaints I had about C# when I started. You import namespaces not classes, so it's difficult to see which namespace a class is from, and even if you know which namespace it's in the method might be an extension so you won't even find the method there. There's also partial classes.

It's a great language but I feel like it requires some tooling

Autocompletion has been common for at least 29 years since MS added it to Visual Studio.
Ever use the AWS SDK? Over 5000 functions with up to dozens of complex arguments each. It would be pure torture without autocomplete.
> To think that some people are still writing code like in the 70's.

I'm one of those, sort of. I did install vscode used autocomplete, find definition and on the fly compilation for a while. In the end I turned it all off bar the syntax checking.

Even my i7 32GB laptop it just got in the way, my typing lagging by many seconds while it recompiled and pondered autocomplete. I left syntax checking on only because while it still fell behind in revealing typos, sometimes by minutes, but at least it kept responding to my keystrokes.

I eventually gave up and went back to vim. It's a sad state of affairs when I can find a definition faster with 40 year old tools than a modern IDE can do it. I respect your decision to use modern tools of course, but I'm not sure I'm the luddite here. An Integrated Development Environment that runs slower than I can think is not an improvement in my books.

As for languages and online docs, one of my first steps in learning any new language is to memorise it's standard library. I don't use other libraries unless the bring something very substantial to the table, in such case I memorise them too. Not having to wait for a IDE to suggest autocompletes means the code flows off my fingers, but also means if the IDE starts lagging my typing I get really pissed off.

All that said, I recently tried using IDE + AI + integrated RAG, and was blown away. It's code suggestions are still so bad it's not worth taking the time to evaluate them, but omg as super grep it's amazing. Yes, it might take 15 to 30 seconds to evaluate my "can you find the code that does X" plain English request and provide links to the key functions, but it would take me hours to read through tens of thousands of lines code I haven't seen before to get the same result. Finally, after 40 years, we may have seen the first step change in programmer tooling since the move from line editors.

You seem to be being downvoted but you are correct. I find it hilarious how so many programmers hate using very useful and productive tools. It would be like a engineer refusing to use 3D CAD software.
I'm with both of you from my personal experience, and have definitely seen some programmers lose tons of time fumbling to google a function, scrolling through files to find a definition etc. As a programmer I find myself offended when I see somebody slowing down when the tool could speed them up. Plus if there's machine refactoring (rename, extract) it starts getting ridiculous when folks don't use it.

However, I've also worked with some bona-fide legends who really just use vim and dust everyone around them. Granted I wonder if they could go _even faster_ with automation but I can't fault it.

For me these days I'm leveraging new technologies and languages so often I really need the IDE features to get going. Doing rust without rustanalyzer or ts without vscode if you're noob (but not a noob coder) is a recipe for wasting a LOT of time imo -- I always learn suprising things from the (good) suggestions [and start dutifully disabling the bad ones].

Turning off especially the autocomplete would be a good exercise for many. I've worked with developers who relied on the autocomplete in Visual Studio to the point where they'd wear down the tab key. They'd rarely consult the documentation and do endless type conversions or attempt to construct the objects required for the API that sort of sounded like what they needed.

I think meeting developers like this will make you dislike autocomplete. If you know what you're doing though, it is amazingly helpful and can save you many wasted hours on silly syntax errors.

We have so many levels of autocomplete now. When I was in school intellisense was just becoming a thing, and it made me so much more productive. Being able to quickly scroll through method names and then jump to the docs was a huge time saver. Another big time saver is when they added the ability to highlight a function and read the doc inline/popup. Now I never leave the code window which is great for keeping focus.
This a fun idea, but honestly… who has the time for that? I’ve got features and bug fixes that need to be delivered quickly. Taking the slow road (especially if intentional) puts a target on my back for dismissal.

If keeping my job requires relying on the latest tech and tooling, that that’s what I’m going to do.

Here's my take.

One of my hidden superpower that I often see others are missing is navigating library code. Especially in new language.

I don't like reading docs. Very rarely docs are good. Usually docs are incomplete or outright wrong. So I never read them unless absolutely required. I just navigate library, skimming through its source code. Whether it's standard library or third-party library.

I failed this approach with Scala and it was main reason that I abandoned this language. Its collections were so absurdly overcomplicated, that I decided this language is doomed to collapse under its own weight. Apparently I wasn't very wrong.

Another failure with this approach is C/C++. For reasons that I kind of understand but don't approve, its standard library either hidden (so I can't just navigate to malloc implementation) or obfuscated with endless underscores (header template libraries), which makes it unreadable.

So it's not absolutely universal approach, but generally it works. And of course it requires "jump to definition" editor feature.

> Another failure with this approach is C/C++. For reasons that I kind of understand but don't approve, its standard library either hidden (so I can't just navigate to malloc implementation) or obfuscated with endless underscores (header template libraries), which makes it unreadable.

That's a complaint with C++, not with C.

You can very easily do development in C without much of what you rely on when using Java, C#, C++, etc.

The one thing, in C, that I do lean on a lot is compilation errors I get shown while developing: C is simple enough that a build of the current project's changed files takes 20ms or so. In practice, it builds faster than I can type.

I tried copilot for a few months, found it annoying, and uninstalled it. These tools make IDEs/LSP unnecessary for my workflow:

1) regex be it grep, or equivalents built into the editor. 2) Multi-cursor editing. 3) dumb autocomplete. 4) knowing how to type fast.

About 70% of the code I write at work is C. Another 20% is Rust (which does have a nice LSP implementation that I use, though I wouldn't call it essential), and the remaining 10% is the usual bash/Python/Ruby/cmake/make mumbo jumbo.

My bottleneck is how efficiently or completely I can keep the problem I'm working on in my head, not how quickly I can look up a function name or variable or type out the actual code. Really, only the latter is helped along by autocomplete. I find myself with that feeling of my mind slowing down more and more as I get older. When I actually get around to writing the code itself, the problem is mostly solved from my perspective, I'm just dumping out of my head into the editor, that part is easy. Until an autocomplete is wired up with an LLM and LSP which knows exactly how I think and approach problems and remember the codebase, it'll be mostly useless for me. So I don't bother.
I used to code in pure vim, so no autocomplete and syntax checking. It is definitely possible.

Is it a better way to work though? Well, in some ways, it forces you to use more cycles in your head, so you do gain proficiency, and you can spot mistakes more quickly. This is a skill.

But once I started working on larger codebases and higher complexity code, I felt it was better to redeploy those brain cycles toward thinking more about architecture, and letting the LSP check the code. With an LSP, I'm now able to write more correct code in fewer iterations.

Like everything it's a trade off. Am I impressed by people who can do complex mental arithmetic? Yes, but for anything complicated that I'd rather not get wrong, I will reach for a calculator. Same idea here.

There are still a lot of developers out there that basically are at the hammer and nails level of programming. They use a basic editor with basic syntax colouring and when they write broken grammar, the editor just misbehaves telling them they've typoed something.

Many still use rg and fd or fzf outside or within their editor and are anti IDE.

I think ultimately they do waste time, particularly they see refactoring as a big 4 hours job when people using intelliJ and other proficient IDE will see it as a 5' job.

That said, have you every felt, that using all the bells and whistle, half the time you're being impaired by them? Auto-complete nags you, copilot is completely off the plot and spewing tons of stuff all the time.

The key, I think, is to have all the bells and whistle but have shortcuts to turn them on/off. I have auto-complete only drop down on ctrl+space shortcut, not automatically. And for copilot, I have ctrl+cmd+c for turning it on or off.

That way I can free flow type code as I think of it and get the tools to assist whenever needed. It's the best of both world. The IDE as clutter free as possible, and all the tools at a finger tip.

But renaming symbols throughout large projects without an LSP? Nah, been there, done that, for decades, and I'm glad that's over.

>But renaming symbols throughout large projects without an LSP? Nah, been there, done that, for decades, and I'm glad that's over.

There is a trick -- never renaming anything. If the name is minted, that's it. It's canon.

> But renaming symbols throughout large projects without an LSP? Nah, been there, done that, for decades, and I'm glad that's over.

It sounds nice; although even with basic emacs: change the definition, compile, step through the compile errors macro-replacing. It's pretty fast and not really common.

Non-compiled languages suck though, but you shouldn't use those for big things

I've recently picked up using lsp now that a lot of my work is in go. I have co-pilot but often forget that it's there and don't use it much.

Generally, I have a hill to climb with a new code base. I get the ideas into my head and then rely on that rather than tooling. It's how I've always worked. I'm very comfortable with my editor so it just does what i think and i don't have to expend effort to translate my thoughts into keystrokes.

That's basically it. This Blog Post by a friend of mine on important editor skills to master is a good read on effectively using an editor https://info.pagnis.in/blog/2014/05/06/10-actions-you-must-i...

I do 100% of my software development in vim. I have syntax highlighting and some auto indentation but otherwise no autocomplete, no LLMs, no vim plugins for hopping between files.

I just… write code? If I need to remember what’s in another file, I open up that file in an adjacent iTerm pane, or pull up the docs for the library, etc etc. if I want to have the program run every time I save, I run a watchexec in an adjacent pane.

You just type or copy/paste, but the main language I use, most statements are terse. But I have personal templates for a few languages. As you go on, most of the programs are pretty much close to what you have already done.

Like the old saying, there is only 1 COBOL Program, all others were copied/pasted from the original.

I do not really belong to that group, but when I am learning a new language I avoid using LSPs and anything more than a generic autocomplete because I find that too distracting while I try to learn the language. Moreover I realised that it actually slows down my learning; I may type stuff faster but I learn and gain understanding slower compared to eg typing everything and searching the docs. In stuff I am already proficient with, it makes more sense to me as such tools help me code faster, including finding and fixing bugs faster.

As for copilot, I find it impractically distracting and I do not understand how people are supposed to code with it tbh. While coding I spend most time thinking about the code than just typing, and having random autocomplete suggestions popping up with lag while typing disturbs my chain of thoughts. Maybe if I was writing more boilerplate I would have liked it more, or I am using it wrong somehow, or maybe one gets used to it after some time. I sometimes use copilot chat though.

Just take a pen and a sheet of paper and see how far you can get.
I do this exercise once year, just for fun. Would recommend.
Not even that.

- Just try reviewing a PR and see how comfortable or uncomfortable you are compared to when you have the code on your usual IDE or editor or whatever.

- Just try being in a Google Meet or something helping a coworker remotely, and see how effective you can communicate before you have to resort to giving them step-by-step instructions.

One thing is using a feature because it lets you do what you want, but more quickly; a very different thing is using that same feature because you literally get reduced to almost zero productivity without it, and start fumbling around (like in the two examples above). This also includes features like debuggers, tooling in general, or even tech stack (e.g. "why bother learn HTML when React is way more productive and it's mainstream").

It's not about dogmatically choosing one or another; it's about making your productivity floor higher, instead of focusing only on productivity ceiling.

I have jumped around over my career: Sublime -> Vim -> Emacs -> VSCode -> Neovim -> Cursor, which is now my daily driver.

However, I still relish in the ability to open up a nerfed Sublime or basic Vim install where it’s just me and the text. I do so when I want particular lucidity in my thought process and code composition.

Then I can always fire up heavier tools for code review after the fact. How do I “do” it? I got really good at grep’n my way through a code base. It’s amazing what grep/ack/rg/etc can tell you when you know what to ask. And if you don’t know what to ask, well finding that answer is going to teach you a lot more than just hitting Tab on autocomplete or GoToDef.

I've found cursor tends to muck up system internals and such when I use shells in it. There is a lot going on under that hood -- would prefer it work as a VS Code extension so it has some guardrails.
Have you tried the Clive or Continue extensions? AFAIK Continue is somewhat like Cursor. I prefer Clive though, it's become an important part of my workflow - although perhaps even more important is knowing when not to teach for it.
I'll check them out.
I learned and worked for decades before these tools were available. If they still weren’t available today, you would find that you too could program without them.
Sure, but isn’t this just “why don’t you use the backup camera that all cars have had for a decade or more” / “I learned to drive without one, and you could too”?
Are we trying out car analogies? How about instead of backup cameras, which are consistent and provide extra information, you have a camera that randomly guesses things around your car? Sometimes it's right, sometimes it's wildly wrong, but mostly it doesn't affect your driving speed.
>backup cameras, which are consistent and provide extra information

in order to be extra information for me, the backup camera display screen would need to be in the back seat of the car, where I'm looking while I back up

My car has blind-spot warnings. They do go off when I'm not changing lines or nothing is there. However, it has probably saved me at least once and is therefore totally worth it.
I drive a car that doesn't have a backup camera and I wouldn't pay more for a car with a backup camera. I've never felt like I need it. I guess this is just how these augmentations work. By the time you've invested the time to learn the skill, you don't need the augmentation anymore. So you're left a bit puzzled by people who do. The people who use augmentations, or rely on them, have a more clear differential view. They compare their augmented ability with their non-augmented ability and it's very different.

I still have most of the python standard library and many of the interfaces I use often in my brain, so autocomplete saves me almost no time. I can type working code into notepad about as fast as I can type it in VS code.

Cars without backup camera tend to have good mirrors (exceptions exist).

Once you put the camera there by default, the designers/engineers gets many extra degrees of freedom since they aren't constrained by visibility requirements. Those degrees of freedom are certain to be exercised! On the total this is probably probably a good thing, but it sucks when the rear camera(s) are covered with snow or grime.

A bit. But note that "you could too" is not a "you should too".

I can back up without a camera, and I can "drive stick" as Americans call it. But a teenager learning to drive today should maybe not bother.

But that's not the same question as "why aren't you installing a backup camera?". Because it wouldn't change my ability or speed of backing up. And I can drive stick. Why not replace my car with an automatic? Because it wouldn't improve anything.

In fact I dislike automatics, since they'll suddenly and jerkily decide that another gear is best, ever though my foot didn't move, and inclination didn't change. But in a couple of decades it'll all be electric and this problem will go away. The deliberate engine braking is in electric cars just the brake pedal.

Backup camera is not only the backup camera and nothing more. In our reality the backup camera is a perfect way of spywaretize cars. Cudos from the Government.
I suppose this is like a lot of tools in general: you just get used to doing it yourself. People wrote code before tools like that existed, and you can too if you put your mind to it.

I typically just use plain Vim without much customization. You get used to it. I am somewhat forced to use just plain Vim on most things because I often write code on random HPC servers and have no control over what is available. But Vim is universally available, so I got good at the one tool available to me. Vim does have have Ctrl-P to auto-complete a word, though.

I also have books and other documentation available, when possible. Man pages are actually quite good and available on many systems I work on. For C, you can type something like "man 3 printf" to get basic documentation on "printf". This works for MPI too with things like "man 3 mpi_allreduce". I've been pleasantly surprised at times how much offline documentation is available.

I never really thought about it. I guess some people just like having those features, but I find them annoying.

I use Neovim with 0 plugins (apart from themes). I code in Go, and frequently reference https://pkg.go.dev.

When I do need to code in VS Code (rarely), I find that the autocomplete just gets in the way of my though process. It's like having a train of though barreling along and then suddenly an elephant gets on.

Also, I didn't even know what an language server was until looking it up after reading this post.

About Copilot: I have many problems with AI. They guzzle electricity, tend to be run by corrupt corporations, and are filling the internet with BS.

If I need to look up the definition/implementation? `:vsplit` works fine. If it's on the internet? https://pkg.go.dev.

If you don't trust me, you can check my dotfiles: https://codeberg.org/Kaamkiya/dotfiles

> What do you do if you need to look up the definition/implementation of some function which is in some other file?

At some point, for me, ‘find <dir> -name “*.ext” | xargs grep <pattern>’ took over for recursive grep, because the required tools are available on most Unix systems.