-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
add tabTracker, add JSDoc, organize and format the code (#17)
* add tabTracker, add JSDoc, organize and format the code, add info to changelog, increase the version to 1.1.2 * delete changelog, decrease the version to 1.1.1 * oj dylan dylan
- Loading branch information
Showing
4 changed files
with
180 additions
and
46 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,9 +1,17 @@ | ||
# Change Log | ||
Check [Keep a Changelog](http://keepachangelog.com/) for recommendations on how to structure this file. | ||
|
||
All notable changes to the "lru-tabs" extension will be documented in this file. | ||
## [1.1.2] - 2024-10-14 | ||
|
||
Check [Keep a Changelog](http://keepachangelog.com/) for recommendations on how to structure this file. | ||
### Added | ||
|
||
- Removing the least active tab based on the timestamp not order, | ||
|
||
## [1.1.1] - 2024-10-12 | ||
|
||
### Added | ||
|
||
- Option to disabled automatic tab sorting | ||
|
||
## [Unreleased] | ||
|
||
- Initial release | ||
- Initial release |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,19 +1,53 @@ | ||
import * as vscode from 'vscode'; | ||
import { removeLRUTabs, reorderTabs } from './functions'; | ||
import * as vscode from "vscode"; | ||
import { removeLRUTabs, reorderTabs } from "./functions"; | ||
import { tabTracker } from "./tabTracker"; | ||
|
||
/** | ||
* Activates the extension | ||
* @param {vscode.ExtensionContext} context - The context in which the extension runs | ||
*/ | ||
export function activate(context: vscode.ExtensionContext) { | ||
// Initialize tabTracker (this will set timestamps for existing tabs) | ||
tabTracker; | ||
|
||
// when a tab is changed or deselected | ||
let listener = vscode.window.onDidChangeActiveTextEditor(() => { | ||
const configuration = vscode.workspace.getConfiguration(); | ||
if(configuration.lrutabs.reorderTabs === true){ | ||
reorderTabs(vscode.window.tabGroups.activeTabGroup); | ||
} | ||
if(configuration.lrutabs.closeTabs === true){ | ||
removeLRUTabs(vscode.window.tabGroups.activeTabGroup, configuration.lrutabs.maxTabs || 7); | ||
} | ||
}); | ||
context.subscriptions.push(listener); | ||
/** | ||
* Event listener for changes in the active text editor | ||
* @type {vscode.Disposable} | ||
*/ | ||
let listener: vscode.Disposable = vscode.window.onDidChangeActiveTextEditor( | ||
(editor) => { | ||
const configuration = vscode.workspace.getConfiguration(); | ||
|
||
if (editor) { | ||
const activeTab = | ||
vscode.window.tabGroups.activeTabGroup.activeTab; | ||
if (activeTab) { | ||
// Update the timestamp for the newly active tab | ||
tabTracker.updateTimestamp(activeTab); | ||
} | ||
} | ||
|
||
// Reorder tabs if the configuration option is enabled | ||
if (configuration.lrutabs.reorderTabs === true) { | ||
reorderTabs(vscode.window.tabGroups.activeTabGroup); | ||
} | ||
|
||
// Close least recently used tabs if the configuration option is enabled | ||
if (configuration.lrutabs.closeTabs === true) { | ||
removeLRUTabs( | ||
vscode.window.tabGroups.activeTabGroup, | ||
configuration.lrutabs.maxTabs || 7 | ||
); | ||
} | ||
} | ||
); | ||
|
||
// Add the listener to the extension's subscriptions | ||
context.subscriptions.push(listener); | ||
} | ||
|
||
/** | ||
* Deactivates the extension | ||
* This function is empty as there's no cleanup required | ||
*/ | ||
export function deactivate() {} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,53 +1,75 @@ | ||
// this file defines the main functions of the extension | ||
import * as vscode from 'vscode'; | ||
import * as vscode from "vscode"; | ||
import { tabTracker } from "./tabTracker"; | ||
|
||
const getNumberOfTabs = (group: vscode.TabGroup): number => { | ||
return group.tabs.length; | ||
}; | ||
|
||
// reorder the tabs in a tab group based on the currently active tab. The most recently active tabs will be closest to the left | ||
// a separate copy of tabs is kept to track the order | ||
/** | ||
* Reorders the tabs in a tab group based on the currently active tab. | ||
* The most recently active tabs will be closest to the left. | ||
* | ||
* @param {vscode.TabGroup} group - The tab group to reorder | ||
*/ | ||
const reorderTabs = (group: vscode.TabGroup): void => { | ||
const activeTab = group.tabs.find(tab => tab.isActive); | ||
const numberOfPinnedTabs = group.tabs.filter(tab => tab.isPinned).length; | ||
// this occurs if there is no tab | ||
if(activeTab === undefined){ | ||
const activeTab = group.tabs.find((tab) => tab.isActive); | ||
const numberOfPinnedTabs = group.tabs.filter((tab) => tab.isPinned).length; | ||
|
||
// This occurs if there is no active tab | ||
if (activeTab === undefined) { | ||
return; | ||
} | ||
|
||
// don't touch pinned tabs | ||
if(activeTab.isPinned){ | ||
// Don't move pinned tabs | ||
if (activeTab.isPinned) { | ||
return; | ||
} | ||
const index = group.tabs.indexOf(activeTab); | ||
|
||
// check if tab is already in the correct position (this happens when it's called twice sometimes) | ||
var targetIndex = numberOfPinnedTabs; | ||
if(targetIndex === index){ | ||
// Check if tab is already in the correct position (this happens when it's called twice sometimes) | ||
if (numberOfPinnedTabs === index) { | ||
return; | ||
} | ||
// Move current tab position to the start, not before pinned tabs | ||
vscode.commands.executeCommand("moveActiveEditor", { | ||
to: "left", | ||
by: "tab", | ||
value: index - numberOfPinnedTabs, | ||
}); | ||
|
||
// move current tab position to the start, but not before pinned tabs | ||
vscode.commands.executeCommand('moveActiveEditor', { to: 'left', by: 'tab', value: index-numberOfPinnedTabs }); | ||
vscode.commands.executeCommand('workbench.action.unpinEditor'); | ||
vscode.commands.executeCommand("workbench.action.unpinEditor"); | ||
}; | ||
|
||
// remove least recently used tabs (but only if they aren't dirty and not pinned, we don't want to touch those dirty tabs otherwise we could get a disease right?) | ||
/** | ||
* Removes least recently used tabs, but only if they aren't dirty and not pinned. | ||
* We don't want to touch those dirty tabs otherwise we could get a disease, right? | ||
* | ||
* @param {vscode.TabGroup} group - The tab group to remove tabs from | ||
* @param {number} maxTabs - The maximum number of tabs to keep open | ||
*/ | ||
const removeLRUTabs = (group: vscode.TabGroup, maxTabs: number): void => { | ||
if(group.tabs.length <= maxTabs){ | ||
const tabsToClose: vscode.Tab[] = []; | ||
|
||
if (group.tabs.length <= maxTabs) { | ||
return; | ||
} | ||
|
||
const tabsToClose: vscode.Tab[] = []; | ||
group.tabs.slice(0).reverse().forEach(tab => { | ||
if(!tab.isDirty && !tab.isPinned && !tab.isPreview && (group.tabs.length - tabsToClose.length) > maxTabs){ | ||
tabsToClose.push(tab); | ||
} | ||
// Sort tabs based on their last active timestamp | ||
const sortedTabs = group.tabs.slice().sort((a, b) => { | ||
return tabTracker.getTimestamp(a) - tabTracker.getTimestamp(b); | ||
}); | ||
|
||
// actually close the tabs here | ||
tabsToClose.forEach(tab => vscode.window.tabGroups.close(tab)); | ||
sortedTabs.forEach((tab) => { | ||
// Don't close the active tab, dirty tabs, pinned tabs, or preview tabs | ||
if ( | ||
!tab.isActive && | ||
!tab.isDirty && | ||
!tab.isPinned && | ||
!tab.isPreview && | ||
group.tabs.length - tabsToClose.length > maxTabs | ||
) { | ||
tabsToClose.push(tab); | ||
} | ||
}); | ||
|
||
// Actually close the tabs here | ||
tabsToClose.forEach((tab) => vscode.window.tabGroups.close(tab)); | ||
}; | ||
|
||
export { reorderTabs, removeLRUTabs }; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
import * as vscode from "vscode"; | ||
|
||
/** | ||
* TabTracker class to manage timestamps for VSCode tabs | ||
*/ | ||
class TabTracker { | ||
/** | ||
* Map to store timestamps for each tab | ||
* @private | ||
*/ | ||
private tabTimestamps: Map<string, number> = new Map(); | ||
|
||
/** | ||
* Constructor for TabTracker | ||
* Initializes timestamps for existing tabs when the extension is activated | ||
*/ | ||
constructor() { | ||
this.initializeExistingTabs(); | ||
} | ||
|
||
/** | ||
* Initializes timestamps for existing tabs | ||
* @private | ||
*/ | ||
private initializeExistingTabs() { | ||
vscode.window.tabGroups.all.forEach((group) => { | ||
group.tabs.forEach((tab, index: number) => { | ||
const tabId = this.getTabId(tab); | ||
// Set timestamps for existing tabs, giving a slight preference to tabs on the left | ||
this.tabTimestamps.set(tabId, Date.now() - index); | ||
}); | ||
}); | ||
} | ||
|
||
/** | ||
* Updates the timestamp for a given tab | ||
* @param {vscode.Tab} tab - The tab to update | ||
*/ | ||
updateTimestamp(tab: vscode.Tab) { | ||
const tabId = this.getTabId(tab); | ||
this.tabTimestamps.set(tabId, Date.now()); | ||
} | ||
|
||
/** | ||
* Gets the timestamp for a given tab | ||
* @param {vscode.Tab} tab - The tab to get the timestamp for | ||
* @returns {number} The timestamp of the tab, or 0 if not found | ||
*/ | ||
getTimestamp(tab: vscode.Tab): number { | ||
const tabId = this.getTabId(tab); | ||
return this.tabTimestamps.get(tabId) || 0; | ||
} | ||
|
||
/** | ||
* Gets a unique identifier for a tab | ||
* @param {vscode.Tab} tab - The tab to get the ID for | ||
* @returns {string} The unique identifier for the tab | ||
* @private | ||
*/ | ||
private getTabId(tab: vscode.Tab): string { | ||
return tab.input instanceof vscode.TabInputText | ||
? tab.input.uri.toString() | ||
: ""; | ||
} | ||
} | ||
|
||
/** | ||
* Exported instance of TabTracker | ||
*/ | ||
export const tabTracker = new TabTracker(); |