Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FR: focus specific terminal; create new terminal with options; optionally reuse specific terminal for runInTerminal; #45

Merged
merged 12 commits into from
Mar 4, 2023

Conversation

frypf
Copy link
Contributor

@frypf frypf commented Feb 28, 2023

Currently, VSCode doesn't seem to offer any way of directly focusing a user-initiated terminal (ie. one that hasn't come from a task) without using workbench.action.quickOpenTerm (and selecting appropriately) or multiple keyboard shortcuts / mouseclicks. I've attempted to address this, and in the course of doing so hopefully opened up some additional potentially useful options, namely:

new command: revealTerminal

  • focuses a specific terminal
  • optionally matches by name, otherwise focuses a user-initiated terminal
  • can request newest or oldest match
  • creates a new terminal with given options if no match

new command: createTerminal

  • creates a new terminal with given options

additional feature for command: runInTerminal

  • can now optionally reuse specific terminal

BACKGROUND / RATIONALE: After coming up against microsoft/vscode#125573 I began using the runInTerminal action generally as a replacement for workbench.action.terminal.sendSequence. However there is then no direct way to run further related shell commands later on within that same terminal, without navigating specifically to it and either entering the shell commands manually or running workbench.action.terminal.sendSequence. To quote the OP in the closed issue above:

This is very annoying as the whole point of these keyboard shortcuts is to avoid manually manipulating terminals.

These features attempt to provide a means to do all this within a single command / sequence / keybinding. Originally I had only sought to refactor runInTerminal, but along the way it made sense to allow focusing a specific terminal as a separate command. Then in due course it also seemed useful to allow creating a terminal with specified options - (this renames the new terminal after creation because the only way of differentiating a user-initiated vs task-initiated terminal AFAIK is that task-initiated terminals always have a creationOptions.name).

Hopefully this is of interest / use.

@usernamehw
Copy link
Owner

usernamehw commented Feb 28, 2023

Not sure about the purpose of createTerminal command... How is it different from runInTerminal?

Like, imagine I'm a user reading the REAMDE file. There are 2 similar commands: createTerminal & runInTerminal.

createTerminal says it creates a terminal with a "name", but "name" also available on runInTerminal.

@frypf
Copy link
Contributor Author

frypf commented Feb 28, 2023

It offers the ability to create a terminal with a given name / icon color / cwd without specifically sending text to it immediately. I only included it originally to avoid duplicating code between runInTerminal and focusTerminal, as the ability to focus a non-task terminal without specifying a name relies on term.creationOptions.name === undefined. There may be other ways to initiate a named terminal directly from an in-built vscode command which would undermine this strategy but I couldn't find any. Obviously for $cwd, it's already possible to send "cd /whatever" to a terminal after opening it. However the icon colour I thought could be of use in particular as it allows quick visual differentiation between terminals intended for different purposes - currently the only way of creating a terminal with a different coloured icon is is to write a whole extra terminal profile and use that.

Regarding documentation, I wasn't sure what to put for a comment after "name" within runInTerminal to correctly show the difference - as it's obvious with createTerminal but slightly more nuanced with runInTerminal. As before, if you omit "reuse" it creates a new terminal with the given "name", or you can omit"name" and it uses the default. But you can also omit "name" and include "reuse", and then it matches the newest/oldest user-initiated terminal with any name, or include both and then it matches by name. I couldn't figure a single short sentence to describe all 4 scenarios - although having read your comments on #44 I feel that's more of semantic issue and a docs section would be able to go into more detail, while the function names themselves show a different use implicitly.

@usernamehw
Copy link
Owner

usernamehw commented Mar 1, 2023

Still not convinced of the need of createTerminal command. Can you merge all/most of the feature into runInTerminal?

If arg.text is undefined - throw error, but if it's an empty string - create a terminal without sending text.

If any feature cannot be merged into runInTerminal - write another comment here explaining which one.

@frypf
Copy link
Contributor Author

frypf commented Mar 1, 2023

Sure I'll have a go, just think the functionality is worth keeping.

It might sit better within revealTerminal instead though if I refactor the expected arg schema? I can't see a need to create an empty terminal without revealing it (which would be possible via runInTerminal), and technically we're not running anything. But the cognitive link between revealing with eg. "someSemanticallyObviousPropName": "most recent" (default) || "oldest" || "new" seems stronger to me at least - any ideas on someSemanticallyObviousPropName are most welcome though! Maybe just "focus"?

Anyway on a related note, I realised that my current strategy for differentiating non-task terminals falls down if runInTerminal is run and "reveal" isn't true - I was renaming the terminal straight after creation to be able to test against creationOptions.name, but workbench.action.terminal.renameWithArg can only act on the active terminal. So if we attempt to create a named terminal without revealing it, the name never gets updated. I'll have to have a think on an alternative strategy later 🤔.

@usernamehw
Copy link
Owner

any ideas on someSemanticallyObviousPropName are most welcome though! Maybe just "focus"?

Maybe "target" or "which".

