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

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?

220 comments

This question reminds me of the first time I met a blind programmer.

I asked him how he managed to code, and he replied with something that stayed with me: a good programmer should organize software in such a way that every piece of code has a clear and logical place. The organization should be so intuitive that anyone could build a mental model of the structure and navigate it easily, even without seeing it.

It felt like something out of a Yoda or Mr. Miyagi lesson. Skeptical, I asked his colleagues if he was truly able to code or if he was just exaggerating. To my surprise, they told me not only was he capable, but he was the best programmer they had ever worked with. They said no one else came close to writing code as organized as his.

That conversation changed my perspective. Ever since, whenever I’m unsure where to place new code, I don’t think about DDD or any specific methodology. Instead, I try to follow the logic and structure of the project in a way that feels natural and easy to follow later.

Later in life, I met two other blind programmers and heard similar stories about their ability to produce well-organized code.

To bring this back to the original question: I view LSP/IDE features the same way those programmers view "visual aids." Code should be organized according to a clear and logical structure that makes it easy to navigate.

Relying on features like Ctrl+Click to find where things are located worries me. Why? Because it can mask structural flaws in the codebase. If we can't intuitively figure out where something belongs, that’s a sign the codebase lacks structure—and that should motivate us to refactor it.

Not only do I avoid using LSP features, but I’m also opposed to their use. While they can help with navigation, they may prevent developers from experiencing and addressing the underlying structural issues in their code.

This HN thread was posted on Reddit and that programmer commented [0].

The full comment -

> Oh hey this is me. My typical setup is two terminals: one for vim, one running the compiler and other tools. I just make edits, then invoke the compiler, in a loop. As for finding a definition, most of the time I'm just familiar enough with the code that I know where it is. But when I don't, usually a well designed grep command will do the trick.

> The why: my job involves frequently doing development in environments I don't have much or any control over, and often don't even have Internet access. Over the years, I just learned to work with the basics (vim and a shell) since I can't take my favorite IDE with me to these different environments.

> Additionally, my vim configuration just involves setting up tabs to be 4 spaces and turning on line numbers. Having a complex config just became too much to try to keep in sync across environments.

[0]: https://reddit.com/comments/1hld3s4/comment/m3ladrs

> Not only do I avoid using LSP features, but I’m also opposed to their use. While they can help with navigation, they may prevent developers from experiencing and addressing the underlying structural issues in their code.

LSP by itself will not prevent anything. LSP (using the terminology from OP, but any IDE really) is just a tool like any other which allows you to do things faster. It doesn't matter how organized your code base is, it will never be as fast to find some definition as hitting a keyboard shortcut (please don't use Ctrl+Click, my gosh... learn the keyboard shortcut for things you do often like this). I want to see docs for a function without moving my eyes from the code I am currently writing. I want to be able to jump back and forth between definitions without interrupting my chain of thought, see function definitions inline instead of having to jump to the file it's defined on.

When you have to manually search for files and then Ctrl+F to find functions, lookup docs in a web browser (which I hear is how people who don't use IDEs still do that), or manually run a linter/compiler to see warnings in your code, you're just being really inefficient. I can't understand that at all. Why don't you use automation to help your job when the whole point of your job is automation?

Keeping the code organized is still good advice, but has nothing to do with using an IDE.

Of course that are good things and maybe I wrote in a too much harsh way.

Linting features and autocompletes are nice, also autocomplete features are nice to have.

The issue that I pointed mostly resonates with the idea that depending on LSP is the big issue.

I personally use Neovim with minimal stuff, I run lint and tests manually and not automatically, because it feels to me like push notifications taking my attention elsewhere, so I go to fix them later after what my intention is already expressed in code.

But agree and dyisagree that "Keeping the code organized is still good advice, but has nothing to do with using an IDE.". It should not be based on IDE, but an IDE on the hands of an inexperienced dev may lead to some comfort that should not be there.

I reviewed many code written by junior people, and very often I see people adding code in random places that later may let the application to be hard to follow and everything "seems fine" to them.

Other smell is like, but "it is so easy to rename a variables with my IDE" even though I believe that refactoring is nice to be done, but if we keep changing names so often, why don't we read the code that is being edited to understand well its intention and maybe realized that a big chunk of code should be split and the name choice will be completely distinct once proper refactor is made.

My point is not about avoid automation, is about having a dependency on that because the code is not manageable to people anymore, but manageable by automation mostly.

> I reviewed many code written by junior people, and very often I see people adding code in random places that later may let the application to be hard to follow and everything "seems fine" to them.

As someone who got their start in edit/Notepad, it wasn't "productivity boosts" that made me bad at code architecture when I was inexperienced.

I'd wager it wasn't the lack of "productivity boosts" either?

> I reviewed many code written by junior people, and very often I see people adding code in random places that later may let the application to be hard to follow and everything "seems fine" to them.

But is that because they're following their IDE, or is it because they're junior developers? I also see that sort of issue regularly, and as someone who is very happy with their LSP creature comforts, it's still something that I have to call out and teach.

I think you're reversing cause and effect a bit here, in the sense that you're trying to argue that IDEs cause developers to be less thorough and diligent, and to care less about good code organisation. In practice I suspect it's the other way around: the people who are more likely to be diligent and get their code organisation right are the same people who would take more care in choosing exactly which tools work best for them. That is to say, it's not that IDE users are worse at code organisation, it's that the people who are worse at code organisation tend to use IDEs.

I think the idea is that very powerful IDEs and other tools make it very easy to manage complex and disorganized codebases, the downside could be that nobody would care about cleaning up that codebase. At the same time powerful IDEs make it somewhat easier to clean up messy codebases so living in a mess is a choice.

This reads a lot like the old assembly language programmers (I was one) who stuck their nose up at C programmers for not knowing how computers worked because it was too high level.

The entire purpose of computers is to automate things and reduce complexity

There is the very real possibility that automation masks complexity, not reduce it. And that’s what he’s saying.

I used this as an example before, the AWS SDK

https://boto3.amazonaws.com/v1/documentation/api/latest/inde...

It’s the same in every supported language since it is autogenerated from service definition files. I chose the Python version because it is all on one page. Would you rather memorize thousands of functions across hundreds of classes? Should AWS “reduce complexity” by getting rid of services and functionality?

Would you rather have an auto complete IDE or have to look up the web reference?

I’m sure it’s more complex to run S3 at scale than to build out the data center I did as part of my job to store 4TB worth of data in the early 2000s.

I would much rather run a 4 line CloudFormation template and do it in less than a second over it taking months to do it in house.

I started my programming in assembly in the 80s, should we go back to that too or should we keep using compilers and interpreters?

Should we keep programming in C or should we use manages runtimes with garbage collection?

yes to all of that. In other words, we need both. We need the low-level stuff to do things nobody has ever done before, and the high-level stuff for the things we do every day.

And even assemblers had macros in the late 80s and shortcuts to make assembly easier.

There is no reason to purposefully make your life harder and not use the tools available.

The parent poster doesn’t use IDEs because it hides complexity. There is a such thing as necessarily complex.

About a decade ago I was working at a company that created a SaaS product for railroad car repair billing.

These are the main requirements not including a dozen addendums

https://public.railinc.com/sites/default/files/documents/CRB...

The parent commenter would say that we shouldn’t use an IDE to navigate through the massive code base to make sure records submitted from the railroad yards were in compliance. What alternative would you suggest?

Intellisense for Visual Studio has been out since the mid 90a

When you have to manually search for files and then Ctrl+F to find functions, lookup docs in a web browser (which I hear is how people who don't use IDEs still do that), or manually run a linter/compiler to see warnings in your code, you're just being really inefficient.

It's inefficient the first time but you quickly build a working memory and a deeper mental model of the code, which becomes even more useful in the future.

Why don't you use automation to help your job when the whole point of your job is automation?

That sort of thinking will get your job automated out of existence.

Good riddance?

Why spend your life doing something a computer could do for you?

The goal of programming is not to write code (however much I enjoy that part), it is to solve problems.

I don't think copilot et al is anywhere close yet though. They are occasionally useful when working with popular APIs you use very rarely, or when you need to write some very repetitive code. Other than that, I feel like it's mostly a monkey typing plausible but incorrect code on my screen everywhere I go.

Why spend your life doing something a computer could do for you?

Why spend your life doing _anything_ a computer could do for you? Why even live, if you're going in that philosophical direction?

I don't think copilot et al is anywhere close yet though.

Unfortunately, many of those in management already think it is.

The less people use their brains, the more easily they will be replaced, and the worse the product they'll produce. Unless you want to lose your job and let society drown in mediocre software (which you will no doubt need to use), do not hand over your agency to the machine.

I don't want to write any code. I want to think about the design of the program and have it pop out of my head fully formed.

The latter gives me dopamine. The former gives me carpal tunnel.

For myself, the code is the journey. There are times though when I'm not fully invested in the problem, that I really just want to skip that part.

> The goal of programming is not to write code (however much I enjoy that part), it is to solve problems.

Right, which is exactly why autocomplete is not a huge help.

We are not paid to “code” we are paid to use our knowledge of the technology ecosystem to add business value - either save the company money or to make the company money.

Back in the 2000s for me part of that job was to lead the buildout of a data center with a SAN that took up a whole room to hold 4TBs. Now I do that with 5 lines of yaml in a CloudFormation template.

My job was not “automated out of existence” by not having to provision a data center as part of it.

When I'm coding, most of my time is spent thinking about the right structure, organization, or solution. Or, debugging something that isn't acting as expected (which, again, is mostly thinking).

I spend comparably little time actually writing the code.

If there is an IDE available that works well out of the box, I'll certainly use whatever automation is available. But often it is broken, incomplete, slow, inaccurate, etc. and rather than spend countless hours fine-tuning some automation / LSP workflow that is going to break when I move to a different project anyway, I just deal with whatever features are missing.

This also has the advantage that I can quickly move to other tools, other languages, other computers, other companies, etc. without requiring days of setup and re-accommodation.

I do have a pretty good memory, which is probably a large part of why this is effective for me.

>> If there is an IDE available that works well out of the box, I'll certainly use whatever automation is available. But often it is broken, incomplete, slow, inaccurate, etc. ...

I think you are unduly harsh here. As a longtime emacs user and who switched to IDE recently (ones that come from JetBrains) my experience hasn't been what you mention. Yes there is a bit of time (not huge) to get adjusted to the shortcuts and efficiently navigate the code, but post that the IDE ecosystem is not as broken as you allude to.

If I'm working on a small hobby project by myself, or some open-source stuff, sure! I agree the Jetbrains stuff is great, I've been using them since 2001 with IntelliJ IDEA.

But most of the large industrial codebases I've worked on at FAANG companies break IDEs one way or another - either because of the build process, or the size of the codebase, etc.

I find the more plugins I add to vscode to do all of the automation, keypresses become more and more sluggish. It seems like it wouldn’t be noticeable — we’re talking about milliseconds.

But I find there to be a world of difference between every keypress being processed as I touch the key versus slightly after it.

With enough experience on a given language you just of internalize a lot of the common linter rules.

I use ctrl-space to activate autocomplete when I need it, but I find when it pops up automatically to be maddening.

I’ve been using AI autocomplete more and more, though it’s a real mixed bag between seeming magical and guessing the completely wrong thing.

> It seems like it wouldn’t be noticeable — we’re talking about milliseconds.

Yeah, I've used xterm for so long I found it a pain a few years ago when I had to use gnome-terminal, because keypresses have enough latency to be noticeable. I never expected that from a terminal.

Is it inefficient? Possibly. But I would argue trying to get me to use an IDE and all of the other new fancy tools is more inefficient. My flow works for me, I can navigate through projects and find exactly what I'm looking for pretty quickly, to the point where people who watch me do it comment on how it just looks like a blaze of text to them. And I've found that trying to use IDEs and other tools doesn't make me more efficient, it just slows me down.

I want to be clear, I don't think my workflow is the best, most good, better than everyone else's. But it is mine, and it's the one I'm very proficient and productive with. Vim, tmux, and an assortment of command line tools isn't the right workflow for everybody, but I would argue I'm as, if not more, productive than most people I know using that latest fancy IDE tools.

> Why don't you use automation to help your job when the whole point of your job is automation?

Because I don't see that as automation, I see it as things getting in my way. My brain is set in its ways, and when I try to use tab completion or other nice editing things that people like I feel so slow, I feel like the computer is putting blockers in my way, because I know exactly the line I want to write, and popups and tab-complete break that flow for me.

All power to everyone who can handle that and prefer it, but it's not for me.

IDEs are neither new nor fancy. I find it really amusing how many programmers spurn IDEs. It makes me think of a engineer refusing to use CAD.

"the whole point of your job is automation?"

Automation is not the point of programming. Think hard about this. It's the most important point. Code/build/hack to create more work for people to do, not less. It's thanatos. People need to unlearn "programming==automation" before it's too late. Everything we do as programmers should be done with "create more work" as a mantra.

I see where you're going but for me "create more work" doesn't quite capture it. In my mind there's a pretty clear distinction between computer work and human work. Computers are good at fast, precise calculations and following complex procedures repetitively without variation. Humans are good at lateral thinking, constructing narrative and drawing non-obvious connections.

Coincidentally, humans are generally really bad at the things that computers are good at and vice versa.

I think our job is to build systems where the computers are doing the computer work, which frees up the humans' brains and time to do the human work.

So not creating more work per se, maybe creating the opportunity to do better work?

Automation is bad for you, but it's "good for business". The least they need you, the better it is.

I assume this is where 'automation' comes in, reduce dependence to the meatbags (us, humans)

"just a tool" is always the excuse for allowing a crutch to make you weak and directionless.

If it's really "just a tool", why so defensive?

Sorry. I know I'm a dick. But come on man, don't pretend the effects of crutches doesn't exist. It's silly to try to deny something so obviously observable all day every day, in all possible contexts not just coding.

Are Soldiworks, Fusion360, etc crutches that have made engineers "weak and directionless" or are they utterly indispensable tools that have drastically increase their capabilities and productivity and enabled them to create things they otherwise could not?

LSP optimizes writing the code. Yet debugging, reviewing and reading other people code take significantly more time than writing. If code is organized badly and go-to-definition or even moving the mouse to trigger the tooltip is required when doing those tasks, it makes the whole experiences worse.

> LSP optimizes writing the code.

I would actually phrase that as “LSP optimizes for understanding” (which is of course important for writing code).

For example, when doing code reviews I routinely pull the branch down and look at the diff in context of the rest of the code: “this function changed, who calls it?”, “what other tests are in this file?”, etc. An IDE/LSP is a powerful tool for understanding what is happening in a codebase regardless of author.

LSP optimises consumption of other code and reading/exploration of code. It's especially useful with types.

> it will never be as fast to find some definition

The fastest definition is the one you never need to look up.

In the absence of "coding aids" like function lookup, people (are forced to) write code that is inherently better-organized and easier to conceptualize.

You are lucky to have small code base or one that you write mostly?

With 6 other devs on the team and 5 apps our team supports there is no way I get code well organized especially when as a senior I have devops stuff to deal with meetings, explaining features to business, checking up support tickets and random stuff happening all the time.

I don’t know the code base and there is no way to keep up.

While I have to dive in and fix shit ASAP or when I get to code review I have to fix some less experienced guy code. Or write part of code when proposing architecture solution, because just telling people “I am right do it my way” does not work until I write piece of code and then they understand.

Language server and ctrl-click is my bread and butter because that is the fastest way while also going slow enough to understand context.

I'm curious what you do when you encounter issues in a 3rd party dependency, or (since it sounds like you do dev-ops work) in an infrastructure process or tool whose code you didn't write? I use auto-complete and LSP features pretty heavily myself in my day-to-day development work, but when debugging an issue, I sometimes run into issues with a 3rd party library, or a kubernetes component, or whatever, and it's necessary to jump into those codebases and understand what's going on, whether the bug is with the library or with our own integration, whether it's more expedient to patch the dependency or write a workaround in our own code, &c. And in those cases, I generally do not have a LSP running, or my editor properly configured beyond basic syntax highlighting, and I have to rely on, presumably, the same techniques that devs who don't use LSPs at all employ in their day-to-day work: being able to quickly read and understand other peoples' code, being able to approximate jump-to-def with find/grep/ag/rg, being able to effectively trace datatypes and control flow through multiple definitions/files, being able to take effective notes to improve my working memory, and so on.

Well yes I still do lots of grepping and just search in all files if needed. It is not exclusive but if I can use good IDE features it helps to be quicker.

I also have notes I write down where search is must have as my notes are not structured anyway.

nearly instantly searching through vasts amounts of data is one thing computers are amazing at and it is absurd not to leverage this capability wherever possible.

[deleted]

This is one of the features I like most about F#, after some years experience with it. The project is structured with a specific file ordering, and there's no forward referencing. Similar within a file/module as well, most of the time.

So to understand a project, you start at the top and work your way down, you wont encounter anything you haven't come across yet as you go.

Ironically, this 'feature' so annoyed me when I first came across the language in 2015 or so, that I put it down after five minutes and forgot about it for years.

> a good programmer should organize software in such a way that every piece of code has a clear and logical place

How many programmers have the luxury to organize the code in the way that exactly suit them? most of the time, I work on code I didn't write myself. In the past, I used to try to refactor but I grew tired of having to justify why it's useful. Nowadays, I just deal with the code the best I can, and LSP is a big help.

I do think - my pet theory - there is two sorts of « good » code :

- The solo programmer’s code : it’s smart, small, straightforward, does what it needs to do and it benefits from being able to fit in the author’s head but it would be a team’s nightmare, hard to add unanticipated features.

- The team’s code : it’s verbose, full of boilerplate, follows strict programming patterns and rules, is easier to modify/add features. Anyone in the team can add or maintain parts but give it to a solo programmer and it would become a nightmare to just maintain.

For a long time in my career, I opposed the two. Being too straightforward and not strict enough in a team setting is often a recipe for disaster in the long term. In the contrary, being too professional in your solo project is often the way to abandon it.

Being able to write those two types of code is an incredible skill - that I mostly don’t have.

I’m sorry to say that some of the gnarliest and most boneheaded codebases I worked on were ones where I was the ‘architect’.

It was a startup environment and hectic, but I had total control over everything, more or less.

Just to say that having the luxury of a greenfield start doesn't mean you'll end up with a nice result.

> I asked him how he managed to code, and he replied with something that stayed with me: a good programmer should organize software in such a way that every piece of code has a clear and logical place. The organization should be so intuitive that anyone could build a mental model of the structure and navigate it easily, even without seeing it.

I had a similar conversation with a blind classical guitarist before I ever played, which was echoed by my instructor when I started to learn a few years later. Something along the lines of "If you don't know a piece of music to play it with your eyes closed then you haven't practiced it enough for a performance."

I'm not sure I follow the same idea with not utilizing available tooling in software development, but I do believe that most developers would benefit from intentionally going 'back to basics' and limiting their use every so often and shining a light on what you might think you have a solid grasp of but are actually at the limit of your unassisted capabilities.

My understanding of successful blind programmers is they basically are forced to write code in a way that fits in their head, and this is the essential feature of good code.

I'd be interested in more concrete examples of what specifically you're referring to though.

This matches my experience as a non-blind programmer. If the code is not well structured, I have issues finding things by intuition. The mental model or map does not work. Then I rely on searches or various kinds. It is annoying, and one can't always change this, when working on a non-restructuring MR. Others relying ore on LSP might not even see this issue.

some colleague some time ago argued that one can write code without much/any spaces, because, "you can see, it's colored differently".. sounding like, "i am breathing".

All these IDE+- things may be nice-to-have but most soon become crutches, and then you cannot live without them, and only walk their walk, not yours.

Just turning off syntax coloring freaks recent developers.. even quite good ones.. i observed it.

Then the trend to pollute untyped-languages' codebases with so-called-"typing" noise, because "it would be IDeditor-friendly" (??) . Form over function, yes..

And another observation from many experiences.. any kind of generated code alienates its users, i.e. programmers. Yet to see how current LLM-ical trend scores in this.. As of last interview, "we need software curators, not programmers"

have fun!

"Just turning off syntax coloring freaks recent developers.. even quite good ones.. i observed it."

Because it really does make code much easier to read and there is absolutely no reason whatsoever to not use it.

> All these IDE+- things may be nice-to-have but most soon become crutches, and then you cannot live without them.

There's a bit of "silly flexing" and projecting here but not entirely without merit. At regular intervals I'll actually turn all my IDE features off just to give myself a refresher. I would imagine that if you took away most IDE syntactical sugar, the vast majority of relatively competent devs could adapt in short order to it.

To me it's the equivalent of using an IME to type Chinese, but occasionally I'll just sit down and physically write the characters on pen/paper. Do I need to do it? Not really, but I enjoy how it forces me into a state of uncomfortableness.

> Then the trend to pollute untyped-languages' codebases with so-called-"typing" noise, because "it would be IDeditor-friendly". Form over function

I honestly have zero idea what you're trying to say here. You mean Typescript or using JSDocs to inform type expectations? What exactly is the issue?

These kinds of arguments get "trot out" all the bloody time. Whatever I grew up with was the most ideal - whatever came after is just a crutch.

For that matter, why are you using a high-level language like Javascript or C#? Don't you know that it's a crutch and gets in the way of true programming understanding? You should be using magnetized needles to etch machine code directly onto disk platters.

I'll have you know that among GC languages C# gets you the closest to "using a magnetized needle and a steady hand"!

> pollute untyped-languages' codebases with so-called-"typing" noise

Yeah, this is going to be extremely controversial: your so-called untyped language actually has types in, and they're important, but only the program can see them at runtime because you've not written them down anywhere.

The real solution to "repeating myself writing down types" is Hindley-Milner inference, which dates back to 1958, and more languages should use it!

IMX, people who use the term "untyped language" generally: a) use languages with Hindley-Milner inference; b) don't consider things that can "only the program can see at runtime" to qualify as "types".

If your language lets you add a number to a string or divide a dictionary by a boolean, that's .. exciting, but also the sort of thing that produces https://www.destroyallsoftware.com/talks/wat

Those “Wat”s are mostly the result ot weak typing, (as opposed to strong typing) which is an entirely orthogonal concept to static/dynamic typing. Don’t confuse the two concepts. Older languages which first started to experiment with dynamic typing also tended to use weak typing. But as things progressed, weak typing was considered less good in serious languages, while it was still expected in “scripting” languages, and Javascript was designed with that principle. Nowadays we have more or less decided that weak typing is almost always a bad idea, and Python is an example of a modern dynamically typed, and also strongly typed, language.

True, but also irrelevant. Python is strongly, but dynamically typed. You cannot do the things you describe in Python, but it's still considered "untyped" in that framework because it performs its type checks at runtime.

Yeah, but even there, if one were to use no LSP or other completions, Hindley Milner doesn't help while editing as you won't see the inferred types. It comes down back to good naming and the compiler at the end.

Yeah this is probably someone that doesn't like type script or type hints in python. If you're slinging dynamically typed code for your own personal project, go nuts, but if you're working with a team that 'typing noise' really helps

> "All these IDE+- things may be nice-to-have but most soon become crutches, and then you cannot live without them, and only walk their walk, not yours."

... and?

Cars have automatic chokes, power assisted steering, hydraulic brakes, airbags, seatbelts, auto-dimming mirrors, self-running wipers, and it's fine. People argue that driving a stick-shift is more authentic but even they use syncromesh and clutches, they don't complain about how rubber tyres are for wimps and they use cartwheel-style metal bands wrapped around wood. They don't complain about having a differential instead of fixed drive to the axel.

A plain editor relies on terminals displaying multiple lines and updating them, filesystems for storage, an OS, a keyboard, ASCII or equivalent, maybe virtual memory management and TUIs and "then you can't live without them"! (scream emoji). But so what, it's not a problem, nobody seriously programs on punched cards because they don't want to become dependent on screens and keyboards.

You can make a case that artisan craftsman furniture is better quality than Ikea furniture but that's not because the artisan avoids factory machinery and uses hand tools, it's that the artisan spends more time and effort and takes longer (and needs to charge a lot more money). If you want to make the case that the artisan shouldn't use tape-measures, laser levels, power sanders, power saws, dust masks, wood glue, clamps, they should use a pencil behind the ear, a thumb's width and a handsaw because that's how they learn the True Nature of Wood(tm) then maybe you're just posturing and gatekeeping, or have some sort of Amish-style religion.

