Command to Link Current Tab with Prompted Tab

Use case or problem

Link with Tab option should be accessible to mouseless users.
Currently, the user must do one of the following to get two tabs linked:

  1. (3 Clicks) Right click a tab, and select Link with Tab, and the select the tab to be linked with.
  2. (1 Click) ⌘-Click the View Toggle

Proposed solution

A command should be added called Link Current Tab to Prompted Tab. When this command is run, the current tab is highlighted, and keys can be used to select the desired Tab for linking:

  • Use ←↓↑→ (Arrow Keys) to highlight adjacent tab groups
  • Use β‡₯ (Tab) to cycle through tabs within group
  • Use ⇧β‡₯ (Shift+Tab) to cycle backwards within group
  • Use βŒ… (Enter) to select the highlighted tab for linking

Current workaround (optional)

I just don’t even use tabs because of this; I keep one tab in two panes always linked, and I am forced to open all files in that single pair of tabs. If those close, my backup is a plugin called obsidian-auto-split. It allows me to open files in linked split view when the workspace is empty. This means the plugin has a process for linking two panes together, but does not provide a command.
Still not what I would call accessible. Mouseless users deserve full support.

5 Likes

I would like to see this feature as well. Personally I believe that any action that can be done from the mouse should also be done from the keyboard. Obsidian having such a large array of keyboard features is one (of many) things that has made me gravitate towards the app

Vote + 1 for a keyboard option

1 Like

Even though I never used typescript, I felt determined and dumb enough to use AI to throw a plugin together.
So that it doesn’t get lost, here is the main.ts that I got to work:

import { App, Plugin, PluginSettingTab, Setting, TFile, Notice, FuzzySuggestModal } from 'obsidian';

class LeafSuggestModal extends FuzzySuggestModal<string> {
    private leaves: Array<string>;
    private onSelect: (selectedIndex: number) => void;

    constructor(app: App, leaves: Array<string>, onSelect: (selectedIndex: number) => void) {
        super(app);
        this.leaves = leaves;
        this.onSelect = onSelect;
    }

    getItems(): string[] {
        return this.leaves;
    }

    getItemText(item: string): string {
        return item;
    }

    onChooseItem(item: string, evt: MouseEvent | KeyboardEvent) {
        const index = this.leaves.indexOf(item);
        if (index !== -1) {
            this.onSelect(index);
        }
    }
}

export default class SetGroupMemberPlugin extends Plugin {
    async onload() {
        // Register the command in the command palette
        this.addCommand({
            id: 'set-group-member',
            name: 'Set Group Member',
            callback: () => this.setGroupMember(),
        });
    }

    setGroupMember() {
        const leaves = this.app.workspace.getLeavesOfType('markdown');
        if (leaves.length < 2) {
            new Notice('There must be at least two tabs open to set a group member.');
            return;
        }

        const currentLeaf = this.app.workspace.activeLeaf;
        const filteredLeaves = leaves.filter(leaf => leaf !== currentLeaf);
        const leafNames = filteredLeaves.map((leaf, index) => `${index + 1}: ${leaf.view.getDisplayText()}`);

        if (filteredLeaves.length === 1 && filteredLeaves[0].view.getDisplayText() === currentLeaf.view.getDisplayText()) {
            currentLeaf.setGroupMember(filteredLeaves[0]);
            new Notice('Automatically set group member to the only available tab.');
            return;
        }
        
        new LeafSuggestModal(this.app, leafNames, (selectedIndex) => {
            currentLeaf.setGroupMember(filteredLeaves[selectedIndex]);
            new Notice(`Set group member to tab ${selectedIndex + 1}`);
        }).open();
    }
}