Launch a specific file using the Run button in the drop-down menu

Alternative “solution”

Why not create multiple repls? It’s good that background stuff like code intelligence, which take up RAM, can instead balance their usage between multiple repls.
New Nix modules allow to reduce the amount of storage taken on new repls, so that’s not a problem. Dependencies taking up storage on multiple repls? Use Nix packages instead. Need to share code between programs? Create a package and put it on Nix.

Not helpful!

Besides the obvious inconvenience: replit’s Nix index is always behind, so you may not have the package or version you want. Maybe this problem could be ~solved by adding a restricted set of packages that are popular on Replit to nixmodules, which is probably easier for Replit to maintain than whole Nix channels. Users could contribute through PRs.

Clarify OP’s needs

I’m guessing that @midvok always edits a file before wanting to run it :person_shrugging: Also, unlike @midvok, @KAlexK wants the main run to be separated from an option to run a single file.

Workaround implementation

Here’s a JS script to put in the browser extension Code Injector, on URL pattern replit\.com/@\w*/(?!.+\?(?:lite|v)=). It maps Ctrl' to run the open file. By ' I mean whatever key is on the left of Enter on your keyboard layout. It uses the .replit file opened in the workspace, so it’d be more efficient if I manage to implement this in an extension.

runButton=__next.querySelector("[data-cy='ws-run-btn']>*")
toggleRun=runButton.click.bind(runButton)
queryMain=this["main-content"].querySelector.bind(this["main-content"])
querySidebar=this["sidebar-section-content-files"].querySelector.bind(this["sidebar-section-content-files"])
onkeyup=({ctrlKey,code})=>{if(ctrlKey&&code=="Quote"){let
replitEditor=queryMain(`:scope>[role=tabpanel]>*>:nth-child(2)>:nth-child(2)
[data-cy$='-.replit']
.cm-scroller>.cm-content`)
const
openedTab=queryMain(`.os-viewport
[aria-selected^=t]>span`),{textContent}=openedTab,stateElement=runButton.querySelector(":scope>span")
if(replitEditor)runOpenFile()
else{try{querySidebar("[role=tree]>[aria-label='.replit").click()}catch(err){alert("[focused file runner|opening .replit] Please show hidden files!")
throw ".replit file not in sidebar tree"}
let
editorSetter=new
MutationObserver(([{addedNodes:[node]}])=>{replitEditor=node.querySelector(`:scope>*>:nth-child(2)>:nth-child(2)
.cm-scroller>.cm-content`)
let
runWhenLoaded=new
MutationObserver(([{attributeName}])=>{openedTab.parentNode.parentNode.parentNode.nextSibling.querySelector(":scope>*>*").click()
if(attributeName=="aria-readonly"){for(let
it
of
querySidebar("[role=tree").getElementsByTagName("div"))if(it.ariaLabel==textContent){it.click()
break}
runOpenFile()
runWhenLoaded.disconnect()}})
runWhenLoaded.observe(replitEditor,{attributes:true})})
editorSetter.observe(this["main-content"],{childList:true})}function
runOpenFile(){let{view}=replitEditor.cmView,{0:oldEntrypoint,indices:[[from,to]]}=/(?<=^entrypoint\s*=\s*(['"])).+(?=\1)/md.exec(view.state.doc)
pushEntrypoint(to,textContent)
toggleRun()
if(stateElement.textContent!="Run")onceRunState(false,toggleRun)
onceRunState(true,partial(setTimeout,partial(pushEntrypoint,from+textContent.length,oldEntrypoint),6e2))
function
onceRunState(state,callback){const
observer=new
MutationObserver(([{target:{data}}])=>{if(data.startsWith("R")!=state){callback()
observer.disconnect()}})
observer.observe(stateElement,{characterData:true,subtree:true})}function
pushEntrypoint(to,insert){view.dispatch({changes:{from,to,insert}})}}}}
function
partial(func,...args){return func.bind(null,...args)}
2 Likes