Closed eugenesvk closed 1 year ago
Is there an action/script I could write ...
See PaneManager
and TabManager
https://marta.sh/api/marta/panemanager.type/
https://marta.sh/api/marta/tabmanager.type/
It should be a very simple Lua plugin implementation.
Thanks for the suggestions re. tab enumeration, but how would I hook it into a "close tab" command? I couldn't find anything hook
via google on the marta website.
And a more general question: is there a list of Marta plugins somewhere I could check to discover what is possible and how it's done?
FMan had this great discoverability feature via builtin plugin manager and also via simple github tabs (which this manager used))
... how would I hook it into a "close tab" command?
https://marta.sh/api/marta/tabmanager.type/close/
... is there a list of Marta plugins somewhere ...
I believe there is no such list. I remember in which thread I suggested building a user community, however there was no follow up, and there wasn't even a GitHub Discussion before.
Here is my simple plugin implementation to close duplicate tabs (only the currently active pane).
close-duplicated-tabs.lua
marta.expose()
marta.plugin {
id = "org.example.marta.close-duplicated-tabs",
name = "Close Duplicated Tabs",
apiVersion = "2.0"
}
marta.action {
id = "close-duplicated-tabs",
name = "Close Duplicated Tabs",
apply = function(context)
local tabManager = context.window.tabs
local position = tabManager:getPosition(context.activePane)
local count = tabManager:getCount(position)
local t = {}
local i = 0
while (i < count) do
local tab = tabManager:getTab(position, i)
local path = tab.model.folder.path
if (t[path] ~= nil) then
tabManager:close(tab)
count = count - 1
else
t[path] = true
i = i + 1
end
end
end
}
Simple and commonly used features like these should be built in, rather than leaving users searching around for a working plugin. (I believe that after some version update, the above code will no longer work.)
Thanks a bunch for this example, though I'm still fuzzy on the hooking part:
... how would I hook it into a "close tab" command?
This says Close the tab.
, so as far as I understand it it's a method I'd use inside some action to close a tab. But what I need is whenever any close tab action (core.tab.close
) is invoked to be notified via some callback.
Or maybe not, I'll just replace core.tab.close
with the plugin's command in the menus and keybinds and also add an additional action there to close the current tab, and then search for duplicates and close them.
(as far as I understood, you can't invoke several actions in a menu/keybind, so you can't have a ["core.tab.close" "org.example.marta.close-duplicated-tabs. close-duplicated-tabs"]
combination, correct?)
So my immediate issue can be resolved, but it you have an idea on how to register a callback, that'd still be valuable for some other plugin idea
Simple and commonly used features like these should be built in, rather than leaving users searching around for a working plugin. (I believe that after some version update, the above code will no longer work.)
Oh, I'd be happy for it to be the case, but the beauty of plugins is that they allow to achieve that much earlier :)
... I'm still fuzzy on the hooking part ... ... how to register a callback ...
As far as I know there is currently no mechanism like event listeners (e.g. events for closing tabs) to register and perform other actions.
I'd like to run this action whenever I close ... so override ... to perform two actions ...
The above code only completes the action of removing the duplicate tabs, so you also need to add tabManager:close(PUT_CURRENT_ACTIVE_PANE_HERE)
before starting the count and removing the duplicate tabs.
Or write another action to call runAction
to run multiple actions in sequence.
https://marta.sh/api/marta/windowcontext.type/runaction/
... you can't invoke several actions ...
For executing multiple actions in a row (not hook
as you mentioned), see my Action Chains
feature suggestion below.
https://github.com/marta-file-manager/marta-issues/issues/785
Or write another action to call
runAction
to run multiple actions in sequence.
what do you pass to this function to run an action that you've already defined?
--???: how to use window:runAction context to pass an action there?
marta.action { id="✗tab_cur←", name="Close Current Tab and switch to the Left Tab",
apply = function(ctxA)
local ctxPaneA = ctxA.activePane
local ctxW = ctxA.window
-- action: Action, context:[PaneContext|ActionContext]?=nil
-- ctxW:runAction("es¦tab.✗tab_dupe") -- ERR: 'apply()' failed: Unexpected type: userData expected, got string
-- ctxW:runAction(tabLeft(ctxA)) -- ERR: Unexpected argument count: [1, 2] expected, got 1, 2
-- ERR↓ 'apply()' failed: Unexpected argument count: [1, 2] expected, got 1, 2
-- ctxW:runAction(action {id="action", name="Hello world", apply = function() martax.alert("Hello, world!") end })
ctxW:runAction(action {id="tab←"}) -- ERR: 'apply()' failed: Unexpected type: string expected, got null
end
}
This is my full plugin
--???: how to use window:runAction context to pass an action there?
--2do: make tabCloseDupe close the other tab instead of the current one:
-- saveCur fails due to a bug:
-- a@0 a@1 b@2 a@3 when a@3 is active: closing a@1 by the function selects b@2 instead of keeping the selection at a@3
-- https://github.com/marta-file-manager/marta-issues/issues/969
-- "Cmd+W" "es¦tab.✗tab_n_dupe"
-- to ✗close the current tab, select 1 tab to the ←, ✗close all duplicate tabs in the active pane
marta.expose()
marta.plugin { id="es¦tab", name="Close Duplicated Tabs", apiVersion="2.1"}
marta.action {id="✗tab_n_dupe", name="Close Current Tab and Duplicated Tabs",
apply = function(ctxA) tabClose(ctxA); tabLeft(ctxA); tabCloseDupe(ctxA); end }
marta.action {id="✗tab_dupe" , name="Close Duplicated Tabs" , apply = function(ctxA) tabCloseDupe({ctxA=ctxA, saveCur=true}); end }
marta.action {id="✗tab_cur" , name="Close Current Tab" , apply = function(ctxA) tabClose (ctxA); end }
marta.action {id="tab←" , name="Switch to the Left Tab", apply = function(ctxA) tabLeft (ctxA); end }
--???: how to use window:runAction context to pass an action there?
marta.action { id="✗tab_cur←", name="Close Current Tab and switch to the Left Tab",
apply = function(ctxA)
local ctxPaneA = ctxA.activePane
local ctxW = ctxA.window
-- action: Action, context:[PaneContext|ActionContext]?=nil
-- ctxW:runAction("es¦tab.✗tab_dupe") -- ERR: 'apply()' failed: Unexpected type: userData expected, got string
-- ctxW:runAction(tabLeft(ctxA)) -- ERR: Unexpected argument count: [1, 2] expected, got 1, 2
-- ERR↓ 'apply()' failed: Unexpected argument count: [1, 2] expected, got 1, 2
-- ctxW:runAction(action {id="action", name="Hello world", apply = function() martax.alert("Hello, world!") end })
ctxW:runAction(action {id="tab←"}) -- ERR: 'apply()' failed: Unexpected type: string expected, got null
end
}
function tabLeft(ctxA)
local ctxPaneA = ctxA.activePane
local tabMan = ctxA.window.tabs
local tabPos = tabMan:getPosition(ctxPaneA) --(tab: PaneContext): Option<TabPosition> -- Get the tab position
local tabActI = tabMan:getActiveTabIndex(tabPos) -- 0-based active tab index
local tabLeft = tabMan:getTab (tabPos, tabActI-1)
if (tabActI > 0) then -- this might not be needed since left-most tab receiving -1 command doesn't error
tabMan:activate(tabLeft)
end
end
function tabClose(ctxA)
local ctxPaneA = ctxA.activePane
local tabMan = ctxA.window.tabs
tabMan:close(ctxPaneA)
end
function tabCloseDupe(arg)
local ctxA = arg.ctxA
local saveCur = arg.saveCur or false -- if current tab is a dupe, close the other dupe
local ctxPaneA = ctxA.activePane
local tabMan = ctxA.window.tabs
local tabPos = tabMan:getPosition (ctxPaneA) --(tab: PaneContext): Option<TabPosition> -- Get the tab position
local tabCount = tabMan:getCount (tabPos ) --(position: Option<TabPosition>): Int tab count for a given position
local t = {}
local i = 0
while (i < tabCount) do
local tab = tabMan:getTab(tabPos, i)
local path = tab.model.folder.path
if (t[path] ~= nil) then
-- if saveCur then -- fails due to a bug, implement later when it's fixed
-- local tabActI = tabMan:getActiveTabIndex(tabPos ) -- 0-based active tab index
-- martax.alert("i=" .. tostring(i) .. " tabActI=" .. tostring(tabActI))
-- if i==tabActI then
-- print('aaa')
-- end
-- end
tabMan:close(tab)
tabCount = tabCount - 1
else
t[path] = {true,i} -- path has been seen @ i (use it later to close i instead of the current tab)
i = i + 1
end
end
end
For executing multiple actions in a row (not
hook
as you mentioned), see myAction Chains
feature suggestion below.
By the way, isn't this
Run Actions | actions – actions to run (array) |
---|
supposed to allow chains of actions?
Though "q" {id "core.run.actions" actions ["core.tab.new" "core.tab.new"]}
didn't work and I couldn't find any Run Actions
in the Action Panel (so maybe my ID here is wrong and it's core.actions.run
or something)
what do you pass to this function to ...
According to the documentation you need to provide an Action
instance.
For example:
windowContext:runAction(marta.globalContext.actions:getById("core.back"), activePane)
By the way, isn't this ... actions – actions to run (array)
I have good reason to believe that this is an outdated document.
Need to wait for yanex to clean up.
According to the documentation you need to provide an
Action
instance.
That part I figured out myself :)
windowContext:runAction(marta.globalContext.actions:getById("core.back"), activePane)
That's what I was missing, thanks for your help!
By the way, is it possible to pass any parameters for these builtin actions? windowContext:runAction
doesn't seem to have a field for that, but maybe there is a trick
upd here is a tab-deduplication plugin that fixes this issue as well as another one https://github.com/marta-file-manager/marta-issues/issues/967
Suppose I have 20 tabs opened and have two pairs of duplicate tabs, so they just waste tab space Is there an action/script I could write to enumerate the tabs and close the duplicates? Ideally, I'd like to run this action whenever I close the current tab (so override
"Cmd+W" "core.tab.close"
to perform two actions instead of just one) as I've found this to be a rather efficient way to get rid of the duplicates