Calling power tools 'crutches' is so you can imply that people who use them have disabled themselves. Instead it's like saying people who commute 20 miles to work in a car are using the car as a crutch because you can just walk 5 hours each way and that's more real. It's embarassing that people are so desperately trying to claim both "I don't use power tools because power tools are for weak babies and I'm a STRONG MAN" and in the same breath "my editor can do everything an IDE can do, it isn't inferior, it is a power tool!".

> "Just turning off syntax coloring freaks recent developers.. even quite good ones.."

Just turning off thermometer and oven temperature controls freaks recent cooks ... even quite good ones. Are you going to make the case that restaurants would be better if all cooks worked like your grandma with a log fire who had learned the right feel of heat for bread, cake, or roasts? No? Because that's obviously silly? But what if those developers one day in 2025 find themselves on a monochrome screen, with no shades of gray and no underlines or italics and no option to buy an alternative, hah what then?! Isn't that obviously also silly? NB. you didn't remove paragraphs or punctuation or capital letters from your comment, maybe you're just not a good writer and need these assistive crutches?

I find it so ironic that a surprisingly large fraction of computer programmers are such curmudgeonly Luddites spurning the most basic tools that make their job easier. Meanwhile engineers are using Solidworks to model mechanism that would be nearly or actually impossible to create without it and then running a finite element analysis to verify it is strong enough and using selective laser sintering to create prototypes for testing and then using MasterCAM to optimize the machining process and then sending it to a $300,000 5 axis milling machine with automated tool changer. Then the part's dimensional tolerances are verified using a $200,000 Coordinate Measuring Machine that is calibrated using gauge blocks made using laser interferometry and accurate to plus or minus a few hundred atoms.

You're erecting a pretty detailed strawman here. It's not that "raw dogging" code makes you a better developer; it's that specifically jump-to-definition and autocomplete make it too easy to create code bases that may as well be huge bags of functions and classes, and that skipping the mental work of organizing the code limits the fidelity of the mental model you can build.

Programming languages are complicated. Their standard libraries are extensive. Real world application are usually not trivial, because they often model real world processes, and the real world is messy.

Anything we can do to make writing software easier and more reliable, and reduce cognitive load, is going to benefit the software developers who are involved, and will make the systems better.

I'm sorry, if you can't jump-to-definition then you are wasting the company's time. It's something that all developers need to do and there's no reason we should be wasting time navigating a codebase when what you are looking for can be found instantly.

Same with autocomplete. I can type very fast, but autocomplete can type faster. Plus with the size of most APIs (even the ones built in to most programming languages) I have better things to spend brain space on. Is it list.empty(), clear(), empty(), truncate() or something else? With autocomplete I can find the function in want in 3 seconds (and read the docs inline, so I can tell that empty() doesn't empty the list, it tells me whether or not the list is empty) without lifting my fingers off my keyboard. Should I remember which is which? Maybe, but I don't care, and a jump between languages frequently enough that it's not worth the effort to keep track of silly things like that That's a contrived example, but hopefully you get the point.

It hard to cook without knowing the temperature, it’s not that hard to code without syntax highlighting.

In your examples white on smoke white text would be the better analogy

> If you want to make the case that the artisan shouldn't use tape-measures, laser levels, power sanders, power saws, dust masks, wood glue, clamps, they should use a pencil behind the ear, a thumb's width and a handsaw because that's how they learn the True Nature of Wood(tm) then maybe you're just posturing and gatekeeping, or have some sort of Amish-style religion.

Or you're William Morris, who was kind of ridiculous and pretentious, but was making a valid point at the same time.

https://en.wikipedia.org/wiki/Arts_and_Crafts_movement

I myself coined a term "kitchenware principle" that I have applied to my codebase as well. You put forks and knives adjacent because they serve similar utility and common purpose. Same with plates, cups, weird gadgets in separate drawer.

You should organize your code similarly and with as little fanfare. They are just tools, dont get clever with them. Sometimes, you get too many forks in same holder so you have to divide them but again, common sense prevails.

so `utils` is pretty much the 'junk-drawer' of the kitchen then ;)

I greatly enjoyed this comment of yours daltonpinto. Thank you.

I do not rejoice with code bases where every file has no logic or code in it but there are hundreds of methods and files with everything spread out. I have no idea how those projects fit together because the actual logic is spread out.

For my personal side project hobby work it's all in one file.

> I have no idea how those projects fit together because the actual logic is spread out.

There are two kind of mazes:

- those that are so tangled up that you can't make out any kind of structure.

- those that are so regular that you can't make out any kind of structure.

Exactly!

Not because it is split it means that was well split.

If you can reason where something should be, it may be badly organized.

Even single file projects can be organized.

If is small enough and makes sense, why not?

But even in a small file, how is it organized? Utility functions maybe at bottom so you keep business logic together and visible? Maybe some other logic to make it cleaner? The way functions are named follow some convention? What about variables?

I once read one opinion that software developers had more in common to artists and writers than engineers. Writing code is like an art of expressing yourself well to your peers in a way that a computer will also execute what you meant, not the opposite.

The computer can understand whatever entangled mess you write, other people (which may include your future self) may not.

A word cloud could be a useful navigation technique if the words were clickable and the sizes of words could be customized.

They could also link to other word clouds

Generated and updated automatically

> For my personal side project hobby work it's all in one file.

Ok, so this is work, but:

    find . -name '*.cs' -type f -print0 | wc --files0-from=-
    1035617 3438912 47446211 total
Not many editors are comfortable with a million line document that's 47MB. And that doesn't include generated code (which I very rarely need to look at, but is right there under F12 if I do)

A 100G file was ok in those editors even with syntax highlighting. That is an extreme because saving did take some time but there are ways to optimize for that would it ever become popular. IMHO 640K per file is enough for everybody.

  dd if=/dev/urandom bs=1M count=100k| tr -dc 'A-Za-z0-9 ' | fold -w 130 > largefile.c

Thanks for the hint about `--files0-from`, BTW. I thought I needed `xargs` for this.

We need tools that process command line output and large files and create tables of contents dynamically based on rules of architecture or comments and allow efficient navigation. I need overlapping buckets or tags.

I've been thinking about it lately but what I've seen in IDEs is not what I want

I liked OpenGrok

Are you willing to do that by hand? Have you heard of the author of _The Art of Computer Programming_ and the technique he created: Literate Programming?

The bane of "functional. No such thing as objects or classes, just a bunch of shotgun spread state fragments.

Cargo cult runneth strong on web.

Of course I agree that code should be organized logically, but I wonder if you could expand on what you mean. Do you drill down into finer and finer directories of detail, code units, classes and functions?

I work with someone that navigates the tree structure of all our directories every time they need to look for something. It is painfully slow to watch and if you ask me, they produce fairly spaghetti architecture. Some of that could be a lack of familiarity with the idioms of our platform and its available SDKs.

But I ⌘ click all the time as well as quick-open right to the class, variable or function I need to work with, and I feel like I still organize things better. I’m constantly fixing the weirdness and proposing even more things that should be improved.

You might even get a bit of a Conway’s Law effect by committing unnecessarily to a specific, onerous work style.

> I work with someone that navigates the tree structure of all our directories every time they need to look for something

Counter example: I’m working with LSP dragging codebase where basic code lint takes 45s. My colleague takes a break after each change so that their code navigation starts working again.

Inefficient people are inefficient.

Not using LSPs isn’t guarantee of efficiency just as using LSP isn’t one. Different strokes for different folks - one has to accept consequences though (more automation means less presence, but it’s everyone’s own choice to make).

It is not about speed, is about quality.

When I met the other 2 blind people, one of them joked that yes, they were very organized, but because they had to be, unlike us, being not organized wasn't an option for them.

I don't question the ability you may have to deliver quicker results, but I bet that your incentive to organize stuff is smaller than what your friend has.

Maybe he will be more inclined to refactor that than you and take even more time, and that maybe it pays off. Of course, I have no idea of your deadlines or if you are in a rush for MVP in search of market fit.

But this also follows those lines of: "wanna go fast go alone, wanna go further go together".

I value more quality than speed, but also understand that sometimes speed is what is needed.

Needs more RAM?

I've been doing work on a Raspberry Pi project, which got large enough that it took forever to get code nav back after an edit.

I switched to using VSCODE remote from a beefier machine with 32GB of memory (and an admittedly better processor). Editing response is now under 10 seconds. Sweetness and light! And even the compiles (which still take place on the Pi) run about 6x faster.

Nope, we are working on beefy machines. Problem are circular dependencies that trigger recompilation multiple times and macros sprinkle on top.

We’re refactoring it and get there eventually but without LSP and types (stack is dynamic) there is only so much that can be done.

[deleted]

When I mean organized it means having a structure that segrates responsabilities.

It could be applying DDD or some other pattern with that makes sense to the team.

If you are using a framework like Rails, learn well its conventions, follow them and change what your team likes and made it clear to all team members.

Also learn well SOLID principles and OO (of functional programming, or whatever you are using) and make it obvious that your code fits well your choices.

In other words, if some file (class, template, whatever) should have a single responsability, and by that, it should be obvious where that will be placed.

It has more than one responsability? How you can split it? And once it is splitted, it should be obvious where it should belong as well.

Adding on, I find that the people who manually navigate everywhere rather than using the IDE navigation features also don't use IDE refactoring features.

When people say "just organize your code well", this isn't something that happens perfectly on the first time, it's something that evolves as the codebase grows. IDE features reduce the barrier to reorganizing as we better understand the problem domain or as the solution grows.

My experience is that those who don't take advantage of their tools produce worse output, even if they believe they are producing better output, the organization they've created only works in their mind and not for their teammates or other people who later inherit the project.

> Of course I agree that code should be organized logically, but I wonder if you could expand on what you mean. Do you drill down into finer and finer directories of detail, code units, classes and functions?

from the parent (i am not the parent)

> I try to follow the logic and structure of the project in a way that feels natural and easy to follow later.

in my own experience it applies to everything in a codebase.

what the end state looks like completely depends on the problem domain at hand, and the tools used to solve the problem.

how to make a codebase “intuitive” is learned, not taught. understand the problem domain, understand the tools in use, then refactor, refactor, refactor, refactor until it makes sense.

> I work with someone that navigates the tree structure of all our directories every time they need to look for something

sounds like they have yet to learn how the code modules are organised.

possibly because the modules are not intuitively organised, possibly because there’s a lot of code, possibly because they just don’t care and don’t mind the mental break of mindlessly looking for the right module.

Not only learned, but it changes with time.

When reviewing code, the reviewer responsability is not only to make sure that it works, otherwise tests and its coverage would be enough, but they aren't.

If a reviewer sees that something does not fit with the convention that the team agreed, it should be questioned and also teached or discussed (if some new addition force the team to do so).

You don't need to know all the code base by heart, but how to follow it and place it.

Something like, does your team uses DDD? Where code that interacts with database should be? And how? How your templates are done? Do you use presenters? When? How? Any other patterns?

>You might even get a bit of a Conway’s Law effect by committing unnecessarily to a specific, onerous work style.

I don't find it onerous at all. I consider it the same kind of responsibility as writing tests and documentation. And I certainly don't think Conway's Law applies, since for my own projects I'm generally creating deep hierarchical call graphs while being the only person in the "organization".

I fully agree with the idea but disagree with the… submission to the norms.

We rarely talk about it and it’s also the constant source of teamwork issues. Look, if our code needs structure to be observable, it lacks structure in the first place.

Languages and editing methods — not talking IDEs here, it’s more fundamental — are still “empty file canvas, paint anything” model. That must be stopped.

These structural issues are analogous to malformed xml issues. They should not exist normally. We could start with e.g. better isolation/visibility systems than “files with exports”, then address lack of annotated TOCs for projects and modules. Then replace files with something more database-like. Theeen we could talk about someone breaking a nice structure. Because this structure only exist in a human’s mind, blindness only serving as a bitter “equalizer” to it.

" a good programmer should organize software in such a way that every piece of code has a clear and logical place. The organization should be so intuitive that anyone could build a mental model of the structure and navigate it easily, even without seeing it." sounds like very good advice to me. In the mid to late 1990s I worked somewhere that tried to do this with a big C++ codebase, because we didn't have IDEs (vi wasn't even vim at the time), unless you count emacs which some people were good at, not me at the time. I believe that IDEs are in many ways a backward step ,because they allow people to develop lazy habits and make a hideous sloppy mess of meaninglessly-named spaghetti, knowing that there's autocomplete and advanced search functionality.

I feel much the same way about how to write the code, but the idea of losing my sight is still horrific. I can't imagine having an easy time adapting to it and can very easily imagine giving up on coding.

I wonder if this makes it easier for LLMs to navigate your code as well. They are effectively blind.

sounds great if youre starting from scratch. I work on a project with 250k+ files I didn't create

Wow, excellent insight from these programmers. Very cool. Will be keeping this in mind!

This is the AWS SDK for Python.

Everything is “logically organized” am I suppose to remember every method on every class?

The C#, Java, Go and other SDKs are the same (they are all auto generated by the same definition file)

It doesn’t matter how well structured a codebase is, once it gets large, you’re not going to remember every method on every class

Of course, but there is a difference between programing using sdk/library/api and some glue, and actually engineering some self standing solution, and everything in between that. I belive blind programer wouldn't fare well in fast churn ci/cd every minute startup, but would be amazing in embedded space with multi year release cycles.

How many large applications are made with no dependencies or frameworks?

In another life, I worked on a SaaS app around railroad car repair billing.

These are the industry requirements.

https://public.railinc.com/sites/default/files/documents/CRB...

And this doesn’t include addendums, regulation updates, industry norms, extra requirements by clients etc

No matter how well structured the codebase is, it will become large and had a lot of classes.

Not to mention the underlying .Net framework

Have you worked with either the iOS or Android SDK? Do you expect people to know that entire SDK and a sufficient large codebase?

Autocompleting IDEs are not a new concept. It’s been part of Visual Studio since the mid 1990s.

Regarding organization, I heard an interesting perspective that may be worth consideration that I would like to hear your input on. The opinion went something like this:

> Well written, clean code is amazing. It is also an issue because the second features or specs change, you have to undo/redo the work you just did! Further complicating things are two other real-world concerns:

> 1) Looming deadlines might make the time needed to express "best organized" code to either be executed suboptimaly, or outright incongruities, leading to confusion due to parts A, B, and D being expressed very well, but C, and E-J are left looking wonky.

> 2) It can foster a "Don't touch" mentality. "Oh, Bob (the pro) wrote that! Better not mess with it. I'll work around it with a hack-y solution." Basically it's a suggestion that, "In order to write very well organized code, you have to be an excellent programmer. So what do you do if you work with subpar to average programmers?" It would almost seem to suggest that by writing well organized code, you are giving yourself even more work, because it is intimidating or too daunting to other programmers who aren't at that same level.

I'm not sure how much I agree with those points, myself. I kind of feel like they are a cop-out, a kind of excuse to go with less thought out designs. I do see, however, that as far as real world situations are concerned, managers and even fellow programmers might prefer "good enough" to be done with it. I'm not really sure what to make of it, but it does seem to make a kind of sense.

I work with two types of LSP/LLM-averse programmers:

1. The HLSP user

This group does use an LSP, it turns out, only via you as the conduit: you are their Human Language Server Protocol. They'll ask, ‘can we pair today?’. From that point, navigating code, looking up method names and signatures, and flagging syntax errors before runtime or compile time is your job. How they find their way around when you're not there is unclear, but it's likely slower.

2. I am one with the machine

This crowd has been wrangling code long before IDEs, LSPs and LLMs. They've amassed a terrifying arsenal of tools to find files and references, bulk-rename, pull up docs, and twiddle bits in ways that looks fluent and natural enough when _they_ do it but would take months or years for you to learn if you didn't give up and go back to your IDE. When you ask them _how_ they just did something, they either pull up a short page of Elisp and say, "it's really quite simple we just reverse the node tree and iterate over the folded quarkenspace", or — if they're a vim user — say something like, "oh, that's just the hiboscus plugin, but piped through smark".

So the response to "how do you do it?" seems to be broadly summed up as, "the way we've always done it".

Group 2 isn't necessarily _better_ than LSP/autocomplete/heavy LLM users (people who are very proficient with more modern tools can look like magicians too). The LLM-free crowd were just forced early to become proficient, they've gotten very good with their home-rolled methods, and — in many cases — they probably wouldn't benefit that much from LSPs, or they use them but with features that bug them switched off.

Group 1 would probably better be served by an LSP but either don't believe in the benefits or is just comfortable with their current setup and feels no pressure to change.

I might be in group 2, rely heavily on command line tools and vim to do what vscode and a load of plugins provides younger programmers.

My answer to the fairly common question of "how do you do it" is always the same though.

I always relay that it's taken an evolving 20 year career to learn all that voodoo, I never imply it's simple to gain that knowledge nor do I encourage others to change their working patterns to match mine. I do like showing off a few tricks though!

One thing I do always mention though is the longevity of vim + the command line. I went through a period of swapping IDEs like most junior devs, now I have a setup that I feel can last me till retirement and I can just continually invest in learning to use the same tools better

I've been coding since the 70s . using a modern IDE or VSCode has nothing to do with age

No that's not my point. Becoming very proficient at vim or knowing you way in depth around the command line takes time, years in my experience.

Maybe with 50+ years there's a limited amount left to learn, but with my 25 I'm still picking things up regularly.

So it's usually more junior and less experienced developers who ask "how do you do that" - sometimes with wonder, sometimes genuine confusion.

My answer is never "it's simple" or "it's just" but always something along the lines of "it's a culmination of using the same tools consistently for many years", usually followed by "hey have you seen this trick too".

It's weird to me that you group LLMs in with code analysis based LSP autocompleters.

Normal autocomplete is basically a context-aware AST browser. It lets you navigate the program semantically instead of file-based.

LLMs are token predictors.

The parent did the same, but of course they're different. The spirit of the question seemed to bundle LSP/autocomplete/LLMs under tooling that some do without.

The way I use LLMs a lot of the time is to simply let copilot complete the method parameters that I was already planning on typing or autocompleting the fields of a struct. It's barely a step over LSP/autocomplete tools but because LLMs have access to more context and aren't restricted by the things they can autocomplete, they work in more scenarios. LLMs get things wrong occasionally but it's usually easy to catch and LSPs can fix those errors.

> This group does use an LSP, it turns out, only via you as the conduit

Oh man, it makes my blood boil when someone asks in which file the function lives, and I know they have a "go to symbol" in their editor of choice, but somehow they never want to learn some features of their tools. I did notice that how you use your tools changes how the project is structured. Neatly organized files and directories are a must if you are not comfortable with quickly jumping to a symbol.

[dead]

LSP enables you to program as you go along, without ever understanding the structure of the whole program. If you don't want to use an LSP you pretty much must understand the whole program you are adding code to

As wikipedia likes to say, quotation needed.

If anything, code-aware tools let you learn the structure of the whole program quicker because you can quickly drill into and explore any arbitrary part of your program (and libraries)

Very well summarised

Is it though? It reads to me more like elitism to me.

A better summary is: “people have different workflows because different people like to approach problems differently.”

That’s all it is.

I find LSPs largely get in my way. I don’t have them disabled because 1% of the time I do find them useful. But for the other 99% of the time they’re adding no value at all. So I could very easily write code without an LSP (and often do write code in vi with zero additional plugins installed).

What I do really value is code formatters. I like not having to write tidy code and then having code formatters clean it up when I hit save. That’s the kind of enhancement I value. (It also gives me piece of mind that a file has saved successfully when you see alignment pop into place).

> people have different workflows because different people like to approach problems differently.

But the way you like to approach problems is heavily influenced by your history of solving them, what tools were available at the time, what you chose to adopt, and how often you revise that toolset.

It's not elitist to say that people tend to use what they've always used, which was my point: "how do people cope without LSP/LLMs?" tends to be "the way they've always coped" — efficiently or otherwise.

And it tends to track with when you began programming or using specific tools. A vim user who adopted vim in the '90s is more likely to have a light config than those who adopted it more recently, where I see heavy plugin and plugin manager use, LSP integration, pre-configured distros, and Lua-based configs.

I’ve spent lots of time working in IDEs and lots of time working without them.

Generally I find IDEs more useful when I’m working with an unfamiliar code base or an unfamiliar language.

And that’s probably why there appears to be an age gap. It might be more down to comfort with the code rather than comfort with the tooling.

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 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.

>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....

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.

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.

> 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.

Arguably, they did turn it off: the whole IDE, at once.

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.

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 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)

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...

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.

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.

> 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.

> 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.

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 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.

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.

> 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.

[deleted]

[dead]

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.

Yes, very zen. How does your pairing partner feel about this?

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.

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?"

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.

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

Great, another pragmatic programmer producing sphagetti

> 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.

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?

[deleted]

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.

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.

[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.

> 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?

So, your argument is that AI does not replace programmers, it just... replaces programmers?

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

I wasnt aware of any that could

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.

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.

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

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

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.

> 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.

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.

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.

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.

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.

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.

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.

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

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.

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.

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 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.

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.

Autocompletion has been common for at least 29 years since MS added it to Visual Studio.

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

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.

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.

The shell is my development environment. I open up new terminals and shells willy nilly. I find cli tools like find/fd/grep/rg are useful because I rarely need to find only the definition of a function, but rather other call sites too, to find out how it is being used. I think being surrounded by the code and being able to slice and dice it leads to a certain kind of familiarity that a tool that takes you right there doesn't afford. I like fast compilers, and type checking, so it doesn't matter if I can remember the types and fields. I'm not bothered by error messages or warnings, I fix them and I have a greater understanding of the code I'm writing. My editor is a pretty stock vim setup with format-on-save and syntax highlighting, but I can operate without those (in fact, I'm often hindered by some other defaults, like bad color choice (dark blue on my black terminal) that makes things hard to read. I dont have much vim customization because I can not rely on it always being there. I use a pretty basic setup that lets me be productive in just about any default unix/Linux environment. I find IDEs to have a lot of visual distractions. When I was first exposed to unix in the early 90s, programming using it just clicked for me and I've never really felt hindered by the defaults. I read man pages and the languages' stdlib docs (usually web pages) so I'm a little more than passingly familiar with what's in them and their capabilities and how to navigate them.

This is my mindset as well. I often need to work with text that isn't code. Maybe it's a SQL dump someone sent me, some bespoke configuration format, a collection of log files, etc. Knowing how to manipulate and navigate text is extremely helpful as a general skill. IDEs degrade to notepad.exe quality when presented with unknown formats.

Personally, my recent work has been: short term freelance work, new code bases, a variety of programming languages including ones I haven't previously used, problem identification and solving, and mature code bases where you'd only write a couple lines of code a day.

In that context an IDE optimizes a tiny part of the work, while getting in the way for everything else.

I'll add that when I worked on a greenfield Java project as part of a large team, I absolutely used an IDE (IntelliJ at the time) and couldn't imagine working differently.

Thank you. I feel like I’m taking crazy pills because I (mostly) hate autocomplete; it mostly just gets in my way. I do almost everything in Sublime Text with very few plug-ins. At the same time everyone around me is using the latest VS Code and going on and on about how great it is when you just hit tab and it writes the code for you. It makes me feel like I’m wrong in some way.

I have an alias for `vim -p $(git grep -li "$1") +"/$1"` that allows me to quickly open files that contain a given string.

I used something similar for a long time, but the past few years I've been using Path Picker.

  rg string | fpp
  git status | fpp
  git diff head~1 | fpp
And with Zsh suffixes you can even drop the pipe.

https://github.com/facebook/PathPicker

I did it this way for about 20 years and recently moved to VSCode with its integrated terminal. It makes me feel pretty lazy and like I’m “cheating”, but there are some productivity benefits (LSP), and I’m less of a purist than I used to be. I maintained a blog about vim for 3-4 years, so I was pretty committed to that workflow back in the day.

I know about VSCode's terminal, and the few times I've used it seems like an afterthought, bolted on, to the primary function of the program as an editor and file navigator. I don't live in the editor. I live in the shell. The editor is a sub function of living in the shell.

I actually think the VSC terminal is one of the few saving graces it has. Maybe not so much on *nix. It works well enough on Mac, but it really shines on Windows where you’ll have a much easier time running powershell, GitShell and WSL terminals within VSC than outside of it. It also has really good integration with the various Azure CLI tools.

I don’t think VSC is a very good IDE though. I have no idea why a Vim user would use it instead of upgrading to Neovim, and obviously doom emacs is the best choice but I do think the terminal is actually pretty good in VSC. At least on Windows.

> I don’t think VSC is a very good IDE though

As someone who has only used inferior IDEs to VSCode (grimaces at the thought of Xcode) and who thinks that VSCode is very good, what exactly am I missing from better IDEs?

Vim/Emacs (and variants) are like a tailored suit. VSC is like an off-the-rack suit. It's a silly analogy but it's probably the easiest way to explain it. For me personally it's productivity, and things like LSP quality in languages which don't have very good VSC plugins. The vim plugin for VSC is pretty bad.

That being said, use what works for you.

on windows VSCode is a great way to remote into a VM with with a sane-er OS.

[deleted]

Visual distraction in IDEs is amazing. I see my co-workers using Visual Studio or something, and I can't even identify the code they're working on among the mess of the screen. There's so much going on. The clean and pure display in vim in my terminal let's me just focus and get shit done. I honestly don't understand how they get anything done, but to each their own.

> The shell is my development environment

*Hell

Good point re: using error messages. If I call a function incorrectly, the call stack will helpfully point out the file and line number of the location the error was thrown from, just a few keystrokes in vim will get you there.

> the call stack will helpfully point out the file and line number of the location the error was thrown from, just a few keystrokes in vim will get you there.

Or Cmd+Click/Ctrl+Click in an IDE

Uhhh that would involve a mouse, gross ; )

Do you use a keyboard to browse the internet?

On unfamiliar codebases a mouse with back and forward buttons can be quite a fast and convenient way to get the "lie of the land".

I often do this inside GitHub's browser-based editor.

> Do you use a keyboard to browse the internet?

Yes, using the vimium extension. My only problem is text inputs like this one, my muscle memory expects vim keys to work and I type a lot of jibberish that I have to clean up. I know there are extensions for that too but I can live with it.

Tridactyl has a native extension that lets you run external programs, such as popping up a gvim window for text inputs.

"Uhhh that would involve a precision action with a tool specifically designed for precision actions" ;)