• Replaces `revealTerminalCommand` & `createTerminalCommand`
@frypf
Copy link
Contributor Author

frypf commented Mar 3, 2023

Had another crack at this today, works more robustly now.

@usernamehw
Copy link
Owner

I think codicon code should be a separate PR. And I have plans to merge Codicon Names into this extension.

@usernamehw
Copy link
Owner

Although, it's probably fine. The icons don't change that often.

@frypf
Copy link
Contributor Author

frypf commented Mar 3, 2023

Could scrub it in favour of an generalised string - although it would make it more difficult to check that the icon in TargetTermOpts won't be blank. Just figured it'd round out all the available terminal creation options. I lifted it from their own reference (and included the link) - it says last updated in November.

@usernamehw
Copy link
Owner

No need to change. I'll review it this week.

@usernamehw
Copy link
Owner

"iconColor" doesn't work...

"commands.focusTerminal_04": {
	"command": "commands.focusTerminal",
	"args": {
		"name": "random",
		"which": "create new",
		"icon": "calendar",
		"iconColor": "terminal.ansiRed"
	}
}

It blinks with red and then - goes back to default color.

@frypf
Copy link
Contributor Author

frypf commented Mar 3, 2023

I can't reproduce - seems to work fine here. I tried with a variety of different "terminal.integrated.tabs.defaultColor" and individual profile "color" settings 🤔.
Screenshot 2023-03-03 at 18 05 41

I just tried on 1.76.0 and it works there too (had to roll back to 1.75.1 yesterday as the latest release seems buggier than most).

Does workbench.action.terminal.changeColor work for you on the active terminal?

@usernamehw
Copy link
Owner

usernamehw commented Mar 3, 2023

I'm on 1.76. workbench.action.terminal.changeColor works fine.

It's probably my powershell profile ... or not.

@frypf
Copy link
Contributor Author

frypf commented Mar 3, 2023

I've only got access to zsh / bash, but it works fine with either.

Yeah I dunno I'm stumped - I've tried hard to break it but it works every time.

"TEST command": {
  "command": "commands.focusTerminal",
  "repeat": 100,
  "args": {
    "name": "${random}",
    "which": "create new",
    "icon": "calendar",
    "iconColor": "editorBracketHighlight.unexpectedBracket.foreground"
  }
}

... even with stupid stuff like:

"sequence": [ {
  "command": "commands.runInTerminal",
  "args": {
    "text": " say foo bar",
    "name": "foobar"
  }
}, {
  "command": "commands.focusTerminal",
  "args": {
    "name": "foobar",
    "which": "create new",
  }
}, {
  "command": "commands.focusTerminal",
  "args": {
    "name": "foobar",
    "which": "oldest",
  }
}, {
  "command": "commands.run",
  "repeat": 5,
  "delay": 100,
  "args": [ {
      "command": "commands.runInTerminal",
      "args": {
        "text": " arr=( 'terminal.ansiBlack' 'terminal.ansiRed' 'terminal.ansiGreen' 'terminal.ansiYellow' 'terminal.ansiBlue' 'terminal.ansiMagenta' 'terminal.ansiCyan' 'terminal.ansiWhite' ) ; printf -- \"$arr[RANDOM % $#arr + 1]\" | pbcopy ; exit",
        "waitForExit": true
      }
    }, {
      "delay": 100,
      "command": "commands.runInTerminal",
      "args": {
        "name": "${random}",
        "text": " echo ${clipboard}",
        "reuse": "newest",
        "icon": "zap",
        "iconColor": "${clipboard}"
      }
    } ]
},
{
  "delay": 100,
  "command": "commands.runInTerminal",
  "args": {
    "name": "${random}",
    "text": " echo ${clipboard}",
    "reuse": "newest",
    "reveal": true,
    "icon": "zap",
    "iconColor": "${clipboard}"
  }
}, {
  "command": "commands.focusTerminal",
  "args": "foobar"
} ]

(I realise it's not necessarily of help - just want to prove that I did a bit more due diligence than earlier in the week!)

@usernamehw
Copy link
Owner

usernamehw commented Mar 3, 2023

Color is probably like 95% this issue microsoft/vscode#167643 (only affects Windows & Mac OS)

@frypf
Copy link
Contributor Author

frypf commented Mar 3, 2023

Weird that there's reports of it on both Mac and Windows but it must be pretty esoteric 🤔 (I'm on Mac).

@usernamehw usernamehw merged commit a87474c into usernamehw:master Mar 4, 2023
@usernamehw
Copy link
Owner

usernamehw commented Mar 4, 2023

Looks great 👍.

I changed "which" to "target".

And haven't tested icons.

@frypf
Copy link
Contributor Author

frypf commented Mar 4, 2023

Good stuff 👍.

Hopefully vscode fixes the issue you linked soon so people can get the full benefit - but in the meantime at least no more accidentally typing random text into files every 5 minutes when I try to focus the terminal and run shell commands after a task has run 🤞.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants