Short and practical: I rely on vim-sleuth to auto-detect indentation settings, nvim-treesitter for syntax-aware indentation, and a formatter integration (null-ls, neoformat, or coc.nvim with prettier/clang-format/shfmt) to normalize code on save. Add editorconfig-vim so project-level rules are respected, and use indent-blankline.nvim to visualize problems.
A quick tip from my messy commit history: enable filetype plugin indent on, set autoindent, and add an autocmd to run the formatter before write. That combo reduces whitespace churn in diffs and keeps my collaborators happy — and me, too.
Will
2025-09-06 05:40:38
If I had to pick three things to improve Vim's auto-indent fast, I'd choose vim-sleuth, nvim-treesitter (or vim-treesitter), and a formatter integration like neoformat/null-ls/coc.nvim. vim-sleuth figures out whether a file uses tabs or spaces and what shiftwidth to use — it removes the most annoying mismatch issues. nvim-treesitter provides syntax-aware indentation that beats most built-in scripts, especially for modern JS/TS, Python, and Rust. Finally, formatters (prettier, clang-format, shfmt, rustfmt) applied via neoformat or null-ls ensure the file is consistently formatted on save.
A couple quick config notes: enable filetype plugin indent on, set sensible fallbacks (autoindent, smartindent), and add an autocmd to format before save for languages where a formatter exists. I also keep editorconfig-vim so project rules are enforced. These layers together make indentation feel like it finally knows what it’s doing.
Kevin
2025-09-08 21:17:10
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.
Quinn
2025-09-10 07:00:53
Troubleshooting flow I use: detect, apply language-aware rules, then normalize. First I let vim-sleuth or indent-o-matic inspect the file to set tabstop/shiftwidth/softtabstop/expandtab automatically — that cures most whitespace noise. If indentation still looks off, I enable a syntax-aware indenter: nvim-treesitter's indent module for Neovim (or the best filetype-specific indent scripts) often fixes nested constructs where regex rules fail.
Next, I hook up a formatting pipeline. null-ls or neoformat (or ale/coc integrations) will run external tools like prettier, clang-format, shfmt, or rustfmt which are authoritative for that language. I usually add an autocmd BufWritePre to format on save so I don't have to think about it. Visual helpers like indent-blankline.nvim or indentLine are great for spotting where logic and indentation disagree. If a particular filetype keeps breaking, I look for a dedicated indent script in plugin collections like vim-polyglot or the repo for that language — often there’s a small tweak that makes everything click.
They were brothers, one touched my heart, the other ruined it.
Ken was safe, soft, and everything I should want.
Ruben was cold, cruel… and everything I couldn’t resist.
One forbidden night, one heated mistake... and now he owns more than my body he owns my silence.
And now Daphne, their sister,the only one who truly knew me, my forever was slipping away.
I thought, I knew what love meant, until both of them wanted me.
Life has a way of awakening us…Often cruelly. Astraia Ilithyia, a humble art gallery hostess, finds herself pulled into a world she never would’ve imagined existed. She meets the mysterious and charismatic, Vasilios Barzilai under terrifying circumstances. Torn between the world she’s always known, and the world Vasilios reigns in…Only one thing is certain; she cannot survive without him.
At the age of twenty, I mated to my father's best friend, Lucian, the Alpha of Silverfang Pack despite our age difference.
He was eight years older than me and was known in the pack as the cold-hearted King of Hell. He was ruthless in the pack and never got close to any she-wolves, but he was extremely gentle and sweet towards me.
He would buy me the priceless Fangborn necklace the next day just because I casually said, "It looks good."
When I curled up in bed in pain during my period, he would put aside Alpha councils and personally make pain suppressant for me, coaxing me to drink spoonful by spoonful.
He would hug me tight when we mated, calling me "sweetheart" in a low and hoarse voice. He claimed I was so alluring that my body had him utterly addicted as if every curve were a narcotic he couldn't quit.
He even named his most valuable antique Stormwolf Armour "For Elise".
For years, I had believed it was to commemorate the melody I had played at the piano on our first encounter—the very tune that had sparked our love story.
Until that day, I found an old photo album in his study.
The album was full of photos of the same she-wolf. You wouldn’t believe this, but we looked like twin sisters! The she-wolf in one of the photos was playing the piano and smiling brightly.
The back of the photo said,
"For Elise."
...
After discovering the truth, I immediately drafted a severance agreement to sever our mate bond.
Since Lucian only cared about Elise, no way in hell I would be your Luna Alice anymore.
Deena Wellington was promised a lifetime when she married Trenton Outlaw—a man who was out of her league—but she was thrown away to make some room for his new girl, Sandra Pattinson.
She was a rising star in the entertainment industry, but she lost her projects and endorsements because of the divorce, and if that wasn't enough, she found out not long after that her mother had cancer and needed immediate treatment.
When she thought all was lost, she heard about Ex-Factor, a reality show where a divorced couple can join and win three million dollars and it was more than enough to cover her mother's treatment!
Swallowing her pride, she asked Trent to join the show with her and fake a reunion to win, but she wasn't prepared to see Ethan, her ex-boyfriend and first love who was also a participant.
With two exes joining her, who will Deena reunite with?
Caregiving for her feeble and stupid twin sister became Minty Brown's responsibility. She needed to feel that temporal security to survive, so she adopted three aliases. She never desired commotion. She desired a simple, tranquil life, but when she was forced to choose between two alphas who were vying to be her mate and learned that one of her relatives was responsible for her parents' passing, her drama couldn't have been less dramatic.
"You are a wild and wacky girl. As you are aware. Did your alpha boyfriend set you up for this, or are you just looking to whore off on your own without me around?"
He laughed hysterically and added,
"I should've been aware. You didn't desire a partner. What a fool I am. Why did I think you would be open to visiting me? You are nothing more than a whore in the arms of a wolf alpha who wouldn't even look at you."
Note: This book is still being edited.
When Carina finds her boyfriend making out with the most popular girl in school, she feels like her whole life is about to crumble, most especially when he reveals that he only dated her because of a bet.
But her mom suddenly calls her, telling her she would be returning to the pack with her new husband whom she got married to outside the state.
Carina is eager to meet her dad, only to find out he is the father of the three triplet boys who constantly bullied her in school.
When she finds out she is mated to them, she knows her life is about to change for the worse and she sure wasn’t wrong. The boys make sure to torture her until she says enough is enough and now they regret their actions and want to treat her right.
Will Carina give them a chance?
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.
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.
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.
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.
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.
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.
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.
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