I can definitely hit my Return key with more precision than I can drag a cursor over a 40x400px target but go off :P

(I use a Superior Technologies trackball because it's the only mouse I could find manufactured in the USA and it's really not very precise, it's kind of a self handicap to nudge me towards keyboard shortcuts, muscle memory gains just have a steeper curve on keyboard than mouse)

> I find cli tools like find/fd/grep/rg are useful because I rarely need to find only the definition of a function, but rather other call sites too, to find out how it is being used

And find/grep are very bad and limited tools for this compared to what an IDE will give you

Kind of? Text search will also find commented out usage, docu, changelog, and my .org file with refactoring ideas from last month. (For better or worse.) It will also show when a class with the same method names exists elsewhere - which you want to know about if the naming is good. To find usage of a method called "update", LSP results will be better, but... that was kind of the point? That you don't name your methods "update" if they are important semantically.

And rg also works in projects with multiple programming languages (e.g. you're using a method from JS and want to find its Rust implementation in the webassembly module) and across project folders (instead of pointing you to a read-only copy of an installed module). But, if you spend 95% of your time in a single codebase with a single language... YMMV.

> Text search will also find commented out usage, docu, changelog, and my .org file with refactoring ideas from last month

Yes, when searching across the entire project for text an instant fuzzy search is an invaluable tool.

> It will also show when a class with the same method names exists elsewhere

Oh, this is a great example when a code-aware tool is better. I also ave a rant-ish about LSP at the end.

So, let's say you have several methods called `update` across your codebase. As per original comment, "I rarely need to find only the definition of a function, but rather other call sites too".

With text-search you will find all those other methods, and all the call sites for those methods. And not just in the working code, but across all tests as well. So you have to manually go through the search results and figure out whether a call to update is the one you're looking for.

In an IDE it's just a shortcut:

- go to definition https://www.jetbrains.com/help/idea/navigating-through-the-s...

- go to implementation https://www.jetbrains.com/help/idea/navigating-through-the-s...

- Find usages https://www.jetbrains.com/help/idea/find-highlight-usages.ht... perhaps even inline https://www.jetbrains.com/help/idea/find-highlight-usages.ht...

- find the full caller hierarchy https://www.jetbrains.com/help/idea/viewing-structure-and-hi...

And so on.

Oh, you want to know where all the methods called `updated` are defined to go and scream at someone?

- Search for symbols https://www.jetbrains.com/help/idea/searching-everywhere.htm...

Of course all that is also integrated with things like refactoring. So if you rename a method, you don't have to painstakingly manually search for all invocations of that method. Or if you rename a parameter to that method, or... See the several dozen possibilities here: https://www.jetbrains.com/help/idea/refactoring-source-code....

----

Here comes the rant.

The whole "text searching is enough, the compiler will pint to me the errors I've made" fashion has held back tool development by several decades. It's telling that LSP (which has barely 5-10% of IDEA's functionality) has taken this world by storm. Suddenly the languages and the editors that lacked even the basic quality of life improvements when working with code got a glimpse of what is possible.

Welcome to the very early beginning of the 21st century. Perhaps in 20 more years you will finally let go of the notion that painstakingly doing a computer's job is not in any way or form productive or indicative of a great programmer somehow [1]. And that to work with code you really want tools that are capable of working with code.

After all, somehow, you reach for Excel/Numbers/Google Sheets to work with spreadsheets, for Photoshop/numerous alternatives to edit photos etc. You don't reach for some generic vaguely-adjacent tool to do the job.

[1] I keep telling this story: About 5 years back I saw several people switch from vi/emacs to PHPStorm/IDEA after watching me zipping through code (including jumping from Symfony configs to code and back) while they spent often minutes doing fuzzy searching through the codebase we were working at the time: a huge legacy monolith we were slowly refactoring and splitting up.

I'm glad you mentioned IDEA, so I didn't have to. People rave about LSP and it's great that it exists, but IDEA has been doing more advanced code navigation for years (decades?).

You seem weirdly angry that some other people like to work in a different way than you like to work. People like different things. You still get to like your thing.

This post just gave me an epiphany. I work with some programmers in their 20s. They are some of the best programmers I've ever met. But they never seem to enter "flow state". In fact, they welcome distractions. And now I think I know why.

When I was coming up, you needed to enter flow state to be a good programmer. Because you had to keep track of all the functions and their signatures, all the different flows and objects, all the different files. And if you got interrupted, you had to reread the code to "load" all that back into your working memory.

But now the tools do that for them. They can click on a function and see the definition. The copilot and autocomplete will keep track of all the minutiae for them. So they don't need flow state to be productive.

This revelation may get me to actually switch from vim to something with all these modern features. Maybe it's finally time for me to try VSCode.

Especially since my kids never let me hit flow state anymore even if I wanted to!

So one of my current projects has a part that is five coordinated microservices. Two of them need to use concurrency that modern tooling doesn’t love out of the box. The entire system has to have strict timing and low latency. Autocomplete can help with some pieces but this isn’t actually that much code. What it requires is being able to visualize the whole thing, be able to test exactly how the underlying libraries respond to different kinds of errors, and how to prevent deadlocks. I have yet to meet an LLM capable of reasoning about deadlocks, catching signals within threads of a process, correct semantics of anonymous pipes and their buffers, etc. In order to work on something like this it does require flow state. You can’t just casually add a few lines or rework some module. You need to visualize the entire system, including error flows, before you can start changing it.

I could likely use some basic autocomplete for things like a function signature, but most times I have the function implementation on one side of my screen and where it’s being used on the other and chances are I’m changing both at the same time. Vim is wonderful for this kind of work.

If you'll allow me to shill my company for a second, I'd be interested if you could take a look at DBOS[0] and tell me if it might simplify your problem. It's designed for making microservices a lot easier to reason about, and might help make your system a lot simpler.

[0] https://docs.dbos.dev/why-dbos

This is something I have been noodling with a bit. I'm 40 (started in my late 20's). I welcome the distractions as well.

When I was learning, I would always have a movie or TV show on in the background.

On stream, I am constantly responding to chat. But I am able to delay that by up to a minute most times. So I get most of my work done in short bursts.

BUT, while distracted by a TV show or a chatter on stream, my brain is probably not completely distracted. It becomes a moment for diffuse thought to kick in rather than relying purely on focused thought. (For anyone reading and unaware, diffuse thinking is what causes "shower thoughts")

So, those distractions are just a way of forcing myself to toggle between thinking states.

Diffuse thought is also the reason why I never end on a resolution for the day. I always try to have something that I can stew on overnight while going to sleep, waking up, showering, doing the dishes, etc. I have solved several bugs on my morning commute back when I used to go into the office.

Something somewhat related. People who do non-traditional sleep patterns like biphasic, or even something as extreme as uberman, are able to get to sleep faster than most people with traditional sleep patterns. It is something that you can actually train and practice. Forcing diffuse thought more often maybe helps it kick in quicker too?

You don’t need to ditch vim to have these features! Mostly they’re using lsp in a client (editor) / server relationship. You can run the same tooling happily from vim (I use neovim, but I believe it’s all implemented in vim too).

I liken this to asking people who don’t use a GPS how they drive and if they have every intersection memorized. It’s not about absolute knowledge of a codebase, but intimate familiarity.

I also don’t think it’s a coincidence most people in the comments seem to be using some flavor of vim. I think using an editor designed before these tools were available will make it much easier than afterwards.

I’m not sure I’m the best case, but I just turned off copilot, haven’t bothered to configure my autocomplete yet in my latest neovim config, and only use an LSP so my macros can be highlighted differently. I write primarily in Clojure though, so inline docs and go to definition are just a part of life.

I don’t really have anything against LSPs, but neovim, telescope, and the repl have always gotten me where I want to go

With regards to my flow, I’ll normally have 1 vim session for every 1 project, each with 1-5 tabs open, each tab with up to 12 splits. There isn’t really structure to the tabs or splits, I’m just liberal with opening splits and conservative with closing them. To me it can be really helpful to have all the recent code I’ve been working on open at one time, and if it’s not, I just pop a new tab and start fresh

> I liken this to asking people who don’t use a GPS how they drive and if they have every intersection memorized.

I find people who drive with sat nav often don't learn almost anything about their route (they don't have to! is the whole point!)

I at least orient my navigation north side up so I have a basic clue what I'm doing.

A friend of mine looks at navigation before driving, then turns it off.

I agree - I had a traveling consulting/repair job before digital maps were a thing. Every year a 50 page city-wide street map book would come out, and you'd buy one every few years from Costco, as needed.

North was always up. I learned to navigate in that mindset and to this day maps that rotate based on direction facing (even in video games!) just don't match the mental model I have of driving.

GPS's gives you a single track view of how to solve a problem, when it's either advantageous or required to react differently (ex: road hazards, opportunistic turns if driving diagonally across a grid), and when you deviate from the single track it creates annoying noise, especially if the road names are not phonetic or in other languages.

There is a route I drive at least once a week. I can do it without GPS (in my case is Google maps via Android Connect).

Yet, every time I ignored the suggested deviations from the "standard" route, I ended up regretting it.

As an example, last time I was 2h late for a meeting because I ignored the "scenic route" suggested and ended up stuck behind a car crash.

Most of these tools are distractions. I don't want suggestions or needling warnings sliding around on my screen while I compose and examine programs; I want a quiet space to write and think. Focus is essential.

I organize notes and action items in a paper notebook in front of me or a text file in another editor pane. I read the code. I search and diff with standard POSIX utilities that are available in every environment. In the languages which support it, I try ideas and answer my own questions in a REPL.

Practice leaning on tooling all day and living without it will feel unthinkable. Practice doing without, and you'll find you need very little.

Agreed. I don't need my code to turn red just because I haven't finished writing the entire line. I'm aware this isn't valid code, I'm not done.

It is remarkable how much easier it is to acquire and recall relevant information while programming if you don't have an IDE constantly spraying distractions in your face and breaking up your train of thought.

I don't code a lot, an when I do it's PHP, HTML, JS, CSS, or Python, and I still just use nano.

If you prefer not to, that's fine; we all have our preferences. But I'd ask the person who pairs with you how much the productivity is actually impacted. In my experience engineers are very prone to romanticizing arbitrary stuff (languages, editors, tools, window paradigms, processes, debuggers, event fonts and colors or whatever). Your coworkers will see right through it, though, and won't hesitate to be honest.

I work almost exclusively in Emacs without the modern LSP-based tools. I believe I do keep more in my head than programmers that use more advanced IDEs.

In code I have control over myself I avoid imports that doesn't enumerate all imported symbols. That is I always use the import Library (symbol) syntax in Haskell and never do wildcard import in Python.

When coding C I sometimes use tags so that I can go to definitions quickly, I should probably use it more than I do to be honest.

I do use hippie-expand for quick auto-completion but it is completely textual, it has no understanding of the programming language it currently works on which makes it much less powerful of course but it also has some benefits.

I always have the documentation very reachable, I use a search keyword in my browser to search on hoogle. I type H <Space> symbol/type-expression <Enter> and I quickly find the documentation.

I do use Visual Studio on a Windows box for working on a C# codebase a couple of times per year and when I do I always turn off that code lens thing and I find that I rely on the code navigation features quite a bit. Part of it is probably due to it being a code base that is larger and that C#(/Java)-flavoured OOP makes the code more spread out. In terser languages like Haskell (which is much terser) it is natural for more functionality or types to live in the same file which means that you get much further with just simple textual search.

That was me for 7 years (using vim instead of Emacs), and it was working fine with Python and Go. I used ctags for navigation, some shortcuts for pydoc, and that was essentially it.

