Quick checklist for when auto-indent stops after editing your vimrc: first, check whether filetype detection is active with :set filetype? and enable it with :filetype plugin indent on if needed. Second, verify that 'paste' isn’t on (:set paste?), because paste mode disables auto-indenting. Third, run :verbose set autoindent to see which script last modified that option. Fourth, start Vim with -u NONE to isolate plugins/config. Also look for errors during sourcing (:source ~/.vimrc and then :messages) — an early error can abort the rest of the file. If you want a fast fix, comment out recent changes and reintroduce them line-by-line until the behavior returns; that usually nails the culprit.
If indentation stopped after editing your vimrc, my brain goes to order and scope issues. A few quick checks: make sure you didn’t accidentally put 'set paste' or 'set noautoindent' in the file, and verify that 'filetype indent on' is present if you rely on filetype-specific indent scripts. Also, the sequence matters sometimes — if you enable filetype detection but then later a plugin overwrites indent settings, you’ll see nothing working.
I also look for typos or unescaped characters that might stop sourcing (use :source and watch :messages). If you use a plugin manager, ensure that indentation-related plugin files aren’t being loaded before the option that enables filetype-specific indenting. Tip: :verbose set autoindent and :scriptnames will tell you where a setting was last changed. Lastly, remember Neovim uses init.vim/init.lua in a different path — make sure you edited the right config file.
One evening I broke my own indentation with a stray line and it took me a while to spot it — so sharing that little debugging ritual I now run: open the troubled file and immediately check :echo &filetype and then :verbose set autoindent. If filetype is empty, Vim won’t apply language-specific indent rules, and if :verbose points to a plugin or vimrc line turning off autoindent, you’ve found the smoke.
I keep a short checklist: start Vim without my rc (vim -u NONE) to see if core Vim indents correctly; source my vimrc manually to catch errors; inspect :scriptnames to find third-party ftplugins/indent files; and check for 'set paste' or mappings that toggle paste (F2 in many configs). Also inspect buffer-local settings with :setlocal — sometimes ftplugin scripts set local options that override globals. If indent still fails, I compare shiftwidth, tabstop, and expandtab values; mismatched widths can look like broken indent when it’s just width settings. When in doubt I temporarily rename my vimrc and reintroduce sections until the problem reappears, which narrows down the piece that caused it.
Man, that frustration is so real — I’ve been there. First thing I do is check whether vim even thinks it should indent: open the file and run :set filetype? and :verbose set autoindent. If filetype is empty or wrong, indent scripts won’t run. If :verbose shows autoindent being turned off by some script, that points to the culprit.
Next, consider obvious toggles that silently kill indentation: if you’ve got 'set paste' enabled (or you toggled paste mode earlier with a mapping), indentation won’t behave. Also check whether you disabled 'autoindent', 'smartindent', or 'cindent' by mistake. Use :set paste? and :set autoindent? to inspect current state.
If those look fine, source your vimrc manually (:source ~/.vimrc) and watch :messages for errors — a syntax error early in the file can stop the rest of the config from loading, so later indent settings never get applied. Also run vim -u NONE (or nvim -u NORC) to see if a vanilla session indents correctly; if it does, a plugin or a line in your vimrc is to blame. Useful commands: :scriptnames (shows loaded scripts), :verbose set shiftwidth? tabstop? expandtab? and checking ~/.vim/indent or plugin ftplugin files for overrides. If you want, paste the problematic snippet and I’ll poke at it with you.
2025-09-10 17:07:36
15
View All Answers
Scan code to download App
Related Books
I Sent My Cheating AI Incubus to the Scrapyard
Reneemoon
3
1.2K
I always had a weakness for handsome men, so I camped out online to grab one of the very first AI incubi.
The brand's whole pitch was seduction tuned a hundred percent to its owner's taste. But every time I got within ten minutes of Lucien Crane, he'd force-start a system cleaning cycle, go dark, and idle out.
"Master, please don't overuse me. Bacteria buildup can cause a malfunction."
Left unsatisfied every single time, I finally went to customer service, and the rep looked as baffled as I felt.
"An incubus unit would never break off contact with its owner. We'd recommend restarting him at home."
But on the drive back, I happened to scroll past a livestream from my live-in housekeeper. The title sat right there in bold: How a Seasoned Queen Subdues In Her AI Incubus.
The lighting was low. The man's earlobes were flushed, and he knelt on one knee, every inch of bared skin crossed with messy whip marks.
My housekeeper wiggled her red-painted toes, all smiles.
"This one's got real stamina. Five hours straight and he never once tapped out."
As the comments poured in, envious, a chill ran through me.
So the so-called "cleaning system" was just his excuse to slack off and idle.
Behind my back, he was happily playing somebody else's obedient little sub.
If he wouldn't serve me the way he was built to, then he could wait to get shipped back to the factory and scrapped for parts.
The newly hired genius programmer was a proud woman who always thought she could turn the entire industry on its head.
When an investor tried to pressure her into drinking, she flipped the table and slapped him across the face.
"My worth is in my programming skills, not my ability to network. Asking me to drink with you is an insult."
Enraged, Clint Warner immediately withdrew the eighty-million investment agreement. He even swore he would never work with us again.
As the Head of Product, I scrambled to apologize. The situation was only salvaged after I drank so much that I ended up hospitalized.
…
Later, I complained to the boss and demanded that he discipline the new hire. To my shock, he dismissed the matter.
"If the employee causes any problem, it's because the supervisor failed in their duty. The promised million-dollar dividend bonus is cancelled. Take this as your warning."
Fed up, I wrote down Mary Hansen's name on the Counseling-Out List.
She couldn't care less.
"I have abilities you’ll never match, unlike a scheming bootlicker like you. If anyone tries to go after me, the project will be halted. Don't come crying to me when everything collapses."
I did not argue with her then. However, when the Counseling-Out List was announced, I found my own name on it.
The boss claimed it was a mistake to force me to leave. Then he promoted Mary to my position and even granted her the authority of a vice president.
"You were only great because of the company's support. Mary's not the same. She's young and truly talented. She’ll lead us to greater heights."
With a cold smirk on my face, I made my way to our competitor, taking the crucial piece of our company's technology with me.
I was in the office bathroom stall when I heard them trash-talking me.
The intern I'd trained for three months whined, "She's a heartless witch—like a robot with zero brain cells."
I was about to swing the door open when another voice jumped in, laughing.
"Documents incomplete."
"Receipts don't match."
"No signature? Denied."
"Seriously, we've all memorized the freaking rulebot's script!"
Once they were gone, I headed back to my desk.
The intern stormed in and slammed a fat stack of reimbursement forms in front of me.
"Don't go on another power trip and block everyone's claims."
I skimmed the obviously fake receipts. Normally, I'd tear into her.
But this time, I just smiled.
"My head's killing me. Can't read the fine print."
The HR manager slid a severance agreement across the table and said coldly, "You're fired."
I froze. "Why?"
Just one week ago, my boss had praised me in the company meeting and called me one of the team's most valuable people.
The HR manager shrugged. "Ms. Lyttle, you're already 35. You don't have the energy of younger employees anymore, and you're not what you used to be. You no longer fit the company's future."
I joined this company when I was 29. Over the past six years, I wrote countless lines of code and worked through more sleepless nights than I could remember.
Every time the company faced a major system failure, I led the emergency response and saved it from catastrophic losses. And now they were telling me I was too old and too slow.
I laughed in disbelief. "So you've already copied all my experience and skills into an AI, haven't you?"
The HR manager paused for a moment before answering confidently, "AI never gets tired, never takes time off, and never asks for a raise. Once the company has an employee like that, why would we keep you?"
I looked at her. "Are you sure the AI has learned everything I know?"
She smiled. "Absolutely."
The moment I heard that, I finally relaxed.
Long ago, I had already hidden a trap inside my code to keep my skills from being copied.
The moment their AI employee went live, the company would only have three days before everything fell apart.
I made a name for myself in my previous life, thanks to the National Robotics Competition. But after that event, someone accused me of stealing my sister's true love's work.
My own sister defended her true love and showed the world the complete code for the program.
The Internet went into a frenzy. They came after me, out for my blood. My own parents told me to kill myself.
I came down with depression eventually, and my family sent me to a mental asylum. I died there, after suffering severe abuse.
When my eyes snapped open again, I was taken back to the day before I joined the competition. I made a different decision this time. I told everyone I wasn't taking part in this competition, and it made everyone panic.
Even though it's the New Year holidays, I'm still cooped up in the company while churning out the paperwork needed for the company's listing process.
That's when my keyboard suddenly types a paragraph on its own.
"Stop working already! Your boss is about to fire you, and yet you're still slaving away for his sake!"
I'm stunned by the information I see. The keyboard goes on typing, "He said you only have a bachelor's degree. If not for the fact that you're a walking lucky charm, you wouldn't have gotten into this company in the first place!
"Now that the company is in the process of getting listed, it's costing far too much just to keep you around! Even though you're being paid a high salary every month, you can't even provide the company with any value!
"He intends to dismiss you the moment the company gets listed! Since it's the new year, new blood should be joining the company!"
I've been holding my coffee mug the whole time. At that moment, I can feel my hands starting to tremble.
For five years, the projects that I've manned never got into any problems. The final round of funding always came through. Even when we were choosing a new office, we came across the situation of an owner who was all-too happy to get rid of the building.
I can say with great confidence that I'm 90% of the main reason how this company expanded from a tiny office to the entire building. To think that I'm the first person to be discarded right after my boss reaches his goal…
I can feel my stomach twisting uneasily. Even my throat goes tight from the anxiety.
Just as I'm about to leave, a few angry voices ring out in the office.
"I'm an office chair! I'll break during the board meeting tomorrow and make sure that your boss falls right on his ass!"
"I'm a printer! I'll make sure to print all the documents he wants with nothing but gibberish on them!"
"I'm a coffee machine! Tomorrow, I'll whip him a special brew that ensures he will never get to leave the toilet bowl for the rest of the day!"
Okay — let me walk you through this like we’re debugging a stubborn editor together. In my experience inconsistent Vim indentation across buffers usually comes down to a few culprits: buffer-local options, filetype-specific plugins, modelines in files, or external tools like an .editorconfig plugin.
First, check what each buffer actually has set. Use :setlocal and :verbose set shiftwidth? tabstop? softtabstop? expandtab? and :set filetype? and :verbose set autoindent? — the verbose form tells you where a setting was last changed. If you see different values between buffers, that’s your clue: something is changing options per file. Often a ftplugin or indent script is overriding global settings, or a modeline inside a file is setting tabs/spaces.
To fix it, pick a consistent baseline in your vimrc/init.vim: filetype plugin indent on (or in Neovim, enable filetype and indentation early), then set sensible defaults like set tabstop=4 shiftwidth=4 softtabstop=4 expandtab or use set noexpandtab for projects that prefer tabs. If a project has specific rules, add an .editorconfig file and install the editorconfig plugin or add autocmds to apply per-filetype settings. When you need to find the source of an override, :scriptnames shows loaded scripts and :verbose set
Honestly, getting Python auto-indent working in vim is one of those tiny victories that makes editing a joy. My go-to is to enable vim's filetype detection and then set sensible Python indentation rules in my config. Add these lines to your ~/.vimrc or init.vim for Neovim:
filetype plugin indent on
set autoindent
set expandtab
set shiftwidth=4
set softtabstop=4
set tabstop=4
The first line turns on filetype-specific plugins and indent scripts (this loads vim's python indent file). The rest make tabs into spaces and use four spaces per indent, which is the common Python convention. If you want the setting to apply only to Python buffers, drop the global lines into ~/.vim/ftplugin/python.vim and use setlocal instead of set.
If indentation still feels off, check the buffer's filetype with :set filetype? and inspect loaded scripts with :scriptnames. I sometimes install a plugin like 'vim-python-pep8-indent' or use external formatters like 'black' called via a formatter plugin to normalize whitespace. Try opening a .py and typing an indented block — it should behave. If not, tell me what output :set filetype? and :verbose set shiftwidth? give and we can debug further.
Okay, here's a practical and friendly way I handle Vim's auto-indent when I need it out of the way for a few moments.
If I just want to paste something without Vim reformatting it, I usually toggle paste mode: :set paste to turn it on, paste the text, then :set nopaste to go back. I often map a key for that so it’s painless, for example :set pastetoggle= or put in my config nnoremap :set paste! to flip it. Paste mode stops auto-indent, indentexpr, and other niceties, so your pasted code won't get mangled.
If I need to disable automatic indentation for editing (not just pasting), I prefer buffer-local switches so I don’t mess with other files: :setlocal noautoindent nosmartindent nocindent and, if needed, :setlocal indentexpr= to clear any expression-based indent. To restore, use :setlocal autoindent smartindent cindent or reopen the buffer. Little tip: :set paste? shows whether paste is on. Personally, I use paste for quick fixes and :setlocal for longer edits — keeps things predictable and quiet during a frantic refactor.
If you're fiddling with Vim's indentation and want precise control, the trio I reach for is :set shiftwidth, :set tabstop, and :set softtabstop.
shiftwidth (sw) controls how many spaces a single indentation level uses for operations like >>, <<, and automatic indentation. I usually do :setlocal shiftwidth=4 for projects that use four-space indents. tabstop (ts) sets how many spaces a literal TAB character displays as; use :set tabstop=4 to make existing tabs line up visually with your intended width. softtabstop (sts) affects insert-mode behavior: :set softtabstop=4 makes pressing Backspace or Tab behave like you're working with 4-space logical tabs even if actual file uses tabs.
A couple of other practical commands I keep in my .vimrc: :set expandtab to insert spaces instead of real tabs (or :set noexpandtab to keep tabs), :set autoindent to keep the previous line's indentation, and :set cindent or :set smartindent for C-like auto-indenting. If you want the changes to apply only to the current buffer, use :setlocal sw=2 ts=2 sts=2. To reformat an entire file after changing settings, I often run gg=G to reindent the whole buffer, or :retab to convert tabs to spaces (or the reverse with :retab!). These little tweaks saved me hours when I was switching between Python, Makefiles, and Go projects.
I'll be blunt: yes, you absolutely can set up Vim to auto-indent differently per project directory, and I've done it a bunch of times across projects with different coding styles.
When I need a project-specific policy I usually pick one of three safe routes: use a repository-level '.editorconfig' with the EditorConfig Vim plugin (works across editors and is a huge life-saver), add per-project autocommands in my global vimrc that match the project path, or—if I must—use a controlled local vimrc mechanism (with security checks). For example, in your main vimrc you can add an autocmd that applies settings only when the buffer lives under a particular path:
augroup proj_indent
autocmd!
autocmd BufRead,BufNewFile /path/to/myproj/* setlocal shiftwidth=4 tabstop=4 expandtab
augroup END
That keeps the rules scoped to files under that directory. I avoid blindly enabling 'exrc' because executing arbitrary project .vimrc files can be risky; instead I either require a checked-in '.editorconfig' or use a trusted plugin like 'localvimrc' that prompts you before sourcing. Also remember to use setlocal so other projects aren’t affected. For Neovim, the same autocmds work, but I often detect the project root via an LSP/root_pattern helper and then apply settings dynamically. Overall, choose EditorConfig if you want a cross-editor approach, or autocommands if you prefer staying purely in Vim land.
If you've ever opened a file that looks like a bento box of tabs and spaces, Vim's auto-indent behavior is surprisingly predictable once you know the pieces involved.
Auto-indent (the basic 'autoindent' option) simply copies the leading characters from the previous line — literally. That means if the previous line starts with a tab, then two spaces, Vim will start the new line with that exact sequence. Nothing clever, just a straightforward copy. Where things get interesting is when you press Tab or when you run reindent commands: Tab insertion is governed by 'expandtab' and 'softtabstop'. If 'expandtab' is set, inserting a tab character from Insert mode actually inserts spaces. If it's unset, Vim inserts a real tab character, and 'softtabstop' affects how many spaces the Tab key represents while editing.
Reformatting with commands like '=' or using cindent/smartindent is different: Vim computes the desired indentation in columns based on 'shiftwidth' and the language indent rules, then writes the indentation according to your tab settings (usually honoring 'expandtab' to decide whether to use spaces, or using tabs where possible when it's unset). Practical tips: use ':set list' to reveal hidden whitespace, ':set tabstop=4 shiftwidth=4 softtabstop=4', ':set expandtab' to normalize new indentation to spaces, and ':retab' to convert existing characters if you want to clean the file up.
Okay, I’ll gush a bit: if you want auto-indent to actually behave instead of randomly guessing, start by combining a detector, a language-aware indenter, and a formatter. I like using vim-sleuth to sniff tabs vs spaces and shiftwidth automatically; it fixes half my headaches before I even open the file.
After sleuth, for Neovim I plug in nvim-treesitter with its indent module turned on — it understands syntax much better than old regex-based indent scripts. Pair that with either null-ls or coc.nvim (or ale if you prefer linters/formatters) to run real formatters like prettier, clang-format, shfmt, or rustfmt on save. That lets the language tools correct structural indentation rather than vim guessing.
Small extras that helped me: editorconfig-vim to respect project settings, indent-o-matic as a fallback detector in weird repos, and indent-blankline.nvim for visual guides so you can spot mistakes. Also don't forget filetype plugin indent on and sensible defaults (autoindent, smartindent/cindent where appropriate). With those layered, indentation accuracy improves dramatically and my diffs stop being a jungle of whitespace edits.
Okay, this is the hot take I give my friends when they ask how to stop JavaScript files from turning into a jagged mess: treat indentation as a filetype thing, not a global, and use 2 spaces plus an actual JS-aware indent engine. I usually put this in my vimrc (or better, in ftplugin/javascript.vim):
filetype plugin indent on
autocmd FileType javascript,typescript setlocal shiftwidth=2 softtabstop=2 tabstop=2 expandtab
autocmd FileType javascript,typescript setlocal autoindent smartindent
Those lines give you consistent 2-space soft tabs (the de facto style for many JS projects) and rely on Vim's smartindent for basic braces. But honestly, for real-world code with ES6/JSX/template literals, install a javascript-indent plugin (like the popular one that provides an indentexpr) and let it set indentexpr for you; it handles arrow functions, template literals and some weird edge cases better than plain smartindent. I also map = to re-indent visually: vmap = = or use gg=G to reformat a whole file.
Finally, I pair this with an on-save formatter — 'prettier' is my go-to — so even when teammates differ, my local formatting is predictable. If you want the exact plugin names or a sample ftplugin that runs Prettier on save, I can paste that too.
I've been using Vim for years, and autocomplete issues can be frustrating. The first thing I check is whether the plugin manager is set up correctly. If you're using Vim-plug, ensure the plugins are installed with ':PlugInstall'. Sometimes, the issue is with the filetype—autocomplete might not trigger if Vim doesn't recognize the file type. Run ':set filetype?' to check. If it's wrong, manually set it with ':set filetype=python' (or your language). Another common culprit is the omnifunc setting. Try ':set omnifunc?' to see if it's set. If not, install a language-specific plugin like 'YouCompleteMe' or 'coc.nvim' to handle autocomplete properly.
Also, check if the autocomplete feature is enabled in your vimrc. Some plugins require explicit activation. For instance, 'YouCompleteMe' needs 'let g:ycm_auto_trigger = 1'. If you're using 'coc.nvim', ensure the language server is installed and running. Run ':CocInfo' to verify. Lastly, outdated plugins can break functionality. Regularly update them with ':PlugUpdate' or your plugin manager's equivalent.
If you've ever opened a file in Vim and wondered why indentation behaves one way in one project and differently in another, the way filetype plugins and indent scripts interact is the usual culprit. In my messy but beloved setup I keep separate snippets in ~/.vim/ftplugin/ and ~/.vim/indent/ and they each have a job: ftplugin files generally set buffer-local editing options (things like shiftwidth, tabstop, expandtab, mappings) while indent scripts (under indent/) provide indentation logic by setting 'indentexpr', 'cindent', 'indentkeys', or related buffer-local options. Because these are buffer-local, whichever script writes a particular option last wins for that buffer.
Practically that means you can get conflicts. An ftplugin might set 'shiftwidth' to 4 for 'python' and an indent script might expect 2; or an indent script will set 'indentexpr' to a custom function that overrides simpler behaviors such as 'autoindent'. The usual fixes I use are: enable both with :filetype plugin indent on, then put overrides in after/ftplugin/ or after/indent/ so they load later; or explicitly set local options with setlocal in a ftplugin; or prevent an indent script with let b:did_indent = 1 if you deliberately want to skip it. For debugging, :scriptnames shows what got sourced, and :verbose setlocal shiftwidth? / :verbose setlocal indentexpr? tell you who last changed a setting. I like keeping ftplugin for styling and small mappings, and leaving indentation math to indent scripts — but I always keep an 'after' copy for those moments when I need the last word.