fix(completion): insert fpath before compinit in .zshrc
The postinstall script was appending the fpath line at the end of .zshrc, but compinit (called earlier by oh-my-zsh or directly) would have already finished scanning. This caused zsh completion to silently fail for most users. Now the script detects the first compinit / oh-my-zsh source line and inserts the fpath entry before it, ensuring completion works immediately.
This commit is contained in:
1 parent
eb2c3fdf89
commit
8263a06a85
1 file changed
+29
-8
+29
-8
@@ -70,30 +70,51 @@ function ensureDir(dir) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Ensure fpath contains the custom completions directory in .zshrc
|
* Ensure fpath contains the custom completions directory in .zshrc.
|
||||||
|
*
|
||||||
|
* Key detail: the fpath line MUST appear BEFORE the first `compinit` call,
|
||||||
|
* otherwise compinit won't scan our completions directory. This is critical
|
||||||
|
* for oh-my-zsh users (source $ZSH/oh-my-zsh.sh calls compinit internally).
|
||||||
*/
|
*/
|
||||||
function ensureZshFpath(completionsDir, zshrcPath) {
|
function ensureZshFpath(completionsDir, zshrcPath) {
|
||||||
const fpathLine = `fpath=(${completionsDir} $fpath)`;
|
const fpathLine = `fpath=(${completionsDir} $fpath)`;
|
||||||
const autoloadLine = `autoload -Uz compinit && compinit`;
|
const autoloadLine = `autoload -Uz compinit && compinit`;
|
||||||
|
const marker = '# opencli completion';
|
||||||
|
|
||||||
if (!existsSync(zshrcPath)) {
|
if (!existsSync(zshrcPath)) {
|
||||||
writeFileSync(zshrcPath, `${fpathLine}\n${autoloadLine}\n`, 'utf8');
|
writeFileSync(zshrcPath, `${marker}\n${fpathLine}\n${autoloadLine}\n`, 'utf8');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const content = readFileSync(zshrcPath, 'utf8');
|
const content = readFileSync(zshrcPath, 'utf8');
|
||||||
|
|
||||||
// Check if completions dir is already in fpath
|
// Already configured — nothing to do
|
||||||
if (content.includes(completionsDir)) {
|
if (content.includes(completionsDir)) {
|
||||||
return; // already configured
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Append fpath configuration
|
// Find the first line that triggers compinit (direct call or oh-my-zsh source)
|
||||||
let addition = `\n# opencli completion\n${fpathLine}\n`;
|
const lines = content.split('\n');
|
||||||
if (!content.includes('compinit')) {
|
let insertIdx = -1;
|
||||||
addition += `${autoloadLine}\n`;
|
for (let i = 0; i < lines.length; i++) {
|
||||||
|
const trimmed = lines[i].trim();
|
||||||
|
// Skip comment-only lines
|
||||||
|
if (trimmed.startsWith('#')) continue;
|
||||||
|
if (/compinit/.test(trimmed) || /source\s+.*oh-my-zsh\.sh/.test(trimmed)) {
|
||||||
|
insertIdx = i;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (insertIdx !== -1) {
|
||||||
|
// Insert fpath BEFORE the compinit / oh-my-zsh source line
|
||||||
|
lines.splice(insertIdx, 0, marker, fpathLine);
|
||||||
|
writeFileSync(zshrcPath, lines.join('\n'), 'utf8');
|
||||||
|
} else {
|
||||||
|
// No compinit found — append fpath + compinit at the end
|
||||||
|
let addition = `\n${marker}\n${fpathLine}\n${autoloadLine}\n`;
|
||||||
appendFileSync(zshrcPath, addition, 'utf8');
|
appendFileSync(zshrcPath, addition, 'utf8');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ── Main ───────────────────────────────────────────────────────────────────
|
// ── Main ───────────────────────────────────────────────────────────────────
|
||||||
|
|||||||
Reference in new issue
Block a user