Then I started working with Scala and, until metals (the language server for Scala) and LSP support was good enough (first vim, now I'm a happy nvim user), it was awful.

So I'm certain it depends on the language. My take before Scala clicked for me was that I didn't want to use a language that required an IDE (or IDE-alike features) to be productive. And I think that opinion was mostly because my bad experience with Java.

I still write C without LSP, and I'm fine.

Despite many years of development, I find lsp and eglot to me mostly unusably slow. I need my emacs to be fast and the only way to achieve that is something oldschool like Jedi/Elpy for python.

> I work almost exclusively in Emacs without the modern LSP-based tools

I'm wondering how many people in the comments would misinterpret it as "Emacs is outdated"/"Emacs does not have modern LSP-based tools"

I was about to switch from Emacs when I found TIDE for Typescript development (which is what I do), and it kept me in Emacs for years longer.

Recently though I couldn't resist experimenting with Copilot and I switched to VS code for it, after 32 years. Is there a good Emacs module for it by now?

I don't know whether there is Copilot module for Emacs, sorry. I'm more of a fan of gptel approach https://github.com/karthink/gptel with explicit context and instructions.

There's definitely a lot of choices in Emacs land for these new LLM tools. There's copilot mode, chatgpt shell, gptel, theres so'e more from other AI startups. Plus writing LLM integrations for Emacs is a breeze with everything being text buffers.

I've not used copilot outside of emacs, but copilot-mode does everything I would want for code generation.

I've been using copilot-mode in emacs for probably a couple of years.

The reason I spelled it out is because I don't use them even though they are available. I realise now that what I wrote is ambiguous, thanks for mentioning it.

But that's bullshit. emacs has had most of the tools that LSP enables, it just had that only for some languages that had better emacs modes (C, elisp, Common Lisp etc.). All LSP is doing is making it easier to write modes for new languages really. emacs with eglot (not the LSP modes which are generally terrible) is a great IDE, and does thing the emacs way. Saying you use emacs but don't like "LSP" feels like a joke to me. The very reason SLIME was so great decades before IDEs became mainstream was that it was already a powerful IDE, it just does the IDE things a bit different than you're probably used to.

The sibling comment about a blind programmer is very worth reading, because it is relevant to what I've observed about other (non-blind) programmers who are highly skilled: they do not need tools to tell them what to do, because they have completely internalised the structure of the program and can think about it as a whole. Incidentally, one of the things I often do when solving a problem --- be it finding a bug or fixing it, or implementing a new solution --- is to close my eyes and think deeply about it, without distraction.

I don't use IDEs either. A plaintext editor and a console window (for compiling, testing, and the occasional grepping) is enough. IMHO someone who is reliant on IDEs and autocomplete is in the same category as not knowing how to type without looking at the keys on the keyboard --- yes, you can get by, but you will never be able to code as fluently and effortlessly as those who can think deeply about the code entirely in their brain, and you'll be frequently writing code that looks reasonable when viewed in isolation but obviously redundant and/or inefficient if considered as part of the bigger whole.

This works for small projects.

I've worked on projects where "hold the entire project in your head" might be somewhere between very hard and impossible. Work the right abstractions, it should be possible to hold the relevant parts in your brain. Still, when you're new to a large project, an ide goes a long way.

Would you consider the Linux kernel a small project?

That's an example of one where a large number of people working on it do not use IDEs.

Yes and they maintain their part of the code. The one they've been working on for 30 years.

I've worked on forks for certain Android devices with very primitive text suggestions that notepadqq provides and the difference in productivity between that and vscode+clangd is staggering. What do you mean there's a macro for anything?

I wouldn't. Good point!

> because they have completely internalised the structure of the program and can think about it as a whole

This state is definitely how you can be most productive.

However, I've written multi-millions of lines of code and many different still active applications. It's gotten to the point where if someone asks me if an app has a particular feature, I have to open it to check even if I wrote the whole thing.

Not all projects I work on are one's where I still have the whole thing internalized.

As someone who started programming on Solaris UNIX, then Linux workstations, in the late 90s, there just wasn't an option. You used vi or emacs or you didn't work.

I'm not saying it was the good old days but it was not a significant barrier to doing what we wanted to do. Code is code and ultimately you need to have a clear mental picture of the codebase, regardless of your tools. LSP isn't valuable because it allows novel functionality (there are dozens of different techniques for discovery within a codebase). LSP is valuable because you have an efficient way to "query" your codebase for contextual information directly in the editor window.

But you can build that knowledge through other means, you just need another terminal window and external tools.

The understanding of the codebase is what maters. LSP is a means to that end, making an already common task slightly more efficient.

> look up the definition/implementation of some function

Text is effective. git grep "def foo"

Autocomplete engines work on text too, based on the contexts of the buffer or files in the directory.

Static analyzers have always worked wonders in identifying LSP-like warnings.

Compilers and debuggers give you access to state and type information.

This stuff has been around for decades. LSP just makes it more convenient and packages it into one UI.

For what it's worth, I'm 100% in on LSPs for my work these days. But if LSPs disappeared tomorrow, I could revert to the old ways with only a small hit to productivity.

Embrace the diversity. Some people use these tools, some don't. What matters is that you build something great at the end. The only people that are 'wrong' are the ones that mock those that use the features and the ones that mock those for not using them. Probably the best programmers are the ones that can adapt continuously to the new tools out there and find, and use, their strengths.

I hate annoying distractions, be it popups, beeps, notifications, alerts, auto brace/quotes/etc and autocomplete prompts. I turn all of that off in every program because I want to be in total control of the computer.

When it comes to autocomplete specifically I initially turned it off because I was mainly a C++ programmer and C++ autocomplete has just never been good enough and a half-working autocomplete is just worse than nothing at all because you end up stalling and waiting for the prompt. But eventually I just grew to hate it for all languages because it interrupts flow and "pipelining".

> I hate annoying distractions, be it popups, beeps, notifications, alerts, auto brace/quotes/etc and autocomplete prompts.

This was also my first reaction when I saw someone else using an IDE. My way of writing code is to get my ideas written into the editor first. Only after I have written the code, I run the compiler to see where things don't fit. The people who were using the IDEs were really astonished that I could understand the output from the compiler on the command line.

Programming is a lot more fun when you sketch out your ideas first before you make sure that all the details are correct.

When you have a good mental model of the code base you're working on (and the libraries you use), you don't really need a lot of IDE features, and IDE features can sometimes hamper the formation of such a model. Let me explain:

Twenty years ago, my IDE was two terminal windows running VI, vertically tiled. On the left, I open header files, and on the right, source files (I was a C++ programmer). When I wanted to look up method signatures or member names, I would quickly look it up from the relevant header file. This could take anywhere between 5-60 seconds.

If you remind me that IDE features could improve this by a factor of 10x, you're absolutely right. But if we apply Amdhal's law to developers, their biggest time waste is often not the physical act of coding, but fixing logical and structural issues in their programs. And the best way to prevent such high level issues is for the programmer to have a good mental model of the code base.

So, the possession of a good mental model of your code base obviates the necessity (but not the convenience) of IDE features such as autocomplete/intellisense. But at the same time, reliance on such features hampers the formation of a good mental model.

My current compromise is to rely more on the "Go to definition" function than auto-complete.

I’m not a developer but someone who is curious about development, can you explain what it means to have a good “mental model of the code”. Does that mean where you understand all code and what it does?

That's at the deepest level. I'd say you can stop one level up: knowing which function serve which purpose, which functions call which functions, which objects maintain which state etc. If you can trace any input/request from the event handler all the way to the database and back, then that's a very good start.

Yeah I think that's correct. It's the combined effect of being able to read the syntax of whatever language it is (Ie understanding code at a small-scale, which is different for all langs), and also to be able to understand/imagine the overall behaviour of it: at a larger-scale, which I think is largely language-independent. I think of it as similar to imagining how to do something or imagine how something works. The analogy could range from as simple as 'how to make a cup of tea' (a small script, or single method say) all the way up to 'how a car engine works'-level like big codebases (kernel, llvm, code-for-whole-app kinda thing).

1. Memorization (i.e., knowledge) beats tooling every time.

2. Pain is the most effective way to learn.

I was a 90s kid, still just young enough to have my parents tell me to go get out a paper dictionary when I asked "what does this word mean?" It's amazing how much better it "sticks" when you have to stop, get up, open a book, and find the entry.

With a minimal vim setup, I find that I just know Linux, the language intricacies, and the codebase better than my coworkers – not because I'm smarter but because I have to manually look up things I don't know. It's slower in the moment but over time it is much, much faster.

For the same reason, I never copy/paste code that I could not have written from memory.

Use it or lose it (or never gain it in the first place).

In a past job I have worked with other engineers and even some, who were senior engineers, however, I was the only one, who was able to write a proper shell script. This knowledge came in handy also for writing CI files, which somewhere tend to have shell commands in them.

You don't do it yourself, you don't learn it. Simple as that.

I turn off autocomplete everywhere I can. Whether web searches, composing code, or anything else, I do not want the computer anticipating what I am about to type. I find it is often wrong, and always distracting.

Yes, I try to learn the language well enough that I know the parameters of common functions. If I don't, I consult the docs. If I need to find the definition of a function in another file, I use grep.

There's nothing more annoying than putting my cursor on text, and then having a pop-up block that text.

Indeed. Completion, yes. Auto-completion, no.

Disclaimer: I do use LSPs extensively, but they do what they are intended to do when I explicitly ask. Offer completions. Format code. Organize imports. All that is available, but only happens when I ask. Same happens where there's no LSP support, and basically the same commands depend on ripgrep, fzf, semantic-grep, external linters and formatters, and plainly compilers.

Me and my tools take turns. It's almost 2025, practically everybody agrees that concurrent mutation of state is a source if trouble.

I find myself mashing escape regularly in PyCharm to get rid of dialogs that interrupt my view and/or train of thought.

Why does it block it and not the adjacent area?

Similarly, I find in vscode, if I'm writing something on a line based on the line(s) above it, the popups block what I'm trying to look at. It makes sense that you'd mostly be looking at the lines above, not below right? I have to type a few characters, hit esc, type, esc, type, esc. Also, I often have to hit esc before pressing return. Deleting brackets that it added where I didn't want it; I'm probably supposed to highlight the part I want to enclose and then type the opening bracket though; I run into that when I intentionally want to replace some text with one bracket and it encloses it instead. I disabled IntelliSense but I still get the other automatic behaviors. I really like the auto-indent though. That alone makes me put up with the rest, and I'm used to all the ways it gets in the way now. Kind of like how you get used to hitting esc to get out of insert mode in vi.

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'm an old school programmer - built my first 8-bit home computer in 1978, and been programming ever since (currently Linux/C++ telecom - heavy multi-threading).

There are tools like ctags that have been around forever and build an index of definitions to let you jump to them, but personally I've never found a use for it, anymore than I ever found a utility for IDEs. I just have multiple terminal windows (or tabs) open along with my editor (emacs).

When I'm deep into a project - even a very large one, I basically just remember where everything is (as well as the code itself), or when needed just use terminal find/grep. For stuff I've written from scratch myself (vs at work working on a large legacy codebase), code organization is certainly part of it - organizing code into file-based modules. I use record/playback editor macros a lot to avoid typing, and occasionally use sed (scriptable Linux command line editor) to perform entire codebase renames etc.

I've tried modern IDEs like VS Code, but really don't find them to be a productivity benefit. I get the appeal of a single tool/environment that does it all (like old-school hard-core emacs folks who treat it as an IDE), but in terms of productivity you can work just as fast with a collection of tools rather than a single one.

My preferred way of working is plain sublime text and the terminal. I use command line tools for linting, formatting and type checking, wrapped in “make lint”.

I find that sublime is just smart enough to go to the definition using only its “dumb” grepping based approach.

I think the hurdles of getting a nice LSP setup that works across projects in different languages and in a polyglot monorepo is a real determinant. I just really dislike spending any time configuring my editor past the basics, because I’m lazy, updates break them, I move between machines, etc. Getting comfortable with just the basic features means I have less pain maintaining my editor. It’s not a great excuse but for me it’s the path of least resistance.

I frequently pair with colleagues, some are vscode users that are heavy on LSPs and copilot. I have one greybeard colleague who runs a very sophisticated neovim setup, and spends a lot of time maintaining it. We’re all roughly equally productive at the “writing code” part of the job. What sets us apart is our skill in actual software development, which I find is completely uncorrelated to the editor setup. We all work in the tools that are most comfortable to ourselves.

Some of us learned (and later shared it) at the times when you had to close an editor to access digital manuals. We went through different phases of “dev envs”, some of which were not that advanced (or later died), and we invented our own stable ways to overcome the issues. Some people chose complete off-road, some found a balanced approach. It all turned into various knowledge bases, muscle memory, tools, habits - that we shared. Inadvertently that created more people who do the same but might never have the issue in the first place.

When someone tries to repeat that from an IDE/LSP perspective, it obviously feels slow, akin to speaking a new language for the first time. Does one need this language? It’s hard to tell.

Problems show different contrast to people with different backgrounds. My personal position here is that if you shouldn’t solve non-problems. The set of problems you decide for yourself based on your experience.

I’m a balanced guy, btw. Sometimes I just sit and try to force upgrade my dev env. What sticks sticks. What doesn’t, goes to hell. I’m using ALE (nice multi-LSP tool) and all the tools I know since ancient times. Copilot writes what I call boilerplate, and I neither trust it nor have the need to write it. Passing my real-business functions to LLMs usually produces unfixable mess, so if someone knows another way for it to be useful, I’m all ears.

I use Emacs and sometimes I open a window to bring up a man page or code definition for some function, but I've never felt the need for a fancy IDE. You just get used to what is going on in the code. Like if you are a fiction writer and you're asked to write a new Star Trek episode, after watching a few existing episodes you would get familiar enough with the characters and milieu to not need to refer to the series bible too much. An IDE that pops up suggestions like "Live long and prosper" or "we have 93.2357% chance of blowing up the ship, Captain" when you type the name "Spock" sounds counterproductive. Maybe I'm missing something though.

Added: it helps a lot to have real documentation, something that has gone out of fashion in recent years. Maybe these IDE's are being used as a substitute. I hadn't thought of it that way before. Hmm.

Added 2: Also, Emacs has always had TAGS (this quick navigates the editor to a function's definition given its name) and I do use that sometimes.

For years now Emacs had integration with LSP. The experience isn't quite the same as VSCode (I think, there are some proprietary extensions to LSP protocol, or some such, but don't quote me on this). But it's good enough to work in most cases (this is how I write in Ada and Rust, for instance). So, if you use Emacs: https://github.com/joaotavora/eglot I believe this is the most popular implementation.

This thread is certainly eye opening. It reminds me of a post I saw somewhere, maybe on Reddit, where someone was describing their experience working as an intern at an old-school tech shop. All of the developers there were hardcore Vim/Emacs users with 20+ years of experience.

The intern was tasked with a large-scale refactoring of some modules which the senior devs estimated would take months of work to complete. After shadowing a senior dev to get an idea of the work involved, they realized the dev was literally string replacing a lot of the code, hence why the estimate was ridiculously long. The intern instead loaded the project into IntelliJ and used the built-in refactoring tools to get the task done in a couple days. This caused a bit of an internal shit-storm with the product owners because the intern made the devs "look bad".

Turns out those devs were indeed hardcore, just not in a great sense.

The intern didn't make them "look bad". They were bad. I mean, I'm sure that they were great developers in some sense, but refusing to ever update your toolkit because you've always gotten along just fine with what you already use is a great way to get sped past by the next generation who start from a better baseline.

Yea, that's the exact point I'm trying to make. And I'm getting very similar vibes in this post with folks refusing to use LSP.

As someone who used InteliJ before working in Emacs full time (20+ years of experience), these are just bad developers.

btw, LSP is not the only way to make go to definition work.

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!

Maybe it's my ADHD, but I cannot for the life of me stand using an IDE. There's too many distractions - popups, suggestions, underlines, warnings, and a million different buttons cluttering up your screen. That along with an AI assistant would make my head explode.

All these things that supposedly "help" us code end up limiting us in severe ways because we aren't forced to think anymore. Typing, syntax checking, and recalling function definitions isn't the bottleneck to programming. If they are, maybe you're not programming.

I have to use VS for work and Intellisense can be so annoying. Too slow (I've already completed the word), or unhelpful. Example: Accessing elements in a 3d vector, having already typed "var." it pops up with the options, x, y, or z, every time. It's not saving me any keypresses, especially after I've already accessed some elements so I know the members of the struct. Also, how about matching to variables or types from the local scope outwards rather than offer something in a system header not present in any preceding code.

So I have it disabled and just search for things (another thing VS can go complete blank on), keeping the relevant file open in another window for reference, which means I also get to read all the comments in the code before using it.

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

Code search (ripgrep, GitHub search, Sourcegraph, git grep, or even just plain grep). You can use VS Code search but I prefer CLI tools so I can filter the output of my search with more searches—VS Code makes it hard to post-process/filter project-wide search results.

Filename search (fzf, fd, or just find).

There are cases where LSP-powered Go to Def is faster, but there are also cases where it’s less accurate. I’m talking:

- Untyped code in a graduate typed language

- References of a method name in a YAML file pulled out with reflection

- References of that method in a comment of some other method, where that method is actually the method I’m looking for.

- A one-to-one mapping of method names with some enum somewhere else, but lowercase in one spot, and all caps in the other spot.

So yes, sometimes go to def will be faster, but you’ll lose out on so many other possible references.

Another case: repos where the codebase is so large that the editor tooling is slow. Repos where I’m brand new to it, because I just need to check why some code in a third-party library is going haywire.

Grep (code search) is just so powerful.

I have a post about how to do large-scale code migrations/codemods. Everyone assumes the post is going to be about how to use high-powered, language-aware AST-based static analysis tooling. But half the post is talking about the unreasonable effectiveness of regular expressions.

I feel heavily annoyed from most IDE features. I love to code in a chill relaxed way where I just write the code that I want.

I actually remember all the relevant fields and I am currently working on, or just reread the relevant code when necessary.

I wonder if syntax and cute grammar has any relevance in a world where people basically let the IDE to the coding.

I honestly wouldn't call me a good coder if I wasn't confident I could produce the same code quality on a computer with just nano or vim and no internet.

I load the Lisp code of a project into the Lisp environment, which is the program and the development environment in one thing. Then all the information about the project is available in the running IDE/program combination. The thing then is fully reflective and introspective.

An example is GNU Emacs itself. For Emacs Lisp it is both the IDE and the application environment.

Similar integrated systems existed already earlier for Lisp and Smalltalk. Interlisp, the MIT Lisp Machine, Smalltalk 80 and others were examples where the IDE and the code was integrated.

OTOH, the combination of GNU Emacs and external Lisps, like Common Lisp systems, was basically LSP before LSP existed. There were tools like ILISP, which connected GNU Emacs to various external Lisp runtimes (which have all the development information about the loaded code). SLIME replaced it at some point in time and usually connected to external Lisps via network connections.

I have a hobby project that turned into a fairly successful commercial project. I hardly use any IDE features. Sometimes, I write a new utility function like "get_abc_from_xyz_index" only to discover I already wrote it a year ago in the file I chose to put it in. So not only is the project well organized, but it's all me so I'm very familiar with it. Lots of tests. I also type extremely fast so unless autocomplete is perfectly tuned, it can just be annoying handling various languages and maybe on different machines. HTML tag closing is a good example of an annoyance.

Since I've been doing this for years, it bleeds into my work too, where compared to my peers I tend to use fewer dependencies and IDE features.

Ah, yes, autocomplete: the propagator of typos. Write it wrong once, have it copied wrong everywhere.

Go-to-definition: the band-aid for overengineering. Write 37 levels of indirection, don't pay the price.

AI programming: now you don't even have to pretend you understand the code! Bonus point: sometimes it generates from StackOverflow, but from the question, not the answer.

These are good tools, but it's easy to figure out who uses them to help themselves, and who couldn't write code at all if it wasn't for these tools.

Related to workflows: vim, tmux, grep -r for finding stuff in somewhat sane codebases, watch to have unit tests running, minor scripts for everything else.

My personal observation, even if this is similar to what others already said: I found that in some (two? three?) big Java-based projects I worked on, where almost everyone used a IDE, the codebase became almost impossible to navigate or modify without using one, so I did. It was so easy to just add a method or class wherever, and it did not matter because you could just ctrl-click a name to find its implementation. It did not matter if you put 100+ methods in the same class or if you named things willy-nilly or overloaded method names.

If I was back working on a project like that, I would use whatever IDE everyone else was using. It makes no sense to fight it. But I prefer projects to not be designed for/by IDE, since that tends to make everything more readable and easy to navigate. I prefer to be able to navigate around the source-code on the command-line or use whatever generic tools to browse, and not be forced to ctrl-click my way around, and if (almost) everyone else working on the code wants that as well it is less likely that someone ruins it.

That said, I have at times also set up Emacs to use LSP or other built-in code-navigation tools, or templates (yasnippets) for generating boilerplate, for some projects. I rarely end up using it much. Usually I just jump around using built-in tools like M-x vc-git-grep or M-x rgrep. The code has to be pretty heavily designed-for-IDE to make those simple tools slow to use.

I've recently experienced a sharp decline in my ability to remember anything code-related. At one point I looked at the code I wrote the day before and it felt as if I don't even know the language it's written in. I was attributing it to the age, but this thread made me realize it coincided precicely with the switch to using IDEs after 15 years of getting by with a text editor.

I visit HN every so often but never felt the need to comment, until just a few minutes ago.

Yes, what you've described, I also went through something similar.

I've been programming little over two decades now. Been an autocomplete (ctags, intellisense, lsp) user throughout my career. Never had any real problems with them; they were convenient tools, nothing that different from someone using grep/fd etc.

The codebase I (used to) work on is a 30m+ line behemoth, and API frequently changes underneath me; an LSP is crucial to get the work done. How could anybody keep two dozen+ minor-naming and subtle-semantic variations of the same method in their head? I'll say yes to auto-complete any day of the week, I thought.

About two years ago, I've noticed some worrying cognitive signs. Out of the blue I realized I could not remember the name of methods, classes, interfaces, even the ones that I use daily. I could code, there wasn't any problem with that. But I could not write anything down without auto-complete. I couldn't even fill the arguments of a function without the LSP holding my hand throughout the ordeal.

With the realization that both my grandmothers went through dementia/alzheimer's, I truly felt like walls were closing in on me, in real time. Of course, I went for a check up, which came out clean, but I could not shake that feeling of impending doom.

By luck ---and some hefty dose of depression due to unrelated personal reasons--- I started writing a toy compiler in C, something that I had no experience with whatsoever. With just a text editor, because I dreaded having to install visual studio on a two decade old computer (which was the best I had under the circumstances). Despite forcing myself to fumble through, a few days later I noticed that the entire code base was in my head. I knew precisely what I wrote, how I wrote it.

Life went on and I went back to work. And only then I noticed. I was waiting for the LSP to catch up and fill the correct type, my mind went back to my crappy lexer. Programmer? No, I felt like a factory worker on an assembly line.

A month after that I finally gave my resignation, then started a new (self-employed) programming job. For the past year I've been working on a game + an engine, without intellisense or LSP. In fact, I even disabled syntax highlighting a few weeks in, and never turned it back on. I've ditched quite a few of my regular tools, opting for simpler (often homemade) alternatives; simple bash script instead of cmake for example.

Suffice it to say, I've come to some personal conclusions. These conclusions stem from my personal bias, true, but I do feel strongly, that they apply widely to the field as a whole.

In short:

1) LSP, intellisense, code completion, are overall harmful.

2) Syntax highlighting does not work (most of the time), it just satisfies the part of our brains that like to recognize patterns.

3) Complex and highly integrated tools are a net negative unless they are purpose built.

Most people will vehemently disagree with all of the above. That is fine; I'm not on a crusade against the machine, so to speak. I just wanted to share my view since I resonated with the post I'm responding to. But I will still briefly explain what I mean, in case if anyone's curious. (In part 2, because comment was too long)

Part2:

1) LSPs. They are probably most productive tool in a programmers belt. Even now, if I had to work on a giant amorphous code base that changes on the whim of hundreds of individual maintainers, I would use an LSP. That said, in my opinion, they prevent you from forming and conveying your actual thoughts.

Using an LSP is like having your sentence be completed by someone else. It's like riding a scooter everywhere. It's like talking to people that you always agree with. Fine, in isolation, but forms habits of dubious benefit at best, or downright harmful at worst. Our brains are just like any other part of our bodies; if you don't use it, you'll lose it.

Completing a function name? Sure, it makes you faster. That is what you wanted in the first place. Pressing 3 keys at most then hitting tab, how could that be harmful over typing the full name with over 16 characters? Unfortunately, brains excel at optimizing, and when done enough, your brain too, will happily optimize the name of the function away.

Smartly completing a function's parameters? Sure, invaluable honestly, without sarcasm. Being aware of types? Even better. Over time though, the brain will strip away the unneeded.

Naturally, this convenience doesn't make you unable to code. The necessary information is still in your brain, just at a higher level. You may not know exactly what gets returned from somewhere, but you can change a few <>'s add a few 's, perhaps shuffle the name a little bit and still get the correct type, because LSP will color it correctly when it is correct. Did you name the thing nioseLevel or levelNoise() or getNoies().Single(perlin-2d)? The idea is the same, does how you get there matter?

In my highly personal opinion, typing every syllable every letter, thinking about the correct types before writing, knowing where a structure is, knowing how functions interact and so on, is the primary way that our brains interact with the code itself. Quite literally it is the exercise that your brain needs to stay fit. This interaction creates a mental map initially, and eventually leads to mastery by being able to hold everything in your head.

Reading code is different. It is a passive action. We get ideas through observation, but learn by doing. Typing, thinking, then writing is the doing verb in programming. Reading is the observation, the reflection after the fact.

An LSP strips away the necessary weights, if you will. If you ride a scooter everywhere all the time, no one will gasp when your muscles atrophy. LSP is similar, but compounding. With the rise of LSPs, so came the rise of complexity, often in form of bad architecture. My personal (and I will immediately concede that it may truly be a personal physiological problem) is the rise of complexity in often what should be pedestrian code. Reminds me of the worst times I've had with java; because everyone has LSP's (right?), who cares if you need to follow 5 files just to correctly create a mental model of that type? But hey, at least it's not oop (because it doesn't have the keyword 'class' in it).

The more I type the more I realize how hard it is to concisely explain what I mean. If I were to use an analogy, using an LSP would be like talking to your best friend where you complete each other's sentences. Yes, both of you know what the other thinks. When you see the news on X, Bluesky, or even TV, all you need is to look at each other and shake your heads. There's no need for words, one glance is enough. If your only political discourse is two best friends agreeing with each other, if you've never exposed yourself to opposing views, you have essentially never articulated your thoughts. Your ideas remained as a bowl of feelings, not logic. So, when someone with an opposite view and a glib tongue tries to debate, they will verbally run circles around you. And you will get angry. But the only way to get better at debating, is to debate. Watching debates won't give you the expertise. Your friend can't hold cue cards as you talk to strangers (or at least they shouldn't). You do not get better at eloquent speaking without speaking. You do not get better at eloquent writing without writing.

To me, LSP was like that. I vaguely had a feeling, and I let everything else go --- even the syntax --- to achieve it. Once collectively done, the result was a 30m+ loc mess of a side project; yes, not even the main one. After years of that, I came to realize I wasn't programming as I defined what programming was to myself.

In a more broader sense, LSP enables complexity. Programming is an endeavor where complexity occurs naturally, and simplicity has to be fought over. This creates a vicious cycle where you need an LSP to combat the complexity, which itself leads to complexity, and in turn leads to more LSP usage. Our field makes this is even more noticeable since programming itself is in a state of permanent newcomers influx; the demand for programmers goes higher every year, yet we are persistently and woefully unprepared for properly educating these programmers, because we can't even agree on what "correct" software development looks like. In this sense, the "harm" is more institutional, rather than intrinsic.

I would not advocate or even advise others to stop using LSPs, mind you. But I do think it is overall harmful at a personal level, and at an institutional level. Not that it would stop any billion dollar companies of course.

2) Syntax highlighting. Throughout the years, I have seen exactly one example where syntax highlighting could (could) have actually prevent a (singular) error, and that was with C #endif's. Leaving aside the extremely self-evident nature of the C macros, the code itself had mixed quite a few #endif's and the author could not be bothered with adding a comment, because (I'm paraphrasing) "his LSP darkened the #ifdef's correctly." Mine did too, but that's beside the point.

Disabling syntax highlighting was unexpectedly difficult, far more so than leaving LSP at the door. At first I couldn't read anything. The code simply didn't look appealing enough. Everything about it was off. I just shrugged and continued my little experiment. Eventually, I realized lack of coloring and hinting made me focus more on the code itself. The pretty patterns while great to look at, I think they do lead me to discard sections of code at a personal level. I would never say turning syntax coloring is better, just that it doesn't have any benefit that I could substantially measure. Though to be clear, turning them off really did gave me some satisfaction, most certainly borne from the mindset of making a change, rather than change itself being positive.

Whenever I look at something on github, my pattern matching brain immediately shoves a dopamine hit down my throat, so yes, I still think syntax highlighting is prettier. Though at the same time, I still get the feeling that I pay more attention to the cold and colorless columns of my editor.

3) Over time I have developed a certain distaste towards certain applications. And over time, that distaste have evolved into a preoccupying hatred. So I will refrain from saying too much about "complex and highly integrated tools." I've come to think some of the reason why these tools exist in the first place is the commoditization of programmers. Nowadays I prefer far simpler tools, at least conceptually speaking. I did pick up emacs after I quit my previous job, so there's a hefty bit of subjectivity in my assessment. That said, I would choose notepad (literally notepad) over visual studio at this point. Bash over bazel; a gun over typescript. And so on.

Wrapping up:

Am I a better programmer than I was a little over a year ago? Without a doubt yes, I have improved substantially. Though the improvement isn't what you would think. I'm not "seeing the matrix" so to speak, as a young me would've embarrassingly put it. At first I ended up regressing and kept refactoring my tiny codebase; it was a slog. Over time I found what worked for me, and become able to hold almost the entire codebase in my head. No, I did not gain inhuman memory simply because I stopped using an LSP, I just became more aware of the code structure, and gained the ability to reason about the entire codebase more clearly and precisely. If I were to present two code samples, one from two years ago and one from today, perhaps even I wouldn't be able to say which is better at a micro level. The real difference is that after numerous refactors, the 200k+ loc codebase I have now feels like a 2k project from my college days; easy to modify, easy to keep it all in my head. Thinking back at my career, most of the codebases I worked on could've achieved that too, but chose not to. The overarching reason is --- in my opinion --- the commoditization of programmers, which causes institutional loss of knowledge. LSP isn't the cause of that obviously, though it does worsen it.

Appreciate the thoughts on this. I've been very conflicted about this topic lately. I'm an old Vim programmer, but I've leapt into AI-assistance earnestly. First it was out of curiosity and some amazement at how well they worked. Then, especially with Cursor, it was like, "Holy shit I'm flying through this stuff, basically hitting just tab. It's reading my mind."

But do I feel something weakening in me? Yeah. I don't have nearly the intimate mental model of where things are in code and how it ties together. It's like my brain is optimizing for the next thing that will prompt a useful tab completion, as opposed to tracking the whole. I don't like the feeling, but the actual output doesn't lie. When I switch to a new file and Cursor dumps in a 30 line function, without asking, that is correct based on what I was working as 5 second before, that's almost unquestionably faster. But at what cost...

I'm trying to find the sweet spot in all of this. There are some areas, like writing volumes of HTML/CSS/Tailwind, that I'll happily hand over to an LLM b/c I'm not great at it, I don't care to be, and it is a time compression of probably 50:1. OTOH, I'm thinking about dialing it back a bit on my backend and SQL code, which is a bit nearer and dearer. Simple autocomplete to save some typing is fine, but maybe lighten up on "Is this (20 lines) what you want? No? How about this? Or this? ..." tab-completion mania. I'd like to still be able to land the plane w/o autopilot.

I use auto-indent and syntax highlighting which is sort of an IDE feature, and some other quality of life things like triming trailing whitespace on lines I edit. I also trigger compilation from the editor so I can step through the compilation errors one by one.

I know my editor (emacs) could do some of the more advanced things you mention, but it needs a bit of setup and I'm lazy. It's not really a blocker.

I look at the docs if I'm doing something new to me or have forgotten a function call. I google more complex things which often gets me more useful info than an IDE could give me, unless it's drowned by AI-slop.

If I want to dig around in a codebase I can grep for things, or just open a likely looking file and isearch for the thing.

I do git etc from the commandline, which I could probably do from emacs too but I never really bothered to.

I have nothing against IDEs and have used some at places where it was harder not to because they'd standardised on a common one. I kinda enjoy the simplicity of just having a familiar editor for any language I encounter though.

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 :).

I don't use most of these features other than go to definition. I find popups deeply annoying. I've tried using other features such as autocomplete but I've never found it very useful. I think it's due to the type of work I do. I rarely write lots of new code and instead spend most of my time debugging existing code and making relatively small changes. Go to definition seems to be the only navigation feature I find useful. However, I use a debugger almost continuously to monitor the state of running code and I have a similar question as you for all the developers that never use a debugger - that seems weird to me now.

Here's my experience so far. 1) The best analogy for LSP is GPS navigator in your car. It's invaluable when you have to navigate to unknown places to do stuff but, it also slows down your ability to learn the roads of your closer neighbourhoods. I am often surprised how confused I am if my GPS sends me down a road that is closed for whatever reason and I have no idea how to figure out an alternative route even if I am driving around my place, it shows me how much I rely on the navigator to get me anywhere now.

So what using an LSP is doing for you heavily depends on the kind of code you write. Are you the kind of dev who works in pretty much a very familiar codebase for a very very long time? Then LSP could even be impeding acquiring a better mental image of your code. Conversely, if you are a coder who often ventures into different and unknown parts then LSP might make you way more productive.

2) Depending on the language, LSP can become an actual part of the language itself. When I code in languages with good LSP (C#, Rust but also C++) I often code with the LSP as my "target".. I think what I'd like to see popping up when I type a "." . In this part of the code I want to see this var and this method.. in that part of the code I want to see also this other vars and methods it gives a very good idea of what the "surface area" of a piece of code looks like.

LSP are also very good instant feedback if something you are typing is wrong. I press "." and nothing shows up? I have some error somewhere and/or the thing I am dotting is not what I think it is.

But, in order for this to work the LSP has to be REALLY good to the point that has to be close to zero doubt that if the LSP is not behaving it means it's your fault. Sadly, not many LSP ever reach this level of reliability.

This is one of the thing that made languages such as C# and Java so popular: the ability to "dot" your way through unfamiliar libraries with great ease without having to dive into documentation to discover there's a function X in some file Y that already does exactly what you are trying to do.

Newer fancy things like code completion are a little faster, but the thing I care about most in my IDE is if I can command+click for type definitions.

For example, writing Python scripts for Fusion 360 modeling is almost impossible if you aren't able to find all the methods and type definitions as Autodesk's documentation is pretty terrible and doesn't list most methods.

If your IDE doesn't have type definition support, being productive with certain APIs with terrible documentation is impossible.

If it's all vanilla code, then this isn't as much of a problem. So the need for better IDEs comes with more complex code.

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.

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.

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.

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.

For most of my projects, the key value I can add is in understanding business needs, translating them to technical requirements, and ensuring sensible choices of data structures, APIs, libraries, etc. Rarely is code generation the rate limiting step.

I do find autocomplete and language servers useful for avoiding typos, but typically there is already some form of compilation, type checking, or linting to ensure valid code.

I think purism is a slippery slope for experienced people, I too suffer from this to a certaint extent. It's natural to fight change as you get older and it's part of the struggle to change your behavior and adapt to the changing times.

Short comment regarding syntax highlighting, unless you have some impairement, I think everyone benefits from this. It's something that helps you recognize patterns much faster and you can skim through the code way faster than without.

I don't benefit from syntax highlighting and don't see how anyone does. It's pretty, but doesn't convey useful information that isn't already right there in the syntax itself.

Keywords vs. variables vs. functions <-- these all look the same.

It's not just purism. IDEs tend to have workflow problems that distract from focusing on the code. I'm increasingly using Codium (open source VScode) but there are many papercuts that prevent vim-like workflow that integrates well with shell and the filesystem. Also vim's "dumb" autocomplete goes quite far, especially when used with the well thought out split-panel implementation.

IDEs tend implement features quite ad-hoc without thinking how they compose which limits the workflow to certain style that's not always very ideal.

So back in the day before LSPs:

Typically I'd leverage 2 large monitors and keep at least 3 editor "views" into code open at once: one for what I was actively working on and 2 others that would contain reference code. You also take considerable care as to how you organize the code, so that grepping for definitions is easy. If I needed to see how a particular object or function worked, I'd pull it up in one of the auxiliary code windows - which would typically start with a grep alias command that would have a shortcut to open it in a designated emacs buffer window. Not anywhere near as convenient as an LSP but it got the job done.

> What do you do if you need to look up the definition/implementation

I have these features on (more or less) and I still use grep, ag (the silver searcher), and GitHub search. I often need to look for things my editor can’t possibly figure out. I’ve never found editors to be great at this. Then again, I probably haven’t optimized for it. I’ll admit that might be a mistake. Old habits die hard sometimes.

BTW, I’m usually looking for other people’s work or code I wrote long ago. Functions written somewhere in a vast code base that I don’t have completely checked out (because I’ve never coded on parts of it). I don’t think much about the obvious stuff, like a function in the standard library.

Before mobile phones where a thing, we used to memorize the phone numbers of every family member and friend and co-worker, etc. The numbers we rarely used, we wrote down or looked up in the phone book. When you got a new number, you maybe wrote it down, then after having dialed it a couple of times, it stuck. This didn't really require any effort, it was just the natural way of doing things.

Then came the mobile phone with the ability to store contacts, today I can't even remember my wife's number.

I have coded for more than 40 years and I hate autocomplete, language servers, etc. I don't use any of it because I have found (after having tried to use it all) that, just like with phone numbers, you don't remember much if you use all of that and you have to make a real effort, but things just don't stick the same way. But if don't use any of that, you only have to look things up in the beginning, then occasionally, then rarely or never again and more things just stick, you get faster in a natural way and you understand your code better. You also think deeper about how to structure your code and how to organize everything.

If you always use a crutch to help you walk, you will never walk by yourself. The crutch will look like it is helping you, but that's only in the beginning, eventually it will hinder you and hold you back.

That's my 2 cents.

As many others I do use fd/rg/ctags, custom scripts, some even Perl ones; Today I’m on Kakoune but had plenty of Emacs integrations when it was my daily driver (Kakoune taught me to pipe selection through a script that echoes code fragment which works in most editors, e.g.: `|gosnip_if_err_panic.pl` with `responseErr` selected).

I think that the reasons I’m not using IDEs/LSP are more worthy sharing:

First one is that I cannot use one. While the main language I’m using has relatively ok LSP, the codebase prevents usage - as it’s ridden with circular dependencies, macros, module aliasing and multi dispatch cast chains. Everything outside of syntax highlight it unusable.

Second: I noticed that assisted coding is like GPS assisted driving. I stopped internally understanding architecture of the code when using IDEs, this disconnected my mind from the code and at some point it started to feel like shoveling. Mindlessly spit out the code at let IDE handle the rest. That made me efficient at local change but unable to build up and see „big picture”. It bothered me to the point I decided to not use them anymore.

The third thing is that I don’t take „no” (coming from software) for an answer. I often get those specific needs for code search/refactorings that IDEs/LSPs refuse to work with. E.g. I need to search customized OpenAPI specifications and link it to a macros/generated code for browsing. IDEs/LSPs cannot help as it’s not idiomatic, so I customize. And customization is a loop. You customize, you learn how to customize better, you customize more etc.

When it comes to LLM-based aids I’m at point of minimum trust. I’ve experienced so many problems with that code that I rather just disable it entirely. Example? I was setting up Ticker based waiters for Go and then in one place I accepted `time.NewTimer` local-LLM snippet instead of `time.NewTicker` in infinite loop. It was 4 lines of code and looked VERY similar as in 3 functions above (that was before code reduction phase). For those unfamiliar: Go’s ticker ticks every N time. Timer fires once. One-shot-fire in infinite loop == lock. Took 4 hours to debug.

I’m not against using LSP/IDEs. They have their use (but for Pete’s sake ask your organization leaders before feeding proprietary code into ChatGPT). They don’t work for me, I feel dumber. Maybe I’d be more efficient but I don’t care. I do this job also for fun, and GPS kills the fun part for me.

I think lumping in LSPs to Copilot is wrong.

The LSP is a (mostly) deterministic system that surfaces information provided by the language or by other programmers (types, comments, etc) which are meant to save you time and reduce the cost of context switching.

The other is a completely non deterministic system which generates code from thin air.

That would be like comparing GPS to a self driving car. Both are certainly helpful aids but using one is not like using the other.

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.

I feel that's a big issue with learning a language in an IDE.

I've written a ton of C# and I don't remember shit about methods in the standard library, because it's all there, and getting worse with AI. Not to mention the detrimental effect that the constant interruptions must have.

I use IntelliJ for Java, but since I learned the language and standard library long before fancy IDEs were a thing I barely notice the blinkenlights.

Autocomplete in code is the single most annoying thing I've ever experienced. While I do have a fantastic memory, I don't feel like it makes a huge difference? I don't quite understand the workflow using autocomplete, I suppose. If I'm typing something I know what I'm trying to achieve (with or without a more concrete implementation plan), the general context of the code I'm working with, and it is quicker and far more enjoyable for me to just type instead of dealing with a minefield of never ending pop ups from autocomplete. I know the types/fields/classes/language features/whatever because I have to in order to do whatever I'm doing. I reference the relevant code, open in other tabs in my editor. I also reference documentation. I don't really find myself wanting for more. I don't understand how using auto completion would impact needing to know that stuff anyway? I get that it's annoying and maybe less efficient to have to type out all the params and types and other predictable stuff by hand but you have to know it to make sure the option you've chosen from the potential many options suggested is correct anyway, right? It feels like less mental and physical effort to me to just type exactly what I mean instead of having to review options and double check I've chosen the right one, but I can kinda understand why that's a minority opinion. I still fuck it up or end up changing my implementation and having to revise it anyway but I definitely prefer to type.

Before I figured out how to configure Sublime Text (I used Atom until it was killed) to have JUST go-to-definition and no other LSP features enabled, I'd just do a quick couple of searches across a code base or file. It was fine tbh. Yes, a single key press is much nicer but it really wasn't that annoying to not have it. I got just go-to-definition working and was able to turn literally everything else off and I'm really happy with it.

For context, I've worked in all kinds of code bases with all kinds of quality and organisation (including lack thereof) in a variety of languages and frameworks, and I've not really felt the NEED to change. I do try VSCode and/or using more of these typical IDE features maybe once a year in an attempt to leverage these features that seemingly every other programmer feels they gain a lot from but I just HATE it. I can't stand it. I really have tried! I do assume I'm leaving some quality of life and productivity gains on the table but I've never been able to make it work for me.

> While I do have a fantastic memory, I don't feel like it makes a huge difference?

I'd say it does. Particulary for names based on English words with synonyms, if I recall the wrong synonym for this particular library, at least autocomplete is faster than searching the docs for all the synonyms. But not as fast as scanning the method/function list should the docs have that (and far too many miss it out).

If you can remember which word for the concept the method you're after uses, then you don't need autocomplete.

BTW only Jetbrains (and other heavy Java IDEs?) get autocomplete right IMO. The basic form in VSCode doesn't cut it in my experience, and gets in the way.

Good insight! I probably take my memory for granted. With your synonym point I can definitely see the friction that could cause.

You're spot on with jetbrains etc.. I have also tried it and a few other highly specific and focused best-possible-experience full IDEs along the way. Early in learning a stack I felt needlessly burdened by the nuances between autocomplete options (which put me at risk of ending up stuck in an documentation hole happily reading about shit I didn't need to for hours) and once more confident I just went back to regular annoyance. In some code bases I'd probably have used it more, as the suggestions were so much more refined and useful. You're totally right in that it's a whole different league from VSCode.

I forgot to mention that I also have linting issues and other gutter icon things completely turned off as well. I have a code formatter installed ...I think? Those are things that I could probably turn on without wanting to pull my hair out but again I've not felt the need. Typing my imports manually is mildly annoying in a small handful of areas but not enough to make me do something smarter about it lol

I use vim, and program mostly in Python, Rust, TypeScript, JavaScript, C, and Bash. There are about a dozen other languages I use on occasion.

My vim configuration is moderately customized, and I regularly write code on systems I SSH into since my personal laptop is a Pixelbook.

The main things I rely on are syntax checking plugins.

I use ripgrep to find stuff in codebases, and when I'm working seriously I use an ultrawide monitor with plenty of screen space to have documentation I can glance at open.

I have a significant collection of small libraries I've written for common tasks, and often refer back to my own code across projects to figure out how to do things. Metaprogramming is something I do often too.

As another person said, thinking is my main constraint when working, not actually writing the code.

It should also be noted that I'm not primarily a "Software Engineer". I'm a Principal Security Engineer at a big tech company. If I'm working on actual code, it's generally "interesting", either a hard problem at work, or a personal side project. There tends not to be much boilerplate.

For TypeScript/JavaScript in particular, something like copilot would get in my way, as my style for this languages is extremely non-standard.

I'm not sure how much any of my coding habits have to do with it, but I regularly tear into unfamiliar codebases to fix bugs and add features, and I'm pretty good at orienting myself quickly, even in languages I haven't used before.

The first thing I did with Rust was add features to a data compression library without any prior exposure to the language...

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.

In Vim, the "stupid" auto complete will get 80% of the way there and works without setting up a language server and it works for any language.

By default it will give all the identifiers in all open files. Having a few of the relevant files open in the editor will get you pretty far.

I do use LSP in other environments where it is available but I still do a lot of my work with just plain vim because I jump between code bases a lot and setting up LSP for C/C++ needs some extra steps to work.

In my experience, code navigation features are necessary for writing code comfortably. If you mean only auto-complete by LSP, then yes, it saves you some typing or function lookup, but that’s not the main benefit for me.

Years ago, I worked for a long time using Smalltalk (VisualAge Smalltalk, to be more specific). Older Smalltalk versions didn’t have autocomplete. But it wasn’t a problem because Smalltalk has excellent code navigation features: find implementations of a message, find callers, and evaluate code inline. With those features and some code conventions, I never felt the need for autocomplete.

Perhaps it’s my Smalltalk legacy, but nowadays, I use the most Cmd/Ctrl-Click to navigate to the implementation, read the sources, and use the “find references” feature. I don’t know if the LSP implements those features, but reading the sources gives me much more information.

Before programming in Smalltalk, I did some C++ and Java programming. While all Java IDEs had autocomplete, C++ autocomplete was unreliable on most tools I used. The solution is to read the docs and the source using search tools across the code base and third-party sources.

I want to be able to reason about my code without sitting in front of it, so I simply don't use those tools and this understanding of the codebase builds over time.

When you're working in one area of it, you read it and make additions in it repeatedly, and eventually your familiarity increases until you have mastery.

Then you can code anywhere, anytime, and merely type it in when you get back to the keyboard.

It's like learning a (human) language. As an analogy: "[foreign language] speakers who don't use a dictionary, how do you do it?" But the foreign language is your codebase. Learn it.

> So to the devs who don't use these tools, how do you do it?

This is the kind of question where you can easily go get a much better and more comprehensive answer on your own by experiencing it yourself.

I did for a very long time. I only used vanilla vim, a terminal, a couple of core utils, and documentation.

You just learn to memorize a lot, organize and design your code. It feels very similar to learning to navigate a city without map. The map will be in your head. A very similar feeling I had with code bases. I navigated a map, sometimes I knew the route towards a piece of information, sometimes I knew exactly where it was. Sometimes you add a building or a new road, but you all keep it in your head.

Nowadays I use LSP, autocomplete LLM's and what not. Makes things easier and above all faster.

I still can do without, I am just a bit slower. For small changes and simple scripts I fallback to vim. For git I still use the terminal. And I still use a lot of commandline utilities, because each IDE has a zillion of commands that do the same anyway.

For your example, nowadays I would use grep or some modern equivalent to search for definitions. And to be honest, that isn't that much slower. I can have my editor open in tmux tab and in the other my editor. You don't have to jump through files then.

I did a lot of work in unassisted vim when I was in university, and I would say the answer is twofold:

- you become a proficient user of tabs in whatever IDE or text editor or window manager you use. you open up header files (or collapsed source files, depending on the language/IDE) and reference the API you use.

- you get better at naming things. You don't need to guess the name of any specific API, because it makes sense within the context of your codebase. I believe this makes you a better programmer.

I'm a Rails programmer and recently the Ruby language plugin for VSCode I was using was deprecated so I switched to Shopify's ruby-lsp. On the one hand, it's much much more capable than the old plugin: better syntax highlighting, actually useful inline definitions, style hints, etc. On the other hand, it's also way more annoying: there's a bug that sometimes breaks my projects' dependencies so I have to reinstall them, the code completion actually slows me down more than it helps, and if the LSP can't start for some reason (which happens quite often) I get a stack of error popups in the corner of my screen.

On the whole I think I prefer my old setup. All I really need out of my IDE is decent syntax highlighting. I've got devdocs.io for Ruby and most Rails definitions and I know how to spelunk through the Rails codebase for anything that misses. Go-to-definition is handy for my own code but I generally know where it lives, and if I've forgotten there's always ctrl-shift-f or `method(:blah).source_location`.

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.

In the past I have been training in a coding "bootcamp" for a while. I insisted that people new to coding use a plain text editor, like Notepad on Windows, no syntax highlighting, no autocomplete, nothing, and a command line to lint and compile the code. I only introduced the IDEs much much later, closer to the end of the bootcamp. First, I confirm that it is perfectly possible to complete rather complex projects this way. Secondly, I have no ground truth to compare my results with, but I know that most of the students appreciated the fact that they do not depend on the IDE/LSP/Copilot that much and developed their own understanding of how the things work.

I don't advocate to do the same outside of the learning process, of course. The tools help a lot (in fact, LSPs are awesome), but there are two principles that are important here I think:

- having an understanding of the underlying code, language, etc.

- being intentional about the use of the tools (e.g., invoking auto-complete with a keystroke vs an endless suggestions list; running a linter explicitly vs a code bloated with "insights" and "warning highlights", etc.)

i remember when i start coding first time (with note pad), first couple of month i keep pocket book close, then i download the manual (it was 56K times) and it was open all the time. back then memorizing functions from stdlib was a normal thing, but there is a saying, always check man page after you write the code.

first time i use an editor which have auto completion but it works only for same file, it was time saving thing.

then i see real auto completion feature, full function name, parameters, returns and couple of words from manual, it was mind blowing for me.

then i start using eclipse, with one click whole class generation from interfaces etc. one of my friend create its own snippets and it was writing like 3 person, couple of keyword strikes and bamm, whole thing is ready.

then internet become something like air instead of water, constant flow of information, constant needs.

In my experience, autocomplete/intellisense/LSP/etc is very difficult to get working on most codebases if you aren't already intimately familiar with how that codebase / language / framework / etc works, or someone with that familiarity has laid out exact steps for your IDE.

When I see someone using these features as part of their workflow, I semi-confidently predict that they spend the majority of their time working on a single codebase, such that the time investment to get everything working was worthwhile.

If, like me, you work on multiple different codebases most weeks, it rarely makes sense to even try setting those things up.

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.

Good code should be designed such that it's easy to find where things are to begin with.

If you need an IDE, that just means your code is a mess.

Ironically, the more messy the code is, and so the more you need the IDE, the more likely it is that the IDE will have trouble coping with the code, becoming extremely slow, or randomly failing to jump into some functions.

Ensuring your codebase remains workable without an IDE is actually a good litmus test for quality.

I reason the same way with explicit typing.

I like syntax highlighting and basic automatic indenting, but not much beyond that. I can't stand autocomplete if there's an automatic popup. I tried some LSP stuff and it was quite nice but I couldn't turn off some features in my editor and they distracted me. The thing I really can't stand is automatic closing of parentheses!

Been using Debian and vim for almost 25 years now. Tried many IDE's but they're distracting, bloated and slow.

My main language is python and for that I use jedi-vim (which allows me to jump to a definition), fzf with ripgrep to easily open files and search for specific things, and ALE that runs ruff formatting and linting. Tmux to keep my terminals organized and openbox to make it stylish and stay out of the way.

No LSP, no autocomplete, and sure as hell no AI nonsense.

> and sure as hell no AI nonsense.

You're emotionally invested. Not wise.

I tried chatgpt and claude, several times over the past year. To get it to say anything sensical is a laborious game of prompt trial and error, and even then in the end the code is of junior level at best, containing subtle bugs, inefficient instructions and needs a lot of refactoring. Not sure how emotions come into play, I tested a tool and found it useless to me. I'm much faster writing my own code, that I understand deeply, can reason about and learn from. I was never a fan of copy pasting big chunks of stack overflow that I didn't understand, which is exactly what LLM coding tools facilitate.

After 40+ years of programming, you tend to retain some things. I started out in 1984, so that means in 40 years, "me" of today will be in the year 2064. I cannot fathom what coding will be like then. But if I compare today vs. when I started, there are remarkably few differences. GDB has been my debugger for decades. The IDEs are better, but the UNIX CLI is still essentially the same. Bells and whistles don't help you solve problems, they just give you something to tinker with in between the real ideas, IMHO.

If they are good at what they do, I think they are simply good at keeping things in mind, what everything is called, developing a good mental model.

Personally I often write code without LSP, and use pure text completions with Emacs (words of opened buffers) and cycle through them. I know the language well enough, or I look things up in their documentation until I know them well enough. Occassionally I will also use LSP, if it exists and is easily configured and works well.

Go to definition: If I don't have it, I develop a map of the project in my mind where I find what in a project. I have also observed how projects become not so well organized, when people rely too much on always being able to "navigate through code". One does not need to pay much attention to module naming or class names and the like, if one never na igates the file tree to go to the file. Sometimes I have to rgrep/ripgrep.

I had a data structures / algorithms professor in college who would occasionally ask us to write C++ by hand, on paper, during exams.

Syntax wasn't really graded, its forgivable to make trivial syntax errors on pen and paper. The questions never covered more than a few dozen lines of code. But doing it this way forced us to really actually hold an entire small problem in our heads instead of just whatever slice of it the IDE was helping us focus on at the time and I think developing some of that skillset ended up being hugely useful to me when I started my career and was jumping into codebases far larger than I'd ever navigated before.

Jump-to-definition and search for symbols in RubyMine/IDEA are some of my most used tools today, but I think I'd probably be a worse programmer if I never had to develop the skill of working without them to a certain extent. I'd encourage everyone to give it a shot next time you have a few minutes to sharpen the saw. Grab a yellow legal pad and write a little toy parser/lexer for a toy programming language you just invented.

FWIW: I also love printing out diffs for nontrivial code reviews and marking them up with pen and paper, particularly big SQL views.

The hard part is not writing code but to maintain a deep understanding of how it works for a long time. The tools you mention do not help in this regard, maybe they even worsen understanding, structure, format and comments.

I find that I don’t use heavy IDE features much.

I just use a TAGS file for definition lookups. It’s fast to generate. Every editor worth its salt understands the format. It’s fast.

It’s perhaps slow but I do tend to use my own memory instead of autocomplete. As I use a module more frequently I tend to recall it from memory and know what I want ahead of time. So eventually I get faster than autocomplete. And bonus I get to know the codebase.

I find I make up for the initial slowness because I do most of my thinking before I hit the keyboard. Sometimes the autocomplete is faster than I can type but often it elects to select the wrong thing by default and it takes me more willpower and key presses to select the right one than to simply type what I want.

Slight gains at the keyboard don’t equate to much for me.

Although if you watch my streams you can see me smooth brain my way through stuff without much in the way of IDE tooling. Often when I’m streaming I’m programming off the cuff, chatting with folks, and generally more distracted than I usually am when programming alone. I also look up documentation manually a lot either because I want to show the stream or because I’m so distracted I have a memory like a fish.

Over time though I prefer to internalize and learn than to rely on tools to do the thinking and recall for me.

I don’t really use AI tools. I find reviewing the code mentally exhausting and tedious. I prefer to simply write the code I want rather than try to clumsily tell a robot how to. Plain language is sufficiently vague for conversation and too vague for programming tasks.

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

I open the other file.

At some point in time I wrote vue.js in vim without syntax highlight. For a few months. I had to eventually configure it, once somebody asked me if I'm color blind (I'm not).

>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?

You don't have to remember every field and type, because you don't work with all the types at the same time. Ones that you work with more often, you remember.

Workflow is something like this: open the file, split to left and right to see two stack frames of the same code path, open another terminal tab, start test watcher. Make changes and see tests fail. If tests don't fail -- write more tests. Then write more code. The usual TDD struggle. In case of CSS, just change it in the browser, then copy back to editor and refactor a but, then check again.

When in doubt about spelling, press shift 8.

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

:open another file and search through it, quote simple. How do I know which file to open? I know and when I don't git grep goes brrr. In theory you can jump to definition even in vim, use fzf to open files faster, in practice, none of that is not the limiting factor.

The limiting factor is iteration cost and the size of your context window.

That all being said, I use vs code now (at work) and use jump to definition all the time, because typescript support is just better in vs code. I think I started using it the moment I had to open more than one repo and switching between them on a regular basis.

Then I get back to my own fun stuff and there I use vim.

At the start, isn't this a bit like asking how people navigate cities they live in without constantly checking a map? The various strategies different people have will be remarkably varied. And there will be blind sides for many people. Hidden paths that some people know and always use, as well as parking spots that some people always try to get.

Moving beyond that, it isn't like LSP originated the "go-to-definition" feature. Indeed, this is one of the things many of us like about Emacs. You can literally jump to the definition of most any function currently in use by the environment. Can even edit it and have that edit immediately open.

But, moving back to my original line. The answer is people work in different ways. Is why some folks get really good at typing on a keyboard. Most people probably are not fast typists. But that doesn't necessarily mean the advantage a fast typists has will be realized in any actual gains.

I mostly need LSP on system with tons of ad-hoc definitions. react/typescript is one example, there's so much type definitions that browsing would take eternity. for non framework python codebase, the shell completion will be enough most of the time

I get distracted by auto complete and they usually stay in front of the code, so I can't read it. I find it annoying when I'm pairing with someone that uses it and the auto complete/type hint/whatever pops up and covers most of the code I was trying to read

Working in a code base every day I end up creating a mental map of the code and the data, so it's not hard to find stuff I'm looking for. When that doesn't work, a global search or find/grep helps.

I discovered copilot was disrupting my flow and providing subpar suggestions. Autocomplete and language servers seemed to result in me not knowing the language and libraries as good as I would otherwise.

I almost always have a browser with documentation open on another monitor and while there is a speed hit removing the tools I feel like it improved my mastery of software engineering overall.

I primarily write code in a DSL which has no good FOSS LSP implementation. If I’m writing this code on my personal computer I’m out of luck. My employer pays for a language server that requires a license.

There are a non-negligible number of my coworkers who don’t use the licensed LSP implementation and they write all their code in vim – or worse, gvim through a VNC. It’s very easy to tell that their code quality is worse.

I use eclipse for most of my Serious Work. With most "clever" features turned off. The kind of code-completion that lets me browse a list of partial matches is very useful (e.g. was it foo.bar() or foo.baz()?). Other than that, I like to do my own thinking. I enjoy writing software, not maintaining software that was generated by some tool.

Do I remember every type and every field? Of course not. But my codebases are structured. There are naming conventions in place. I generally have an intuition of where to find things. And of course there are many ways of searching for stuff...

I prefer using language agnostic tools where possible because that is both simpler and allows me to use the same tools with every language. For example, git, grep, or vim all work on any text file. vim has a few language specific settings though (e.g. syntax highlighting).

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 use an LSP and every IDE feature in intelliJ for typescript, Java, and anything else well-supported by jetbrains... except Ruby.

For me, Ruby's standard library tends to use names for things I would guess first, and the way people build things in Ruby feels natural to me. Any sort of LSP feature is nice obviously since it's never in the way, but when I end up trying Solargraph or RubyMine I end up noticing I'm just not paying much attention to it. The only places where I end up reaching for it is mass refactoring, like big renames... which are tough in things like Rails projects where files need to be renamed and pluralization matters.

So for me, it's the ergonomics of the language. That's probably mostly related to hours spent with it of course, but I think everyone has some specific environment/language/style that lets them compress the current state of what they're working on in their head better than anything else.

I use IDE at work but rarely at home.

My design is usually very simple, I don't have to keep a lot of things in mind to begin with. For instance, https://wordsandbuttons.online/ is about 100KSLOC now, but since it's inherently flat, no dependencies, no third parties, I can manage it with a Vim or a gedit with none of the IDE features. My implementation is always in the same file as the call.

I suppose, IDE makes writing harder code easier, which results in tons of saved time, but it also makes writing harder code easier, which results in tons of hard code.

First, surrounding your code is other code that very probably have a clue on what you should do. You do not have to go at the definition to see what to do.

Second, for one written/changed line I have read, perhaps, couple of hundredths of lines of code. This results not in a "fBeggy is a field of a class CBaggy" kind of understanding, but "the general approach to solve problem like this one at hand will be such (see this part) and such (also see this part)."

As a software support engineer, I have twice as low yearly output of (real) LOC (11.5K/y) than is expected from software engineers at, say, IBM. Mostly from the need to read substantial amount of code.

Find definition of Foo():

  grep -IR "func Foo("
Show uses of Foo():

  grep -IR "Foo("
Hmm, what were the methods in that field again? Open a split pane in Vim and scroll down in the second pane to where the field is defined. Also I pretty much just have the standard libraries of my most commonly used programming languages more or less memorized and keep the docs open in a separate window alongside as well for when I don't. And of course in a sensible language that actually gives you feedback (I'm aware some languages are more or less strict about this and it's not an option for everyone): when I try to build it, it will fail, indicating that I've done something wrong. This is okay, use the build loop and embrace the build errors.

*EDIT:* updating to address "CoPilot" specifically, as I don't think it's the same as the other things on your list. I have reviewed a lot of submissions that were written with various AIs and all of them without fail, this is not hyperboly, all of them were just bad (I'm sure someone will say that if you just use it for a 1 line error tweak it will be fine and what could go wrong there? And sure, probably, but if that's the case you're not getting any benefit from them so that's not what I'm interested in). The code was worse than a human would have written it, there were subtle bugs that no one had noticed because they were trusting the AI, etc. just don't use them. They're not ready, they may be speeding you up, but they're slowing down whomever is reviewing your code. It's a serious disservice.

I use emacs, and although I have LSP configured I switch projects and branches often enough that I don’t rely on it working. Finding definitions is normally pretty easy because code bases have structure, but occasionally can be tricky if the method is inherited, or overridden by subclasses, but that sort of thing sticks in your head after working with a codebase for a little while.

I think co-pilot is the more interesting example you give, because my answer is that I will not use it unless I could do the job without it. For example: yesterday I was refactoring a bytecode interpreter as the core loop had grown so large it was causing a performance issue. Solving this required getting the size of the method containing the inner loop back below a threshold. This isn’t something an IDE’s “Extract method” refactoring can do automatically because there is mutable state that needs to be passed in and out, and if I didn’t already know how I wanted to do it, would not be something I could easily check the correctness of co-pilot doing. So you sit down and think. What stages will you have to go through to extract and change this code? You come up with something that will let you validate the idea and then refine it, and you have tests, lots of tests, and some degree of intuition so that when you see a failure you can guess the thing you might have missed.

I used to not use any of those tools. In C, I split my source into logical modules, and added a short module prefix to each function, to make it easy to find.

Later, I found out about ctags and started using it; but it's not that useful for autocomplete. I kept to my old naming conventions: one verb whenever possible, plus any prepositions (is/has/etc.), noun if applicable, and module prefix.

This works well for the programs (not libraries) I write. Libraries have a different set of design considerations.

My function names end up like:

    memalloc (mem module, alloc verb)
    print (no module, print verb)
    gccollect (gc module, collect verb)
    vecappend (vec module/noun, append verb)
    Vec (module/noun)
    render (static function, render verb)
Most functions should end up private (static/not exported) anyway, so exported names can be short and still unambiguous.

In languages that have namespaces like Go or Python, I use their own namespace facility. I like to avoid the need for underscores or capitals in names so I don't have to press shift to type them, but some languages (Go) make this unnecessarily hard.

Eventually, when I started working in large Python and Java codebases written by others, I had to get an LSP plugin so it would take me to the correct definition. Ctags doesn't know about overloads. And some people don't care if they put a function in a logical place or not.

My editor's plugin doesn't have autocomplete, but giving functions a reasonably-sized name (and having two code windows open side-by-side) solves that problem.

> 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.

A question which I’m being asked more frequently as time goes by. Something that I just thought of is that i’ve worked mostly on long term projects which i’m usually the main architect. I know how the systems work inside out so I don’t really need IDEs to help me out with showing me where stuff is or being an encyclopaedia of function names, parameters etc.

Its a similar story with frameworks, those who create systems which are mostly frameworks wired together and those who strive for minimal dependencies. You can guess which camp I’m smoking my pipe in.

If you’re changing languages fairly regularly it can be more helpful, but if you’re in a comfortable language it’s pretty easy to memorize the most common functions/methods etc.

I recently had to switch to a project in Ruby and the LSP was not working it was frustrating but I can’t say that when it started working the next day that it helped me that much more. Maybe like 10% improvement?

Command F, command shift F in most IDEs to look up the definition if LSP isn’t working just search for name and append the class, method, function definition syntax. Like “function getUser” or whatever.

I've never used an IDE, perhaps it doesn't matter because I don't write Java. I actually find auto complete annoying in places where it can't be turned off like Google Apps Script or the BigQuery console.

Over the past few years I rarely write code anyway I just use ChatGPT and then edit the code.

I tried using the new canvas/project features last night and I think it slowed me down versus a copy/paste workflow. I think those formats could be good but they're not fast and polished enough and I've gotten used to tricks and hacks for working in chat style.

I've never used a LLM that has actual access to the codebase, so I kind of take chunks of code and put them where they need to be. Even if I have like 6 lines of code and I want to change the logic I past that into ChatGPT and say "change this to do XYZ". Even though that sounds dumb I actually gain massive advantage in concurrency. I can be working on lots of tasks at once because ChatGPT kind of toils away and I'll then jump over to something else and come back 90 seconds later and the code is there, I read it over, maybe diff it from a previous version, then I run that to test it and maybe while that's running I go to a different chat and issue another instruction.

Before LLMs I used vim. When I want to find a function definition I ctrl+z find . -name ".whatever" | xargs grep "function whateverThisIs" and things like that.

grep -d skip "thing"

I copy and paste a lot if I'm using function names, I use a clipboard manager I guess as a sort of pseudo auto complete.

"Then why don't you just use an IDE?" I hear you ask!

It's because I write lots of what you might call "glue code" or "microservices". Lots of snippets of SQL and JavaScript functions that are executed on a queue, and API calls to integrate with things and code that runs on different platforms.

I'm almost never working on what you would call "an app" these days, so that's probably why I've never gravitated towards an IDE. Even when I was working on more monolithic web apps I never used anything other than vim with "set nocompatible" turned on so it wouldn't try to do anything IDE like.

I think what I liked about it then was that I could be just as productive using putty from an internet cafe as I could be on my own computer. Like a doomsdray prepper version of coding.

This comes up from time to time and I always struggle to succinctly make the point I'm about to try and make again here:

Your brain is a good natural limit on complexity. I'm not saying there aren't goals that merit tools to manage complexity beyond what your brain could, only that you should be extremely reticent to unshackle that monster, because it's more likely to eat you than do your bidding.

Or more practically (and maybe more of a polemic): if you're maxing out the capabilities of your IDE on an average project, you goofed! We built postgresql, sqlite, Redis, Linux, Go, etc without IDEs.

Bad coders are bad coders. It has nothing to do with an IDE or features that streamline the process. Code Organization takes a higher-level of intelligence or skill that most people rarely develop without a solid mentor. If you have an organization with poor developers, then you’re not stepping up and using code reviews to mentor or taking time out of your day to educate. Most likely, your code is also not that well-written either or they would learn from that.

I use ratpoison tiling wm with custom bindings, it's kind of tmux or screen for Xorg where you stack apps for example firefox, vim, ssh, tmux/screen, terms. Anyway, it's up to you how you search ctags, man, grep, web, etc

This setup is agile but still not as fast as lsp or copilot, but I prefer learning and remembering over speed, personal taste :-)

I’ve been doing this a looooooong time. And that’s really about it.

Every time a popup or tooltip covers code around my cursor I groan in agony.

I’d probably use it if the tool tips just updated in the bottom right of my screen while I typed or something.

Emacs has completion preview mode, which shows the completion inline in grey text. This is what I prefer using at it does not block text, and I am only interested in the top completion 99% of the time.

There is an extension for Codium / VS Code that shows function docs on the margin instead of a popup – I find it neat and less distractive.

There was some shitty IDE years ago that would stop your keyboard input because it clogged the CPU with lookups for auto complete. It might have been eclipse or some other java monstrosity.

Visual Basic and VBA used to throw up syntax error dialogs if you cursored off an incomplete line.

It's why I don't like pair programming: done properly per XP principles, it's like having a human version of VB's intrusive error dialog.

One thing that’s missing from this discussion is the level of experience of the user and the type of projects they work on.

How long you have worked in a particular language affects how much you will be looking up function definitions.

Lots of other people working on the same project with loose standards means harder time assembling a mental model of the codebase.

Someone with cursor asked to program in a new language may be like “ah ok whatever sure” vs someone with vim might be like “it’s unreasonable management wants us to use these new age tools X works just fine” and then say “vim is so fast” in the same sitting.

I learned to code in a c64 and still sort of program in the same way. I sometimes print (in paper) code to better understand it. Also, I code on plain Vim with no plugins or custom config. *shrugs*

I would say advanced programmers were using some kind of autocomplete way before Microsoft popularised it.

The concept of IDE was invented by lisp machines, and emacs inherited a great deal of that functionality, but without the visual IDE. Great programmers were using shortcuts for accessing documentation at incredible speeds. The go-to-definition was there although limited to supported languages only, usually lisp dialects.

What Microsoft did was popularising it, standardising for different languages and making it easy to use/visual-graphical interfaces and destroying the competition the MS way, like Borland.

I would say, except copilot, all those features existed 30-40 years ago. It was just a pain in the a$$ to set or very expensive(Lisp Machines IDEs) or difficult to pirate(very important for Microsoft success).

Copilot can be replaced by competitor's products, like Claude. I use them outside Microsoft ecosystem. I use my own automatic system to access the AI.

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.

I hate auto complete. The last thing I need is a "helpful" popup of choices. It's distracting and ruins my focus on the code.

I have etags for jumping to a definition on the rare times I need to do that.

I programmed by hand for 25 years out of stubbornness, and finally installed JetBrains. Just do it, it's such a time-saver.

I prefer snappier IDEs, jetbrains stuff is really slow start up times and just slow making it more a frustration to use than other options such as vim or sublime

I write a lot of code for 9front within 9front, all of which is done through the sam editor. While sam does have a powerful general purpose editing language, it doesn't do syntax highlighting or any sort of language aware tooling (LSPs, jump to def, autocomplete, whatever). However I didn't start off with this, I'm not too old (in the second half of my 20s now) so I did take the tour through Java IDE's, tricked out vim configs and vs code as I was learning how to program. However when I moved to working on 9front I actually felt like the lack of these features made it easier for me to focus.

I like to think of code as not that much different than prose, they are both strings of text for communicating information, typically in a fashion of one thing after the other. I think most people would find syntax highlighting for prose to be more annoying than not (outside of perhaps seeing grammar rules for learning). Once I tried reading and writing code without syntax highlighting I found that it encouraged me to actually read and digest code instead of just skimming it. Compare it to reading prose with and without certain subsections highlighted.

Autocomplete strikes me as optimizing the wrong end of the problem. When I'm writing code I generally am spending a lot more time thinking about the problem space or considering possible implementations then I am having my fingers on the keyboard actively typing it out. In general I think the more you're able to think carefully about code in general the smaller it gets, so I find it hard to believe that by making it easier to quickly dump large amounts of text on the screen you're really gaining much. I think there should be a larger focus on reading and understanding code than writing it.

Stuff like code search is quite nice, and even in 9front we do have some scripts and tooling built-in to help us do that. We have programs like 'Bfn' which can search for a function and send it to your text editor, file names with line numbers can also be quickly sent to the editor as well. I think advancements in tooling that helps people move around in code are generally great, the time spent searching for something is generally not something I enjoy. This was perhaps the nicest part of LSPs in my experience. However I do also think that if you make it quite easy to jump around to lots of different files there is less of an incentive to carefully consider how you're laying out your code. How 9front works where there is some tooling to reduce the monotony but not enough to make it easy to traverse a couple million line java project strikes a nice balance for me.

[deleted]

I have NeoVim open on one terminal and just the console on another. I just run the linter/auto-formatter/compiler directly on that second terminal after I write in the first. if I need to remember a type/method/class, the default suggestions (ctrl+n in INSERT mode) or a simple grep are usually enough.

is this the most efficient way to code? probably not. but it involves zero yakshaving, which I no longer have the patience for.

I'm one of these, though I use a simple version of autocomplete which only suggests other strings currently loaded in my vim buffers (helps with RSI).

I liken it to spaced repetition. The first time I don't know where to find something I grep, after a few times I start to remember. I have a vim layout with 12 windows, so I have many views into the code and always have space to pull up more without losing context. I genuinely feel claustophobic with less.

> What do you do if you need to look up the definition/implementation

Sometimes I feel "jump to definition" trades immediacy in favor over natural exploration of the surrounding code. I work on a 10 year old mono-repo with 1000s of contributors. After two years I have a good feel for the basic layout, and would say I have a good mental map of the stuff that most affects me. During code review I'm often pointing people to existing implementations that they've just duplicated.

Just remember it, love the language.

It depends on what I'm working with.

A huge 100k LoC codebase? I'll happily boot something with an LSP. But it's very annoying and gets in the way. I hate when the context for my keystrokes is an autocomplete window, but it's worth it if I need to call a method with fourty arguments.

But when I'm writing code from scratch, it means I know what I wrote and what I'm using. If I forget, I usually just go back through the code.

Pen and paper is very useful as an extra scratch space.

[deleted]

My basic setup was vim/emacs (only as text editors) + grep/sed. It is totally doable and it is possible to be really productive but makes no sense when you have actually tried out adding some integrated tooling to your editor.

Thank you for this post. By making it, you have attracted other people from Hackernews who've learned to "switch off the targeting computer". It helps to feel not alone.

So to answer your question, hmm.

I started programming -- well, I started programming the way many xennials did, in BASIC on an 8-bit micro. But when it came time to use "real" programming languages and environments -- your C++, your Pascal, etc. -- it was typically on DOS/Windows machines with an IDE. I became a Linux convert in 1995-1996 or so; I kept Windows around but just found myself wanting to use it less and less. So I had to think of Linux -- and, if possible, free software -- replacements for all of my favorite Windows programs including Borland C++ and Microsoft Visual C++, both of which were at the time roughly coequal tools for serious development on Windows. (It would take a few years for Microsoft to consolidate its developer tools into Visual Studio and then eat everybody's lunch with that.) So you know, Microsoft Paint had xpaint, and Photoshop had GIMP (still at version 0.54; you think it's rough now?!?) and Visual C++ had....?

The guy who introduced me to Linux in college was an Emacs advocate as well, and I'd heard of Emacs probably through Micro Emacs on the Amiga. So I decided to try Emacs (it had to be better than nano or vi[0]!) and learn how to use the command-line compilers and Makefiles as well, and these tools cobbled together would be the rough equivalent of Visual C++ with all its features. Note well that there was much less difference between a commercially available IDE and a text editor with a compiler bolted on in those days than there is today -- Visual C++ wouldn't get IntelliSense until 1997 or so[1].

So right from the jump -- before even trying Linux or Emacs or anything -- I learned how to wield APIs by studying the docs and remembering the names of things. Class, method, and function names to me were just like any other vocabulary. Just as you might learn the name of a new bird -- say the Spencer's Warbler -- but not just the name, the association between the name and what the bird does. So it goes with APIs. You learn that there's a function called CreateCompatibleDC, that it takes an HDC param, and what it gives you in return. If you're vague on any of the details (param type and order, return type, details of behavior) the docs are always a keystroke or click away. This was true even in Emacs which gave you a choice of two man page viewers, or you go to the web and look it up. Simple as.

Since learning to work well in Emacs, I have revisited IDEs from time to time and found them to be distracting. They don't have the features that I need. Even if they be extensible they make extending it to add those features difficult. And they give me a lot of features I didn't ask for or want. It seems like the IDEs are designed for corporate drones, to optimize standard applications being developed in standard ways. Even in the times I've been a corporate drone, never once has plugging forward in a standard workflow suited my needs[2]. I have always needed to write a bit of Emacs Lisp to help smooth out the kinks in my workflow -- running certain database queries, for instance, or monitoring and managing Docker containers for the app I'm working on -- and give access to all the weird little things I have to do on the daily to myself at a keystroke. Doing my coding in an IDE, for all the convenience afforded by some of their features, is full of friction, and I never reach that smooth fast state of flow the way I can in Emacs. I'm sure I could get faster by practicing in the IDE, but I'm always unsure if I would gain enough in productivity to justify the time investment in learning to do so. (Visual Studio Code, I know, is absolutely "not better enough" than Emacs to justify completely overhauling my workflow for it. There's still some doubt about IntelliJ for me in that regard.)

Go-to-definition is one of the few actual productivity enhancers modern IDEs give you, just from a standpoint of being able to walk a code base to find out what everything does as you study it. For most programming languages, it could be simulated with ctags/etags in vim or emacs since forever ago.

[0] Hail to my vi/vim brethren; vi was actually my first Unix editor and I still use it to this day. I found its modeful operation inconvenient in 1995, but today I don't see vi and Emacs as rivals, just two different approaches to achieving the same thing which is providing a flexible, real-time hackable development environment in contrast to the IDE/Visual Studio Code school which optimizes for standardized workflows and is absolute friction town for everything else.

[1] If you are unfamiliar with mid-90s software development, I recommend you go onto Internet Archive and look for old versions of Borland or Microsoft development tools, and install those in like a VM running Windows 95, 98, or 2000 just to get a feel for what they were like to use back then. They feel very bare bones compared to what we use today, yet large companies ran on client-server applications written in them.

[2] I've noticed this even in the Visual C++ days; Microsoft really wanted me to use the MFC library, and what I was writing at the time (a game for Windows 3.x) had absolutely no use for the "document/view model" or anything of that sort. The engine also didn't mesh well with how MFC handled events; and at the end of the day, the difference between event handling code done the MFC way ("message maps") and event handling code done the regular way (writing and registering a WndProc procedure for your window class) was really about the same, so MFC didn't really save me much. But if you committed to MFC, you could mash a button and skeleton out an app in an instant, and then it was just a matter of filling in the blanks. I felt I learned more, and could gain a bit of code efficiency, by writing everything myself.

Auto-closing tags. hate them. I go to encapsulate something in quotes and it just tosses a closed quote right next to it, incorrectly. They perpetually make the wrong move.

All the "smart systems" are equally annoying. The auto-comment generators are just trash. They just add noise like this:

   # Object receives something
   object.receive(something)
I see this stuff in code review, just did today, I just ignore it now. Garbage added by the IDE, whatever.

And then there is the "smart indent" systems that seem to always guess incorrectly.

These systems are like a 4 year old trying to help you wash the dishes. I don't know how you people deal with it.

I coded for years on a line editor (ed). It was probably faster coding then whatever I'm using today. That thing was basically gestures moving at the speed of thought.

grumble grumble, kids these days.

> I go to encapsulate something in quotes and it just tosses a closed quote right next to it, incorrectly. They perpetually make the wrong move.

In Emacs I have automatically closing brackets and quotes and such, and if I want to encapsulate something I select the entire thing I want to encapsulate, press the opening character, and it automatically puts the closing character at the end of the selection. It also properly moves over closing elements when I hit a closing character (so if the cursor is in front of a closing bracket and I press the closing bracket key the cursor moves behind the closing bracket instead of inserting another one). I've gotten so used to it that editors which don't do this correctly turn me off big time.

Random thoughts on this topic:

- Years ago, I didn't use anything. It was just me, Emacs and a few packages. I surely knew about IDE features, but didn't bother. But I did get frustrated to have to look up things every time when I forget something. Autocompletion is an improvement and seeing docs fly up on a function helps a lot. But it's one part of the picture where the computer aids me...

- case in point: rg or ag are fantastic tools for searching through codebases. I use go-to-definition too if I can. However, I usually can find pointed references to fuzzy ideas about things much faster than co-workers who don't use rg, because regexing a codebase is much simpler than tediously running through files I am not familiar with to get a quick answer.

- autocomplete is useful when I don't know the language and helps to spell correctly. It does take me away from learning a language, but I don't do a lot of coding (hope that changes in 2025!)

- when I write Python, I don't really need tools as much. I pull up docs more. I have pylsp installed and sometimes when it is off or it can't boot for some reason, I just grumble and continue to do things without it. The same with bash. I am good with python but stink with bash, but still don't use LSP at all with bash.

- I still have some odd fears that since I don't use dedicated IDEs for most things, I will get disrespected when it is relevant for career progression. This is not without merit - sometimes computer-assisted tools can help with certain tasks much faster than others. We shouldn't measure based on individual tasks, but if you are getting constantly stuck on trying to finish something but the bottleneck is your chosen text editor/environment to convey ideas, it can look negatively.

- please, no copilot! I already feel like I lean on search engines too much to answer my questions. I know I become better when I enrich myself with general knowledge on a topic. It doesn't answer everything (thankfully search engines are there for that and don't want the quality of sites fall by the wayside because of copilot), but I imagine I would not be so swift on the types of problems I solve if it weren't for deliberate documentation reads and discovery.

- I am improving my understanding of Lisps (common and emacs). I feel like there is a different experience working in these. The typical IDE tools feel different given that all these tools can be used to interact with a running environment instead of using something that just primarily analyzes source code. I would probably fall back to my old habits when I am comfortable, but it is fascinating at least to me how the tools fit together differently than in "normal" languages.

[deleted]

I usually code with VIM. I work in many different languages and repos simultaneously. Python, TypeScript, C++, Kotlin, etc. Sometimes I need to ssh into a server and code there because I can't build AOSP on my Mac laptop. I sometimes find autocomplete helpful, but I can't be bothered to keep it working across all of these environments.

vim with zenburn theme. grep/find when I need to look for something.

I've been programming professionally for about a decade, and the basic Unix tools have always "just worked." They're available everywhere, my dotfiles are easily portable, and there's no licensing or procurement to worry about with corporate beancounters.

I'm sure I'm giving up some marginal level of efficiency, but I've watched so many fads come and go that I'm OK with the tradeoffs of "old reliable."

One key upside of Emacs for me is that you can open 3+ screens of code on one monitor. It compensates somewhat for lack of IDE features - I can literally see a lot of the code the IDE would otherwise be completing for me.

Sometimes you don't get a choice.

Some embedded ish IDEs, ssh-ing to a remote machine where you only have text mode etc.

You'd better keep that part of your brain that can code without autocomplete in shape, you never know when you may need it.

Spicy take: I write minimal but easy enough code to follow that there’s no “flow” needed. And by extension, no need for anything except a text editor.

Easy to say, takes a lot of practice, focus, and knowing common concepts across all languages to execute on.

I think this is very much an age dependent thing for me. When I started programming, there were no LSPs. There was not even any real code completion. I was using the Delphi 1 IDE in my first job and that didn't even really have any type checking till you compiled.

I think Delphi 3 was the first version with basic completion.

I do feel like I have suffered and become a little too dependent on LSPs/AI over time. But it is easy to see why when they can basically write your next line for you with quite a lot of accuracy these days.

Just take a pen and a sheet of paper and see how far you can get.

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 do this exercise once year, just for fun. Would recommend.

[deleted]

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've built a few small personal projects using Vim with NERDTree only in C#. I keep doing this every few months (small means the solution has around 4-5 projects and it performs a few clearly defined little functions) and it is really is both helpful and interesting to realize how many things we take for granted, but how great it feels to better understand dependencies, which nuget packages are needed, version compatibility issues and many other things.

I also end up better knowing and remembering any new classes and methods because I have to dig through the reference documentation for each of these things.

Yeah. I don't use autocomplete, LSPs, or copilot. You just remember as best you can, choose better variable/type names that aren't a full sentence, etc. Most of my time isn't spent typing.

I do use and really like go-to-definition, though. LSP is one way of doing that (probably the right way) but historically we used tools like "ctags" for this (and I still do, just because I've already got that workflow set up).

At some point, python became the language I use the most. And its IDEs… are frankly not really great. They are doing their best, but given the dynamic nature of the language, the experience of using autocomplete and other similar features is often jarring enough, when it doesn't do what you want it to do, to be annoying.

So I mostly stuck with really simple text editors (first likes of notepad++, geany and gedit, later switched to barely customized vim). You learn the language, you learn its standard lib, you learn the libraries you use often, you learn to navigate their docs. You learn the project you are working on, and remember how things are named. I do use a simple autocomplete (ctrl+n in vim), but it's more of a typo preventer (or a typo propagator, depending on how you look at it). It autocompletes every word in open files. Which might be more handy than it sounds, because it will autocomplete stuff not typically being autocompleted in IDEs, like json keys, or file names in the open directory listings, or even outputs in the open terminal session.

As for navigating unfamiliar code bases and "go-to-definition": it's grep. Just search for a substring in the whole project. You will find the definition. You will also find some other interesting stuff, which "normal" IDE tools wouldn't look into. Heck, you'll find interesting comments, interesting name clashes, interesting usecases for a thing you were looking for. And it's a language agnostic skill. You don't need another bespoke IDE, you don't need to configure some weird LSP to navigate unfamiliar code base even in not so familiar language.

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.

PSA: No matter how good you are, please don't do this if you're working in a tech stack you are not familiar with, in a team with people who are experts and are using fully fledged IDEs.

There will be inevitable ultra-basic mistakes, especially if you're also not familiar with testing the code you're actually writing.

I say this as a specialist using an IDE and having had PRs sent to me that weren't even syntactically valid, because the developer was not using an LSP in a language they were not familiar with.

Maybe submitting PRs with code that wasn't even run is the problem, not IDE features?

This happen with IDE people too, and even more often with LSP people. Too many people take what the tooling say as gospel instead of taking the time to get an understanding of what they are doing.

Not using LSP does not mean not compiling/running. Using an LSP should not qualify you to commit without compiling or running either!

I use nvim. If I need to look something up, I use Telescope, which pops a modal up in the current buffer. Type the first few characters of whatever you’re looking for, and get a preview of it in the codebase, as well as the path. If I want to, I can then open that file for further investigation.

I personally don’t like the surprise of autocomplete, or of anything popping up on-screen that I didn’t ask for.

Telescope is amazing. Although lazyvim seems to be all in on fzf now.

Long time sublime user, always has autocomplete off as it’s more a distraction than use. Recently started using LSPs for the inline error/warning checking but avoid things like go to definition - search works just as well in my experience and is faster.

See lots of comments here about code organisation and developing a deeper understanding of a codebase and I could not agree more. At least for myself not having all these functions gives me a deeper understanding of the code. I’m probably slower to onboard onto a codebase but I bet long term have higher productivity on it.

I use a concise language that I know well. When your language doesn't have so much boilerplate junk, you don't need an AI to generate it for you.

Try working in a really concise language, e.g. an APL-family one, for a bit. Once you get used to it you might take the style back to other languages, it's possible to write fairly concise code in most languages if you actually try. See e.g. https://github.com/tlack/b-decoded/blob/master/b.c

When I can't remember something, I look in the documentation or at the implementation. For functions I use often, I remember what arguments they take and what they return, for others I just look them up as needed.

I find myself going back and forth about whether I want all of that stuff. Not having to look up a function template is handy. On the other hand, having my code bouncing all around, and obscured by random pop-ups, is distracting and eyestrain inducing. None of it is touch-screen friendly, though I admit that it's reasonably well designed for keyboard shortcuts.

I'm on the fence about copilot. It's like today's story of Julius, an assistant who is beloved by management, but whose work demands attention and must be corrected. Doing a Google search for something is less "efficient" but I need to take frequent little mental and physical breaks anyway.

[deleted]

Just about a decade ago I switched from VIM to an IDE with auto complete. For me personally, typing it all out made me far more intimate with the code, but more importantly it forced me to be very intimate with the language.

Today, at the other extreme of having an LLM actually write entire methods or sometimes classes for me, I do feel that I have less of a mental model of how my software is designed. Ostensibly I still "wrote" all of it, but it's just not in my mental cache.

Or, that's just age ))

In one of my earlier jobs a few years back, we were training deep learning models on VMs with GPUs, back then the tooling was not as extensive (vs-code did not have the remote ssh then) as it is is now.

So, we would use SSH into the VM and do our work. This also involved a lot of debugging of code through vim since it's quicker to make in-place edits and re-run experiments, this taught me a lot on effective debugging and writing code for the VM

I'm interested in any tips you figured out for debugging in that environment. I find a GUI debugger to be an essential tool for this kind of work. It's the thing that keeps me using vscode remote vs just vim on the server (which I'd prefer if all I needed was editing).

I have code completion in vim and I try it every few years and sure it can save a few key strokes but the habit of using it never stays with me.

I think I just learn the code base and build a mental model of where everything is and it works for me. I spend more time thinking about how to organize my code well than to actually type it in my editor anyway. It probably helps that I'm working on Rails apps so there are strong conventions about how to do things that makes this easier.

Same here, code completion just gets in the way and messes up what I was already planning to type.

But I DO use jump-to-definition in Vim and other editors. IMO LSP has been an amazing productivity boost just by that one feature.

When I started like 20ish years ago, you didn't have all that fancy IDE stuff thrown easy at you. For a matter of fact, I didn't even have access to a stable internet. So I learned a lot and relied on my memory.

It had many drawback, it had some upsides like really having everything stuffed in my head and learning probably more promptly by searching/memorizing.

Java is the only language I've ever met where an autocomplete might be a net positive, since the ecosystem is full of excessive verbosity. I'm not confident about that, since I don't write anything in Java if I can help it.

For other languages - typing is never the limiting factor, and actually reading the docs is better than praying that your IDE gives you something meaningful. For languages with a working REPL (or even a typo-detector) you can use that if you really need to introspect.

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.

Thanks, I'll take a look and see if that helps.

[deleted]

Delete these five words.

Imagination, not pagination. Destroy all software. Don't let some tool make you a fool because the safety is off and the training wheels are no longer there. Turn off the defaults, the noise of misinformed conversation, non-existant completion of words lost in translation.

I do wordpress dev at the moment and there are some blade template and I don't know how use autocomplete/LSP to hunt down functions/methods used in blade templates.

Makes me sad :(.

At least xdebug works.

I've learned two languages using just a text editor (VI or Notepad) and found that it really helped me spot typos and syntax issues early on. I keep a browser open with tabs loaded for referencing language/package docs and referencing examples. Compiler errors literally tell you where your mistakes are, which is great for learning a new language.

I definitely recommend IDEs for navigating large codebases at work, but I feel like autocomplete has gotten much worse over the past ten years, as it tends to be slower and less concise.

> Do you just remember every type and field in a codebase?

I remember the functions that are relevant in the current context, yeah. I don't design things that have a lot of properties in the first place; and I'm concerned with what objects can do, not with their types (and I use Python, which empowers me to write this way).

> What does your flow look like?

Generally I keep a terminal open as I write in an editor window; most of the time it's cd'd to the project root. (Hmm, maybe I should be using `pushd` and `popd` more....)

At about 200 lines of code in a file or 10 lines in a function, I start looking for ways to split it up or organize things better. At double those values I start panicking about it.

Every identifier name is an opportunity to explain something crucial about the process.

I rarely use inheritance any more, let alone multiple inheritance. Jack Diederich's "Stop Writing Classes" (https://www.youtube.com/watch?v=o9pEzgHorH0 - a clickbait name, but you know how it goes) is part of my mantra; `functools.partial` is very often a better tool for the job.

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

I can tell where it is because the import statement tells me the package name, and I have a single file hierarchy for code in my project. But most of the time I can just trust myself that it works the way I expect it to, because I wrote it, and I followed conventions when I wrote it, and I made sure it fundamentally doesn't do very much or have a complex signature. (If it operates on complex data, I build that up - step by step - rather than passing all the pieces as separate arguments.)

If it's someone else's code, generally I'm going to look up the documentation anyway, not the code. If for some reason I have to figure out where the code is, I can do it easily enough, because I know where third-party libraries are relative to `sys.executable`, and I know where that is because I use venvs in a standard and predictable way. (Oh, but I could probably improve this with a one-liner Bash function, brb....)

But I do also have the option of checking things at the REPL. Python does a lot to help programmers feel like they don't need an IDE. (Avoiding boilerplate is also huge here.)

In dynamic languages things like autocomplete often make it worse, they cannot identify the correct types and locations 100% of the times. So at some point I decided to avoid these and got used to it. To the point where I avoid QtCreator for Qt/C++ projects b/c autocomplete and fancy navigation features become annoying and distracting

Some languages like c/j/k/perl/vanilla js etc I have no issues doing without these tools: they are usually more an annoyance than doing anything useful anyway. For verbose languages or environments where you are basically gluing libraries together, I do like these tools. Cannot imagine how you comfortably spelonk the trillion npms you get thrown in your lap in that project you got handed.

So, Autocomplete, Lang Server and Copilot.

I don't use any of those, and I've never felt the need for them really. Is Make and Vim not an IDE?

None of those existed when I started to code at my first dayjob and I've never really seen the value in them.

I find it interesting you think that go-to-definition isn't possible without a language server. I was doing that long before lang servers existed.

When I want to look a function signature up, well there's two ways I do it.

1) vim + ctags and Ctrl-] will take you there (usually, sometimes it gets confused).

2) grep (or nowdays, ripgrep) the codebase for the name of the function (in another window).

As for remembering what is where. Good organization helps. After time I tend to develop a mental model of what is where and I'll just find myself popping over to the other terminal and opening a file in vim to find what I need.

You can take syntax highlighting from my cold dead hands, though.

who has all the time to set that crap up for it just break tomorrow?

How does anyone handle the visual distraction/interruption of those g-d popups?

If I could get syntax hints and docs in a fixed space I would probably do it

[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.

If you just used a library for a few times or new to the language, LSP is indispensable and immensely helpful and productive. But after working with them for a long, you automatically memorize things and don’t really need them anymore. Until you work with a new library. And nowadays, library and frameworks make the heaviest burden of the daily programming task, not the language.

[deleted]

I don’t use autocomplete for the same reason I use a single monitor: Distraction.

And I’ve noticed my co-workers who use IDEs and multiple monitors are no more productive.

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.

[deleted]

I had no choice most of my career doing Rails.

Now I do C++ and I would fight to the death to keep autocomplete.

But Copilot I bought a license for a got a refund for after a few months. In the net, it wastes your time.

And I mean, copilot in particular is especially bad. It refuses lots of valid programming questions. Other LLMs are better. But they still are wrong a lot.

Rails is the worst. No autocomplete. How do Rails devs live like that? I hate it every day lol.

Copilot really helps me as "inline ruby/rails docs". I think the RoR docs are pretty bad and many gems are even worse. Rspec docs are incredibly unclear so I rely on copilot + chatgpt and other files to find out how to do things hah. Usually I reword the question a few times to find multiple solutions and I pick the one I like best.

Did you also try out selfhosted LLM alternatives? How do they perform?

I am looking for a terminal/offline LLM I can use for templating tasks, as most other programming mistakes are caught by my linters and tests anyways.

I’m satisfied bouncing between the free tiers of Claude and ChatGPT

I usually only have like a few hard questions per day, where I have lots of unknown unknowns.

If the LLM doesn’t get me an answer within the free tier number of messages, it’s not gonna get there

I use an app called Dash from Kapelli to access documentation for classes and methods. It’s a game changer, even if using a LSP. I do use copilot though.

I use partial autocomplete. Emacs has the universal autocomplete that's not language specific but gets it right often. I do use LSP on languages that have support. For languages that don't have good LSP support, just search. Emacs has great project wide search.

for me "artisan" devs see coding as a craft, avoiding modern tools to "stay sharp" or stay closer to the metal. its cool admirable but really not adapted for complex modern systems. Tools exist for a reason—maximizing productivity and reducing cognitive load.

IDE features are meant to prevent mistakes, errors and done tasks quickly. Do not to use it as a guiding map all the time to find your lost treasure i.e. code part you wrote a few hours or a while ago.

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.

> and recently copilot

I, for one, have never even used ChatGPT. ¯ \ _ ( ツ ) _ / ¯

I'm a software engineer, pretty highly regarded as very skilled by everyone around me, almost entirely self-taught (programming since age 7), and have worked at 2 household-name companies (and now a spin-off of a third). The only computer science class I've ever taken was a PhD-level introduction to machine learning, in the mid ’90.

I've never seen any task _where the details matter_ that AI appeared to be any good at. For example, I've seen a coworker trying to demo for me how quickly an AI coding assistant could fix a bug in a parser's state machine… but the AI made a mistake, which I spotted immediately.

I have done +12 langs (used for work) with a variation of some using an IDE, a user-facing GUI (like Excel/VBA/SQL Admins), others just a text editor, etc

Some have auto-complete, others do not.

I use some of these combos at the same time.

The main thing I learned is that certain languages are made for one way or another.

For example, python, SQL.

There is not much you get from a IDE for python, and a good editor make wonders. SQL is braindead and bad designed, so the only moment you wanna to autocomplete (for get fields) any tool I have used fails (ironically, this one thing where copilot actually improves it).

So, if the language is made to work well without ide, it will work well.

What is a terrible mistake is refusing to use an IDE (or IDE-like capabilities) for languages like Rust, C++, C, etc...

Before switching to neovim, I used a split terminal with vim in one split and the other split for running `rg`, `make`, tests, etc. It's amazing what you can achieve with grep especially if you use something like ctrl+p in vim which can use ripgrep for fuzzy finding.

I refer to the documentation like my forefathers did. But I do happen to work with a language with good documentation (Elixir).

They program as I used to in the 1980's and 1990's until Borland and Microsoft introduced code completion to the masses.

Typing the whole thing, while having manuals open for quick cross-checking.

Using text search tools to find code.

I'm old. I use vim with no plugins, no LSP, no autocomplete. I use the command line for everything but editing. Works just fine.

Now get off my lawn.

Wow, surprised I look like living in a different world, enjoying when documentation pops up as I type. So surprised that many people don"t like Intellisense stuff.

Think of it as people who feel more frustrated than other by being interrupted in their thinking process. From my anecdotal evidence I think one can map different psychological spectrums like ADHD or autism to them liking or disliking such tools that "pop up".

I agree, but just turn hover popups etc off in vscode settings?

But yeah, oh my is vscode noisy!

To folks over a certain age this question is hilarious. ;-)

Pretty impossible for anything JVM-based IMO. But I am mostly working with C++, C and Python, and it's all doable with grep, vim and a tiling WM

I prefer autosuggest to autocomplete. And I didn't like copilot, doesn't seem to work very well for embedded code, though it's been a while since I've tried it. LSPs are useful.

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.

i do search with rg its good enough most of the time, i rarely need to use lsp. I also do it in emacs which kind of abstracts these things away from me it almost looks like lsp. I do use autocomplete but its on opened files/buffers its not projectwide works fine. I don't use co-pilot but heavily use ai so most of my programming these days is editing instruction to ai. Fix this ui, create this method, make it modular, give me skeleton flow, lets debug this, etc.

You just skim over the API docs and learn the APIs. Grep can help look things up. Depends a lot on how many new APIs one is using and how non-trivial their implementations are.

I use my squishy pinkish-brown thing to create a malleable model of the program

I admit this is my personal shortcoming, but when the IDE pops up anything while I'm typing I find it very distracting and damaging to my flow. It feels like someone interrupting me every spoken syllable. And they commonly cover up other code.

I want help when I explicitly ask for it.

Younger devs might not have this issue.

Code should be intuitive - i.e. it should be implicitly obvious about types and so on.

Perhaps if you are working on things in a very "scatter gun" way - i.e. you write a function here a function there but never really go deep in a codebase to really grok it then you'll never really get an understanding of it.

In the old days - or when LSP just doesn't work which for me is probably more than 50% of the time it seems - I rely/relied on compiler errors and/or test failures to detect problems. You can just open up the file that contains the function you are calling etc to go read what it expects.

FWIW I use all the fancy bells and whistles in terms of autocomplete and LSPs when I can (and when it works it is a great help) but I never use AI directly in the code-writing-flow. For me this is akin to the bad old days of junior/offshore Devs just copy-pasting code they found online/on stackoverflow and trying to write glue code to connect it all up. You end up with a real mishmash of inconsistent approaches/styles, duplicated code that does the same thing but in different ways, code that kinda-but-not-quite does what it needs etc, usually no coherent tests, etc etc - tl;dr super low quality and hard to maintain mess.

I will certainly use AI to help me with a few things, perhaps provide an example way of doing something/inspiration, but it is more akin to rubber-ducking and the output of an AI is never directly used. I view it as a quicker way of going to look up the right algorithm in a text book or something.

I keep a few windows open, e.g. the module I'm editing, and whatever module I also want to be reading. If it's not my code, I just have the doc open [https://hackage.haskell.org/package/vector-0.13.2.0/docs/Dat...]

I use ag (silver searcher) to instantly match any usage across the project - frontend, backed, SQL strings, whatever! Also since it's CLI, I can pipe/grep to refine the results even better.

Or alternatively I just make the change I want, hit compile, and get a nice list of all the breakages.

The language is way more important to me than the "tooling". Especially when certain features can oppose each other:

Example 1: null detection. Your IDE prides itself on finding nulls, when really your language designer was the one that put them there. Most langs don't allow reading uninitialised data, so if you accidentally read a null, it's because someone deliberately wrote a null. Far easier to not have nulls, than to insert them and take them out later.

Example 2: IDE type-overlays. If I write 'User user', my IDE scolds me and tells me to write 'var user' instead. Then the IDE has the audacity to insert a small grey 'User' back into my text because it knows 'var' isn't helpful.

In the case of Xcode, I use it, but carefully.

The new "intelligent" autocomplete is annoying AF.

In some cases, it's great. Gives me a suggested function call that exactly meets my needs.

In other cases, not so much.

Here's a [hypothetical, but not really] example:

Say that I declare a property, like so:

    var userWantsMeToCreateWidgets = false
Then, later on, I want to reference that property in a function:

    func seeIfUserWantsWidgets() {
        if userWantsMeToCreateWidgets {
            .
            .
            .
        }
    }
When I start writing the if line, autocomplete invariably suggests something like:

    func seeIfUserWantsWidgets() {
        if *userDoesntWantWidgets* {
            
Where the heck did that come from?

But wait! That's not all!

If I later reference the function call, autocomplete often does this:

    seeIfUserWantsWidgets(*to: .paint*)
WTF???

It will often hallucinate variants of API calls, as well. I have to be careful, when adding delegate functions, because they are completely legit, as far as the compiler and linker go, but will never be called, because their signature is wrong.

Ctrl+N in Vim, and API docs.

Rigrep and fzf in bash and vim.

In Java, not having something that automatically inserts imports would be incredibly counter productive. I feel that this is easier in other languages, where you don't need to manually import almost every 'jdk' class that you use.

Not sure about others who commented in this post, but all guys I met in real life who refuse to use advanced features of an IDE like autocomplete, refactoring ... are either: 1) have never work in a truly large scale projects (and usually familiar only with weak type languages - which IDE cannot help much so they cannot grow over a certain limit - chicken and egg?). 2) do not know what are the differences between a rename/search features offered by IDE and terminal commands to achieve similar objectives. 3) do not really care about productivity (use find & xargs for searching and does not even bother to write a script? meehh)

So when someone says he do not need an IDE because its feature are just distraction, my first question is always about the biggest project that he has worked with, and the second one is how he do rename/navigation/... with his code base. Never find a single guy does not fall out of these 3 groups.

Copilot is another thing for me. The reason is its accuracy is not good enough yet. The moment it can produce code align with my intention 100% accuracy, just like how search/refactor/suggestion that IDEs are currently offer, I will include it in my workflow instantly.

There is some low-key ableism in comments like this. Not all of us have our productivity enhanced by videogame shit happening in our field of vision while we're trying to code, or by software tools attempting to get ahead of us and do or check our work while we're typing. These things are distractions, and the price of distraction, especially for people with certain forms of neurodivergence[0], is very, very steep, nullifying or negating any productivity gains we might otherwise get. So we use our editors with bells and whistles kept to a minimum, and do a bit more up-front thinking in terms of how to structure things and what to name them.

I've worked on very large projects including the entire software stack of a robotics platform and a few enterprise apps using bare Emacs with no autocomplete added. Lack of autocomplete and bulk renaming has never been the productivity bottleneck for me[1]. And I can always tell code by those developers who get a little bit lazy -- or rush through things a little -- and let the IDE do the work, it's marked by things like class and method names that are consistently misspelled everywhere because the programmer typed in the name once (wrongly), and then let autocomplete finish it after typing the first few characters every other time -- never noticing the misspelling.

As for not bothering to write a script -- usually to smooth out my workflow I write a bit of Emacs Lisp to wrap a complicated shell command that does one of the more common tasks such as starting up/shutting down containers for my app, running tests, etc. Emacs Lisp is actually a very powerful environment optimized for this sort of work, even if it's wonky by modern Lisp standards. Then these tasks are just a keystroke away whenever I need them. Great for my ADHD, as I don't have to "stop train of thought, remember shell command(s) to do task, switch to shell, type in command(s), examine output, resume train of thought".

There's even an Emacs command built in for the example you gave: M-x find-grep.

[0] There is actual scientific research backing this up. See: https://arxiv.org/abs/2302.06376

[1] Usually the bottleneck is, I get stuck on some bug and feel the need to bro down and fix it entirely myself, rather than getting a coworker's eyes on it. I find I'm better about this now than I used to be.

"Back in my day, goin' to foo's definition meant packin' yer bags for a four-day horse trek over the mountains..."

Seriously though, pressing Ctrl-B in JetBrains IDEs is half my workday.

I just tried out Copilot starting a couple of weeks ago for Advent of Code, and I'm very impressed. Easy 2x speed boost, with occasional bursts of much more. I'm mostly using Java, though I've tried Perl and it knows that too.

Honestly, it's really not that difficult if you give it a try. I grew up in a era where autocomplete was complete garbage and sometimes it would even cause issues (slowness, crashes) in the IDE.

Give it a few weeks (or even a few months, I don't know). You quickly learn the "rhythm" of codebases -- and then eventually you've seen it all to the finest details.

Then it's "ezmode." And it's not just for one codebase, you become better and better at realizing the way a code base is architected (code base being anything from an actual application, to an SDK, etc).

These days I mostly write Haskell, so I'll focus on that. When I'm writing Python, Rust, or C the stories are similar broadly, although may vary a bit in the specifics.

I don't think the way I work is all that different from the way people who use a lot of IDE-like features work. The main difference is that I prefer a pull-based approach to getting information, rather than having my editor push information at me or try to do things for me.

My typical setup for a project is to have my editor (emacs) open with code, and separately to have my project open in a REPL (ghci). For smaller projects I use haskell-mode, which lets me open a REPL with the file I'm working on loaded automatically. At work our codebase is a bit too big and our build system a bit too complicated for haskell-mode to be able to manage my repl, so I use a separate tmux buffer to open ghci.

I can do a lot from my repl. If I want to know the type of something, I can either look it up using the repl if it's a top-level binding, or I can add a type hole and reload the file if it's something that's not directly available in my repl. I can also see what instances are defined for a type, what functions are available in those instances, and where the type is defined.

In addition to my repl, I'll usually have a shell open in my project. If I'm trying to figure out where something is defined, I can just run a command to query hiedb, although in reality it's often fast enough to just use ripgrep.

If I'm trying to remember the name of a file or where it lives, I will typically use fzf, either in my shell or in emacs. I can usually remember enough about the name to at least narrow it down to a couple of options.

For things that live outside of my project, I wrote rofi-hoogle (https://github.com/rebeccaskinner/rofi-hoogle/) to let me search packages and documentation from my desktop with a simple keyboard shortcut. It also lets me jump to the online documentation if I need to read more than the type.

I don't use copiolot or any other sort of AI auto-complete at all. Occasionally I'll present a simplified version of a problem to ChatGPT and ask it to write code, or I'll ask it to review some code, but I typically do that through the web UI. I keep intending to get it set up in emacs but I haven't bothered yet.

I wouldn't necessarily say that other people should adopt my way of working, but it's the best way of working that I've found for me and my own quirks. I've tried IDEs every so often, but I find that the constant distractions make it hard for me to focus on the task at hand- whether it's things popping up in my field of view, auto-complete moving my cursor around, or error messages popping up because I haven't finished the code I'm writing. I'm probably slower at the IDE-specific tasks than people who are really good with IDEs, and maybe even slower at those specific tasks than I would be using an IDE, but the benefit of being able to eliminate distractions and focus on the code I want to write outweighs the cost for me.

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

Am I the only one paranoid about LLM IDE integration like copilot stealing your code and using it as training data, even if there's a privacy policy that denies any such intent?

Hi, younger programmer here who's first programming experience was Visual Studio and .NET (that's a lie my first programming experience was a decade earlier with yabasic and notepad but given that I only ran about three programs I'm loathe to count it) my tiny laptop struggled to run Visual Studio and I was working a lot in server admin so naturally started using vi. Vi came without any modern features and when I tried to move back to Vs code I hated it so much. The screen was so busy and every time I typed something I was distracted by 100 different suggestions, sometimes I would accidentally press a key and paste a load of code in I didn't need. By this time I had already gotten proficient at vi keybindings, got any information about an API I needed from scouring the documentation/manpages(please every one make a lot more manpages). I then decided to see how much I could strip back without really affecting productivity. Anyway a few months ago I switched off syntax highlighting and now other people's editors look like a mess to me. Anyway I love that I can program in any environment on any machine as long as a text editor is available. Makes me feel like I'm not beholden to Microsoft or jetbrains when they inevitably tighten the licenses and I think it makes me a better programmer because I have to read and think about the APIs I'm calling.

tl;dr modern ide's abstract you away from compilation pipelines and make you more reliant on intellisense than reading docs. Syntax highlighting is a psyop designed to kill the art.

I also want to add to this: I write code in such a way that I shouldn't need to be referencing multiple files because each file exposes a clear interface. As long as the interface makes sense with the rest of the program I shouldn't need to think about the specifics of it and should be able to populate the interface as naturally as shifting gears whilst driving

Also I use vi so language server protocol installation isn't something I have the energy to mess with. Nor would it make me more effective

I have a friend who still to the day doesn’t use syntax highlighting. People like living on hard mode lol

Emacs, etags, elpy.

For me part of this is a matter of context. The time when I was coding in a single language uninterrupted for months (I think I went a couple of years in one case) are long gone. Once you start context switching between languages, platforms and frameworks, things are very different.

Perhaps the easiest way to explain it might be CSS. If you work with CSS all the time, you retain and recall approaches to solving problems and, more than likely, have developed reusable code to copy-paste-modify. However, those of us who don't touch CSS full time always run into the dumbest of issues (centering and alignment come to mind).

For me modern autocompletion tools are like asking for a capability being loaded into the Matrix. This allows me to switch between just polar opposites as Javascript and Verilog and almost not miss a beat.

Given the right context, I would not fault anyone for relying on these tools. Solving problems computationally isn't about remembering ridiculous syntactical differences between languages but rather about data structures, algorithms, performance and process. If you have a solid background in CS and experience developing software, not remembering the differences between C, C++, Objective-C, Swift, JS, etc., etc., etc. isn't that important.

One caveat: There are domains where you need to have a certain level of expertise without assistive tools. One example of this is mission critical real time systems. Than again, this isn't about remembering syntax and more so about being able to write performant code that is safe.

Yes, you just know what you're doing. The more you do it, the more better you know it.

Can you drive a car with manual transmission?

If you can, then do you feel helped by automatic transmission? I don't. I feel like too often the automatic transmission makes the wrong choice. It doesn't feel like more work at all, and allows for much better control of engine braking.

(You shouldn't be using your other hand to hold anything while driving anyway)

I moved to an EV from an automatic transmission, and I’m pretty much used to one pedal driving now (using regen to slow down and stop most of the time). No gears at all took awhile to get used to, but now it just seems a better way to drive.

Manual transmissions get a bit stressful on steep hills, and so I don’t really miss them much accordingly.

Ripgrep ;)

I've been through both aspects. I really wouldn't listen to any of the people in this thread. Advice in this arena is so specific to domain and environment. If you don't remember function parameters for every builtin or stdlib of your language(s), you should look it up in the docs or use the LSP provided feedback. I have to reference my own libraries for docs sometimes. I just find myself in too many different codebases in a week to remember everything.

I learned more Bash and Python from running Shellcheck and Ruff respectively. Frankly, if your code has squiggles that get on your nerves from the LSP/linter fix the settings ... or better yet, correct the syntax. gasp

Alt + Backslash , YAS, etc. Emacs

M-\ is delete-horizontal-space, you may mean M-/, dabbrev-expand.

Autocomplete:

It's nice, but using non-shitty libraries with good documentation is nicer.

Language servers:

Bloat.

Copilot:

Why bother with AI when I'm good at writing buggy code myself?

Remembering types and fields:

Don't trust memory. Write documentation—if only for yourself if not for your colleagues.

The language server go-to-definition feature:

That doesn't require a language server, just a cross-reference; see also ctags, bloat (above).

For IDEs, I use Jetbrains and some VS Code.

Autocomplete mostly pisses me off. Most of my completions are triggered accidently. Whether it's because of me, the trackpad, or my crappy keyboard, I dunno.

I want the suggestions off to the side, not in some rando pop-over that's always moving around. So distracting.

My alternate UX notion is for the cursor's focus to always remain in the middle of the editing window. The content (source code) would scroll up and down "under" the cursor.

Then all those inlines, suggestions, autocompletions, popovers, whatever could always appear in the same location. Not dance around or try to fit where there's no room.

Next, since I'm polyglot, I spend a lot of time splunking javadoc (or equiv). I want some kind of hybrid between suggestions and abbreviated javadocs.

--

There is one onerous (to me) task which chatgpt excels. My new tool injests SQL. I'm assembling a corpus of tests, scrapped and copied from all over. Whenever my parser fails, chatgpt helps me to identify the correct dialect (grammar specification BNF) to reference.

For straight coding, I mostly use chatgpt to get oriented, get started. For common tasks I haven't done (any time recently). Like how do today's yoots do command line parsing? Replacing stackoverflow, more or less.

Otherwise, my current (hobby) project is a new take on an old problem. (Re)Invention and innovation. Chatgpt is sometimes helpful (to me) for brainstorming or validating a notion. But I'm too ignorant to know how to get chatgpt to help me create a new (to the world) thing.

If I was doing CRUD or game development, I'm sure chatgpt would be very useful.

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'm a long time i3, tmux, vim/nvim user. You can see a pattern. When I write code, I typically have a bunch of i3 and/or tmux windows open with dedicated tools ready to execute the necessary commands. Linters, compilers, containers, http clients, db clients, REPLs, log viewers, doc viewers, notes, tests, etc. All nicely organized and readily accessible a few finger taps away.

For the longest time I've only used a dumb variant of autocomplete that is scoped to only suggest names found in files that were loaded in the current editor session. It's not context aware like an LSP would be. It may sound bizarre, but I never really felt that I missed much. C-P/C-N, scroll one or two items away and most times I get what I want. If I needed to use an unfamiliar feature, I'd open my past notes or the docs and skim through them, or I'd reach for the REPL. But working like this, I think you also develop some extra awareness and other tacit optimizations that reduce the need to do this sort of things often. You remember many small details, you develop a knack for taking notes, you get efficient at using external tools, you learn to quickly access docs from REPLs, that sort of things. Someone else mentioned code organization in a comment. That's definitely a big deal.

I've often been fascinated by the approach of transforming the editor to integrate all the things for which I have separate tools. So I decided to try it out for a few months (Neovim has some powerful plugins). I ended up keeping some of the suggestions, mostly the ones that aid in navigating the file system within the editor and finding files (e.g. Telescope). But I think my LSP experience has been one of the most distracting programming experience I've ever had. Perhaps if I'd given it more time, I might have gotten use to it. But it felt less productive for really marginal gains.

I think describing my experience can bring to light that some of us prefer working depth-first, while others are comfortable breadth-first.

The "real-time" nature of the warnings and suggestions was inappropriate for me. It felt like trying to write an essay and being told to worry about form and grammar, while I'm still developing my thoughts. Laying down the foundations of what I'm trying to express and meanwhile things popping up in my face completely out of context. By context here I mean at the wrong time. I'm currently laying down the structure of my thoughts and I see the editor issuing warnings about syntax or wrong imports. Please, this is not the time. Let me think. Stop distracting me. I'm ok to not have it right on the first try. When I run the damn thing, you can complain all you want. Don't worry, I'll understand what you want and will fix it. Right now I need to think. This is not grammar time.

The fix for the above was to configure the LSP to be mostly silent and on-demand. But then there wasn't much difference to using it externally to the editor.

Grep?

The only tool you need really is a very powerful search that lets you jump around with only a few keywords.

Due to how my job is defined, autocompletion (the kind that comes with LSP) is usually not an option at all. In the context of my job, the largest part of my effort goes towards RCA (figuring why something doesn't work) in a system mostly not written or designed by me.

This means, that most of the time I deal with a system after it was deployed, often times in a distributed system with most of it only accessible remotely. So, the aspects of my tools that I value (over autocompletion) are integration with shell / terminal, integration with debuggers / tracers / profilers, ability to quickly search / patch files in any format.

Typically, if you look at my monitor (when I'm actually doing something), you'll see Emacs running ansi-term with tmux that shows a bunch of buffers with shells in VMs in different corners of the world, database interactive clients, interactive debuggers, interactive interpreters, vi with multiple tabs open, multiple journalctl -fu xxx buffers, or perhaps kubectl logs -f xxx buffers etc. and outside of tmux some Org buffers with lists of tasks or text that I use to export to JIRA markdown.

(I think my setup would make for an exciting hacker representation in some sci-fi movie! It's all green letters changing rapidly on black background in many small adjacent boxes)

Even in this context, there's some word completion available (eg. in shell, or in Emacs just trying to complete the word by finding similar words in the same buffer), but usually by the time I actually need to write something new (rather than add breakpoints or investigate in some other way), it's crystal clear what needs to be written, and I don't need to leaf through pages of autocompletion to find the right word.

---

Now, while most developers don't spend that much time figuring out why their software doesn't work, I still think it's a significant portion of any developer's work, so, simply from the standpoint of how much time you spend in what environment it might make sense to go for a tool that's better at editing text than a tool that has better integration with LSP.

I somehow just have a significantly large working memory in my head for what I'm trying to do, and then I'll look up a method if I really need it.

Grep, etc to find shit.

Then I dunno, it just kind of works.

I learned to code when the only thing available was syntax highlighting. I mean come on, if people with punch cards could do it, a nice editor with syntax highlighting should be enough!

I started professionally programming using VB back in the 90's, I remember how amazing it was at the time to use an IDE with autocomplete and a visual debugger coming from just doing basic on say the Commodore. I was never a C or assembly programmer, I understood it but everything I wanted to do I could do much faster in a higher level language in an IDE.

This was back when Windows was finally getting good (Win95) and I was not familiar with Unix at all. All of this seemed like the obvious progression from text base UI's to GUI's.

So for me it has been very natural to use autocomplete and expect to just attach a debugger and inspect running code and even modify it (VB allowed edit and continue) which is still a rare thing today that I miss.

Also using a mouse to move around the code base and inspect it just like using a GUI to use the computer. Because of this I have never developed a strong keyboard only ability, I expect a mouse to be available.

I remember getting into web development and having to step backwards into a language that wasn't really typed and no real IDE's that could autocomplete an interactive debugger, back to print debugging and text searching. Eventually the browser developer tools caught up but the JS language was pretty difficult to accurately autocomplete and navigate / refactor properly at a code level with an IDE.

Was fun to watch all the JS devs get excited over Typescript because autocomplete and refactor now worked reliably. For me having a language with real types the IDE can understand was the way it's supposed to be.

It seems like it's how you got started that determines your preference. If you were a Unix guy you liked the command line and TUI's and everything was about wrangling things at a text level, everything is a file and just a stream of bytes. If you were a Windows or Mac person then it was GUI's and mouse interaction and it was more about widgets and objects and IDE's.

I can appreciate both sides, I would like to be stronger in the command line and keyboard but how I got started strong influences the tooling I prefer and I am sort of set in my ways now, I suspect that is pretty typical.

I've never used an IDE to write code, though I have tested a few out on the recommendation of others. For 30+ years, I've only used these plain-text editors in this order: Vi, Vim, NeoVim, Emacs, Kakoune, and now Helix (I used Vim for most of that time).

I guess I keep everything in my head and use reference materials when I forget something.

IDEs bother me. I enjoy working in the terminal and have always found using a mouse while writing code annoying. I also dislike having tabs, buttons, menus, drop-downs, pop-ups, etc., in my way while I think and write code.

I primarily use a pretty minimal vim setup, and I use it a lot differently than most devs these days use their editors. I don't really have a "home" machine for programming, I just ssh into whatever box the code is going to be running on and use that machine's vim. I rsync over my vim config/plugins if I'm going to write more than a few hundred lines from that box, or if I'm using a language that doesn't have good native syntax highlighting and needs a plugin. For work at least I use local vim on my work-provided laptop, but other than that I don't really have a tight association to any particular dev environment. If it runs vim I'm happy, so I can pick up and start writing code comfortably from anywhere.

> how do you do it? Do you just remember every type and field in a codebase? What does your flow look like?

It's very different for a codebase I'm familiar with vs one I'm still learning. I do the vast majority of my programming on the former, where I don't feel most of the features you mentioned really matter. Yeah, I remember the types and fields. Usually they're already being used several times in the same file I'm already working in, so it's rare that I even have to make an attempt to recall something, and even rarer that I fail to. When I need to change or add something, I simply open the relevant files and write the relevant code, because I know where it should go.

When I'm learning a codebase, there's a lot of jumping around and looking things up to get familiar with it. I've found that using IDE features during this stage makes me slightly more productive in the short term, but makes me much slower at becoming familiar with the codebase in its entirety (or the subsystems relevant to what I'm working on, in very large codebases). Being familiar with the codebase in its entirety is very important to me and I feel like it enables me to design features and bug fixes much more reliably. My number one priority when working on a new long term codebase is to get to the point where I can fit basically the whole codebase in my head (with a fidelity depending mostly on the size of the codebase), and I do that much better when I'm working on it raw and not outsourcing my understanding to tools. Then once I have that complete understanding, I no longer need the tools anyway.

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

I open the file it's in and read the code. If I don't know where it is (which is rare, especially because most languages and codebases have rules or conventions for file/module/function names), then I grep the codebase for its definition before opening the file. But usually if I'm in the Foo subsystem and need to check the definition for its Bar.baz function, I know it'll be in src/foo/bar.ext and I can "/def baz" or whatever to jump to the definition as soon as I open the file. I've been meaning to try getting used to fzf vim plugins for the last 5 years or so but I really just don't care enough to put in the effort. It's obviously slower to grep and open and search for the def, but the problem just doesn't come up often enough for there to be a good incentive for me.

Switching/Learning costs are higher than my expected benefits

> Do you just remember every type and field in a codebase?

I type 'make' and let the compiler show me where the definitions fail. Often it will suggest the valid options. Opening the header in another buffer or window also helps.

I value semantic correctness first and don't get distracted by syntax errors if I'm in deep concentration. Conversely, I often make small changes when I anticipate a compiler error so I will know exactly where it came from, fix it (often by trial and error) and move on.

When I started writing code, I was using NotePad++ and tracking versions by... file name suffixes. And occasionally writing stuff on paper by hand, for the hell of it. It was awful. Discovering Git about a month into my programming career was, of course, a game changer.

The first IDE I used was Zend Studio [0], because I was writing a PHP application for the IBM i Series, and Zend pushed their IDE along with their licensed server [1]. (Note that in modern times, with IBM OSS for PASE, PHP for the IBM i can be sourced from e.g. Seiden Group for free). Zend Studio is eclipse based, and terrible - their modern landing page advertises PHP 7.1 support. About a month into using it (this would be sometime circa 2018), IIRC, the whole thing broke while I was tinkering with basic appearance preferences, and the application would no longer open. Instead of fixing it, I asked my manager if we could buy a PHPStorm license, since I kept seeing it mentioned in blogs and tutorials and it sounded nicer.

PHPStorm was an absolute game-changer. It was the first time I experienced the miracle of modern language servers. Go to definition? Holy shit! It can see errors before I test the code?! IT CAN HELP ME SPOT ERRORS IN MY JAVASCRIPT?

My PHPStorm license was probably the single highest ROI expense my company ever took on my behalf. That led to all sorts of rabbit-hole learning, like setting up gulp with babel and sass and autoprefixer back when we were supporting all the way back to IE10 on our websites.

When I went back to school for a BS CS, I downloaded CLion expecting as-good support for C++ (our curriculum's language) as PHPStorm had for PHP. I was a little disappointed, but from what I hear CLion is much better now (with the Nova engine). On another note, JetBrains threatened to suspend my account when they saw me using an educational CLion license on the same account as my corporate PHPStorm license... Explained my way out of it (as I was using the licenses correctly / following EULA) but it was a sour moment, especially considering they recommended people join all of their licenses (personal & professional) under one account [2].

Regarding CoPilot: I haven't used it and probably won't, unless they add truthiness to LLMs. I've found that actually typing my code is rarely the bottleneck, and sparing myself from typing is the "value add" most coding LLMs offer.

[0]: https://www.zend.com/products/zend-studio

[1]: https://www.zend.com/products/zend-server/ibmi

[2]: https://sales.jetbrains.com/hc/en-gb/articles/208460135-Can-...

One. Letter. At. A. Time.

Yes, I code in Rust and I don't use a LSP or Rust analyzer.

I write code. I mostly remember things but I check the documentation often.

Docs.rs is always open.

Then I compile it and fix the compiler errors. The Rust compiler errors are very nice and friendly. So it's not that difficult.

I mean that's how C and C++ programmers worked for many many years.

I use vim on the command line, and screen to switch between terminal and vim. vim does have autocomplete, but it doesn't pull names from the entire codebase, just from the current files open.

I don't remember every type and field in the codebase--I have to familiarize myself with them when I work with them, just like you do--and if you don't familiarize yourself with your types, the IDE telling you what your type is, isn't going to be particularly elucidating. With good code, it's usually pretty clear what the type of a variable or field is, even if the type definition isn't in your current viewport. If that's not the case, your code is likely overcomplicated, and needs a refactor. If there's too much inherent complexity in the problem to allow for that, then you've no choice but to keep a whiteboard handy to sketch stuff out--that's much easier and more useful than anything an IDE does to trace complexity.

Go-to-definition lets you lose track of the big picture, because you don't have to have a working knowledge of your project's file structure to work around it. The result is often multiple definitions of the same thing with loose translation layers between them which people don't really touch often enough to feel obvious pain from, so they end up just sitting there hurting performance and introducing subtle bugs whenever adjacent code changes. I've worked on a few Java/C# codebases like this.

It's really important to me to read and understand all the code around what I'm modifying before I make a modification, so I can make exactly the change I want to make and nothing more.

Workflow: Make sure you are on the same page as product with what the feature is, asking any questions you can think of. Write an integration test, if possible (it isn't always). If not, write a test case for manual testing (it's better if you can get the testers to do this, and even better if you can do it with them). Get an architecture in my head, or draw one on a whiteboard if it doesn't fit in my head. Visualise the "flow" of data through the different units, and what needs to change--if the feature is complicated, write this down so you don't have to start from scratch figuring it out tomorrow. Start at the beginning of that flow and write a unit test, then implement it, cycling through unit test and implementation in a circle until each unit change is implemented. Then run the integration test and manual test. Take a step back and see if there's anything you missed. Deliver it to product/testing.

SIDE NOTE: An underestimated attribute of using command line editors of olde is that they basically don't change. Yes, Vim is under development still, but the new features don't matter to me, because I don't track them and don't know what they are. All of the things I have ever done with Vim, Vim still does exactly the same way it did when I started using Vim.

I'm too out of touch with the IDE world to be sure they all have this problem, but at least the ones I used BITD would make changes that forced me to re-learn how to do things I already knew how to do before the change. I'm not against doing this entirely, but it needs to be done a lot more judiciously than most higher level tools do it. Code editing simply isn't an area where there are fast advances being made, so if your editor is making large changes, they are probably not advances, they're just causing you problems.

Eh, it comes down to a combination of putting time and effort into mastering the tools of your craft and having docs open on a 2nd monitor as needed. Put in enough reps and you just organically memorize huge chunks of language/framework details. As for finding function declarations on the fly, have grep will travel.

please tell me this is bait

> autocomplete

is rarely useful to me, I just type things out.

I'm just quicker this way. By that I mean that my stream of thought just flows, when thinking about autocompletion is like in another "brain space" which makes my mind stutter.

I don't know if I'm wall-clock quicker for real, especially as I'm not that fast a typer (certainly not as fast as I want to be) but the mental exercise is annoying enough that I prefer the smooth tarmac of typing it all vs the pebbled trail of jumping back and forth between thinking about the output of typing and autocompleting.

If some autocomplete produces a dropdown list the thing it does help me is a quick feedback as to whether I made a typo, but I basically never tab the autocompletion out.

Only time I do tab out autocompletions is on the shell, and mostly only for paths.

> language servers

I do kind of see the appeal e.g VScode's invoking this inline view of a method implementation right at the call site. In practice I never use it.

Another one is inlay hints in Vim, e.g with type information for dynamic languages (e.g Ruby when using RBS) or to correctly feed autocompletion.

What I don't like is how heavyweight LSPs "feel".

> and recently copilot

I tried Copilot a few times and it was a) slow and b) mediocre.

Slow is stupendously because it feels like I'm driving an autobahn, except littered with 10kph roadbumps.

Mediocre as it sometimes produces code that works, but most of the time is either wrong or flat out doesn't work; even for boilerplate its output is bad/inconsistent with the codebase/outright incorrect. So every time I have to enter a "review mode" state of mind and fix the damn thing, which ends up being slower than just fully typing the thing out in the first place.

> go-to-definition

:sp <leader>p lib/whatevs (backed by fzf) then /thething because codebases I work on are typically organised sensibly.

Or I just open a new tab and rg thething then vim thepath +:42

Unix as IDE is stupidly fast and powerfully flexible for me.

> Do you just remember every type and field in a codebase

Mostly, not everything but I do have a mental map to find things quickly with the above.

Rereading the above, I realise that maybe the takeaway is that I'm a "fixes radios by thinking" type of person, which means huge mental models and map of everything fit in my mind, then I reason it out and come up with a solution in my mind, and I just need to type it out as a final step in a sort of stream of thought way, so anything that gets between the mind and the characters appearing on screen is a major drag.

I don't think it is any worse or better than an IDE, it's just the way I work, and I've seen some people do crazy stuff crazy fast with IDEs/LSPs/LLMs just as well. It's just not my way of operation.

I've set up LSP a couple of times, but not been wowed yet. Didn't feel like it added much value. It's on my TODO to do in again, though.

For your question about go to definition: not like it takes much time to open a file and search. Yes, of course objectively it takes longer, but I don't feel like my coding speed is limited by my typing speed. (a mouse is not involved when opening a new file)

I mean to set up LSP again because it has to be better. But in the past, when it's broken or I code on a different machine I've found that I don't miss it, or even necessarily notice it being gone.

Editors have had go-to-definition a decade or two before lsp.

I usually use Python in medium-size projects and remember the types for a couple of files at least. It’s almost always one of the top five builtins or a custom class I wrote or modified. If in doubt I click on the word and it highlights everywhere. Usually obvious what it is by context.

[dead]

If your work is building Technology and you have a mental model such as: “it was better when it was worse”

You don’t understand the essence of your job.