mirror of
https://github.com/JanDeDobbeleer/oh-my-posh.git
synced 2024-11-09 20:44:03 -08:00
feat: execution time segment
This commit is contained in:
parent
e92061428b
commit
5f7b1f6ac6
|
@ -137,7 +137,7 @@ Community Impact Guidelines were inspired by [Mozilla's code of conduct
|
|||
enforcement ladder](https://github.com/mozilla/diversity).
|
||||
|
||||
[docs]: https://ohmyposh.dev/docs
|
||||
[guide]: https://ohmyposh.dev/docs/contributing-segment
|
||||
[guide]: https://ohmyposh.dev/docs/contributing_segment
|
||||
[cc]: https://www.conventionalcommits.org/en/v1.0.0/#summary
|
||||
[homepage]: https://www.contributor-covenant.org
|
||||
[conduct]: mailto:conduct@ohmyposh.dev
|
||||
|
|
|
@ -76,7 +76,7 @@ go build -o $GOPATH/bin/oh-my-posh
|
|||
|
||||
## Add the documentation
|
||||
|
||||
Create a new `markdown` file underneath the [`docs/docs`][docs] folder called `new-segment.md`.
|
||||
Create a new `markdown` file underneath the [`docs/docs`][docs] folder called `segment-new.md`.
|
||||
Use the following template as a guide.
|
||||
|
||||
````markdown
|
||||
|
@ -114,6 +114,43 @@ Display something new.
|
|||
|
||||
Open [`sidebars.js`][sidebars] and add your document id (`new`) to the items of the Segments category.
|
||||
|
||||
## Add the JSON schema
|
||||
|
||||
Edit the `themes/schema.json` file to add your segment.
|
||||
|
||||
At `$.definitions.segment.properties.type.enum`, add your `SegmentType` to the array:
|
||||
|
||||
```json
|
||||
new,
|
||||
```
|
||||
|
||||
At `$.definitions.segment.allOf`, add your segment details:
|
||||
```json
|
||||
{
|
||||
"if": {
|
||||
"properties": {
|
||||
"type": { "const": "new" }
|
||||
}
|
||||
},
|
||||
"then": {
|
||||
"title": "Display something new",
|
||||
"description": "https://ohmyposh.dev/docs/new",
|
||||
"properties": {
|
||||
"properties": {
|
||||
"properties": {
|
||||
"nwprop": {
|
||||
"type": "string",
|
||||
"title": "New Prop",
|
||||
"description": "the new text to show",
|
||||
"default": "\uEFF1"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Create a pull request
|
||||
|
||||
And be patient, I'm going as fast as I can 🏎
|
||||
|
|
|
@ -231,10 +231,17 @@ Edit `$PROFILE` in your preferred PowerShell version and add the following lines
|
|||
$errorCode = 1
|
||||
}
|
||||
}
|
||||
|
||||
$executionTime = -1
|
||||
$history = Get-History -ErrorAction Ignore -Count 1
|
||||
if ($null -ne $history) {
|
||||
$executionTime = $history.Duration.TotalMilliseconds
|
||||
}
|
||||
|
||||
$startInfo = New-Object System.Diagnostics.ProcessStartInfo
|
||||
$startInfo.FileName = "C:\tools\oh-my-posh.exe"
|
||||
$cleanPWD = $PWD.ProviderPath.TrimEnd("\")
|
||||
$startInfo.Arguments = "-config=""$env:USERPROFILE\.poshthemes\jandedobbeleer.omp.json"" -error=$errorCode -pwd=""$cleanPWD"""
|
||||
$startInfo.Arguments = "-config=""$env:USERPROFILE\.poshthemes\jandedobbeleer.omp.json"" -error=$errorCode -pwd=""$cleanPWD"" -execution-time=$executionTime"
|
||||
$startInfo.Environment["TERM"] = "xterm-256color"
|
||||
$startInfo.CreateNoWindow = $true
|
||||
$startInfo.StandardOutputEncoding = [System.Text.Encoding]::UTF8
|
||||
|
@ -269,21 +276,40 @@ Once added, reload your profile for the changes to take effect.
|
|||
Add the following to `~/.zshrc`:
|
||||
|
||||
```bash
|
||||
function powerline_precmd() {
|
||||
PS1="$(oh-my-posh -config ~/.poshthemes/jandedobbeleer.omp.json --error $?)"
|
||||
function omp_preexec() {
|
||||
omp_start_time=$(($(date +%s%0N)/1000000))
|
||||
}
|
||||
|
||||
function install_powerline_precmd() {
|
||||
for s in "${precmd_functions[@]}"; do
|
||||
if [ "$s" = "powerline_precmd" ]; then
|
||||
function omp_precmd() {
|
||||
omp_elapsed=-1
|
||||
if [ $omp_start_time ]; then
|
||||
omp_now=$(($(date +%s%0N)/1000000))
|
||||
omp_elapsed=$(($omp_now-$omp_start_time))
|
||||
fi
|
||||
PS1="$(oh-my-posh -config ~/.poshthemes/jandedobbeleer.omp.json --error $? --execution-time $omp_elapsed)"
|
||||
unset omp_start_time
|
||||
unset omp_now
|
||||
unset omp_elapsed
|
||||
}
|
||||
|
||||
function install_omp_hooks() {
|
||||
for s in "${preexec_functions[@]}"; do
|
||||
if [ "$s" = "omp_preexec" ]; then
|
||||
return
|
||||
fi
|
||||
done
|
||||
precmd_functions+=(powerline_precmd)
|
||||
preexec_functions+=(omp_preexec)
|
||||
|
||||
for s in "${precmd_functions[@]}"; do
|
||||
if [ "$s" = "omp_precmd" ]; then
|
||||
return
|
||||
fi
|
||||
done
|
||||
precmd_functions+=(omp_precmd)
|
||||
}
|
||||
|
||||
if [ "$TERM" != "linux" ]; then
|
||||
install_powerline_precmd
|
||||
install_omp_hooks
|
||||
fi
|
||||
```
|
||||
|
||||
|
|
33
docs/docs/segment-executiontime.md
Normal file
33
docs/docs/segment-executiontime.md
Normal file
|
@ -0,0 +1,33 @@
|
|||
---
|
||||
id: executiontime
|
||||
title: Execution Time
|
||||
sidebar_label: Execution Time
|
||||
---
|
||||
|
||||
## What
|
||||
|
||||
Displays the execution time of the previously executed command.
|
||||
|
||||
To use this, use the PowerShell module, or confirm that you are passing an `execution-time` argument contianing the elapsed milliseconds to the oh-my-posh executable. The [installation guide][install] shows how to include this argument for PowerShell and Zsh.
|
||||
|
||||
## Sample Configuration
|
||||
|
||||
```json
|
||||
{
|
||||
"type": "executiontime",
|
||||
"style": "powerline",
|
||||
"powerline_symbol": "\uE0B0",
|
||||
"foreground": "#ffffff",
|
||||
"background": "#8800dd",
|
||||
"properties": {
|
||||
"threshold": 500,
|
||||
"prefix": " <#fefefe>\ufbab</> "
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Properties
|
||||
|
||||
- threshold: `number` - minimum duration (milliseconds) required to enable this segment - defaults to `500`
|
||||
|
||||
[install]: /docs/installation
|
|
@ -19,6 +19,7 @@ module.exports = {
|
|||
"command",
|
||||
"dotnet",
|
||||
"environment",
|
||||
"executiontime",
|
||||
"exit",
|
||||
"git",
|
||||
"golang",
|
||||
|
|
|
@ -42,6 +42,7 @@ type environmentInfo interface {
|
|||
runCommand(command string, args ...string) (string, error)
|
||||
runShellCommand(shell, command string) string
|
||||
lastErrorCode() int
|
||||
executionTime() float64
|
||||
getArgs() *args
|
||||
getBatteryInfo() (*battery.Battery, error)
|
||||
getShellName() string
|
||||
|
@ -200,6 +201,10 @@ func (env *environment) lastErrorCode() int {
|
|||
return *env.args.ErrorCode
|
||||
}
|
||||
|
||||
func (env *environment) executionTime() float64 {
|
||||
return *env.args.ExecutionTime
|
||||
}
|
||||
|
||||
func (env *environment) getArgs() *args {
|
||||
return env.args
|
||||
}
|
||||
|
|
5
main.go
5
main.go
|
@ -19,6 +19,7 @@ type args struct {
|
|||
PWD *string
|
||||
Version *bool
|
||||
Debug *bool
|
||||
ExecutionTime *float64
|
||||
}
|
||||
|
||||
func main() {
|
||||
|
@ -55,6 +56,10 @@ func main() {
|
|||
"debug",
|
||||
false,
|
||||
"Print debug information"),
|
||||
ExecutionTime: flag.Float64(
|
||||
"execution-time",
|
||||
0,
|
||||
"Execution time of the previously executed command"),
|
||||
}
|
||||
flag.Parse()
|
||||
env := &environment{
|
||||
|
|
|
@ -71,12 +71,19 @@ function Set-PoshPrompt {
|
|||
$errorCode = 1
|
||||
}
|
||||
}
|
||||
|
||||
$executionTime = -1
|
||||
$history = Get-History -ErrorAction Ignore -Count 1
|
||||
if ($null -ne $history) {
|
||||
$executionTime = $history.Duration.TotalMilliseconds
|
||||
}
|
||||
|
||||
$startInfo = New-Object System.Diagnostics.ProcessStartInfo
|
||||
$startInfo.FileName = Get-PoshCommand
|
||||
$config = $global:PoshSettings.Theme
|
||||
$showDebug = $global:PoshSettings.ShowDebug
|
||||
$cleanPWD = $PWD.ProviderPath.TrimEnd("\")
|
||||
$startInfo.Arguments = "-debug=""$showDebug"" -config=""$config"" -error=$errorCode -pwd=""$cleanPWD"""
|
||||
$startInfo.Arguments = "-debug=""$showDebug"" -config=""$config"" -error=$errorCode -pwd=""$cleanPWD"" -execution-time=$executionTime"
|
||||
$startInfo.Environment["TERM"] = "xterm-256color"
|
||||
$startInfo.CreateNoWindow = $true
|
||||
$startInfo.StandardOutputEncoding = [System.Text.Encoding]::UTF8
|
||||
|
|
|
@ -83,6 +83,23 @@ func (p *properties) getBool(property Property, defaultValue bool) bool {
|
|||
return boolValue
|
||||
}
|
||||
|
||||
func (p *properties) getFloat64(property Property, defaultValue float64) float64 {
|
||||
if p == nil || p.values == nil {
|
||||
return defaultValue
|
||||
}
|
||||
val, found := p.values[property]
|
||||
if !found {
|
||||
return defaultValue
|
||||
}
|
||||
|
||||
floatValue, ok := val.(float64)
|
||||
if !ok {
|
||||
return defaultValue
|
||||
}
|
||||
|
||||
return floatValue
|
||||
}
|
||||
|
||||
func (p *properties) getKeyValueMap(property Property, defaultValue map[string]string) map[string]string {
|
||||
if p == nil || p.values == nil {
|
||||
return defaultValue
|
||||
|
|
|
@ -104,3 +104,43 @@ func TestGetBoolInvalidProperty(t *testing.T) {
|
|||
value := properties.getBool(DisplayHost, false)
|
||||
assert.False(t, value)
|
||||
}
|
||||
|
||||
func TestGetFloat64(t *testing.T) {
|
||||
expected := float64(1337)
|
||||
values := map[Property]interface{}{"myfloat": expected}
|
||||
properties := properties{
|
||||
values: values,
|
||||
}
|
||||
value := properties.getFloat64("myfloat", 9001)
|
||||
assert.Equal(t, expected, value)
|
||||
}
|
||||
|
||||
func TestGetFloat64PropertyNotInMap(t *testing.T) {
|
||||
expected := float64(1337)
|
||||
values := map[Property]interface{}{}
|
||||
properties := properties{
|
||||
values: values,
|
||||
}
|
||||
value := properties.getFloat64(ThresholdProperty, expected)
|
||||
assert.Equal(t, expected, value)
|
||||
}
|
||||
|
||||
func TestGetFloat64InvalidStringProperty(t *testing.T) {
|
||||
expected := float64(1337)
|
||||
values := map[Property]interface{}{ThresholdProperty: "invalid"}
|
||||
properties := properties{
|
||||
values: values,
|
||||
}
|
||||
value := properties.getFloat64(ThresholdProperty, expected)
|
||||
assert.Equal(t, expected, value)
|
||||
}
|
||||
|
||||
func TestGetFloat64InvalidBoolProperty(t *testing.T) {
|
||||
expected := float64(1337)
|
||||
values := map[Property]interface{}{ThresholdProperty: true}
|
||||
properties := properties{
|
||||
values: values,
|
||||
}
|
||||
value := properties.getFloat64(ThresholdProperty, expected)
|
||||
assert.Equal(t, expected, value)
|
||||
}
|
||||
|
|
|
@ -89,6 +89,8 @@ const (
|
|||
Diamond SegmentStyle = "diamond"
|
||||
// YTM writes YouTube Music information and status
|
||||
YTM SegmentType = "ytm"
|
||||
// ExecutionTime writes the execution time of the last run command
|
||||
ExecutionTime SegmentType = "executiontime"
|
||||
)
|
||||
|
||||
func (segment *Segment) string() string {
|
||||
|
@ -146,6 +148,7 @@ func (segment *Segment) mapSegmentWithWriter(env environmentInfo) error {
|
|||
Golang: &golang{},
|
||||
Julia: &julia{},
|
||||
YTM: &ytm{},
|
||||
ExecutionTime: &executiontime{},
|
||||
}
|
||||
if writer, ok := functions[segment.Type]; ok {
|
||||
props := &properties{
|
||||
|
|
37
segment_executiontime.go
Normal file
37
segment_executiontime.go
Normal file
|
@ -0,0 +1,37 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"time"
|
||||
)
|
||||
|
||||
type executiontime struct {
|
||||
props *properties
|
||||
env environmentInfo
|
||||
output string
|
||||
}
|
||||
|
||||
const (
|
||||
// ThresholdProperty represents minimum duration (milliseconds) required to enable this segment
|
||||
ThresholdProperty Property = "threshold"
|
||||
)
|
||||
|
||||
func (t *executiontime) enabled() bool {
|
||||
executionTimeMs := t.env.executionTime()
|
||||
thresholdMs := t.props.getFloat64(ThresholdProperty, float64(500))
|
||||
if executionTimeMs < thresholdMs {
|
||||
return false
|
||||
}
|
||||
|
||||
duration := time.Duration(executionTimeMs) * time.Millisecond
|
||||
t.output = duration.String()
|
||||
return t.output != ""
|
||||
}
|
||||
|
||||
func (t *executiontime) string() string {
|
||||
return t.output
|
||||
}
|
||||
|
||||
func (t *executiontime) init(props *properties, env environmentInfo) {
|
||||
t.props = props
|
||||
t.env = env
|
||||
}
|
79
segment_executiontime_test.go
Normal file
79
segment_executiontime_test.go
Normal file
|
@ -0,0 +1,79 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestExecutionTimeWriterDefaultThresholdEnabled(t *testing.T) {
|
||||
env := new(MockedEnvironment)
|
||||
env.On("executionTime", nil).Return(1337)
|
||||
executionTime := &executiontime{
|
||||
env: env,
|
||||
}
|
||||
assert.True(t, executionTime.enabled())
|
||||
}
|
||||
|
||||
func TestExecutionTimeWriterDefaultThresholdDisabled(t *testing.T) {
|
||||
env := new(MockedEnvironment)
|
||||
env.On("executionTime", nil).Return(1)
|
||||
executionTime := &executiontime{
|
||||
env: env,
|
||||
}
|
||||
assert.False(t, executionTime.enabled())
|
||||
}
|
||||
|
||||
func TestExecutionTimeWriterCustomThresholdEnabled(t *testing.T) {
|
||||
env := new(MockedEnvironment)
|
||||
env.On("executionTime", nil).Return(99)
|
||||
props := &properties{
|
||||
values: map[Property]interface{}{
|
||||
ThresholdProperty: float64(10),
|
||||
},
|
||||
}
|
||||
executionTime := &executiontime{
|
||||
env: env,
|
||||
props: props,
|
||||
}
|
||||
assert.True(t, executionTime.enabled())
|
||||
}
|
||||
|
||||
func TestExecutionTimeWriterCustomThresholdDisabled(t *testing.T) {
|
||||
env := new(MockedEnvironment)
|
||||
env.On("executionTime", nil).Return(99)
|
||||
props := &properties{
|
||||
values: map[Property]interface{}{
|
||||
ThresholdProperty: float64(100),
|
||||
},
|
||||
}
|
||||
executionTime := &executiontime{
|
||||
env: env,
|
||||
props: props,
|
||||
}
|
||||
assert.False(t, executionTime.enabled())
|
||||
}
|
||||
|
||||
func TestExecutionTimeWriterDuration(t *testing.T) {
|
||||
input := 1337
|
||||
expected := "1.337s"
|
||||
env := new(MockedEnvironment)
|
||||
env.On("executionTime", nil).Return(input)
|
||||
executionTime := &executiontime{
|
||||
env: env,
|
||||
}
|
||||
executionTime.enabled()
|
||||
assert.Equal(t, expected, executionTime.output)
|
||||
}
|
||||
|
||||
func TestExecutionTimeWriterDuration2(t *testing.T) {
|
||||
input := 13371337
|
||||
expected := "3h42m51.337s"
|
||||
env := new(MockedEnvironment)
|
||||
env.On("executionTime", nil).Return(input)
|
||||
executionTime := &executiontime{
|
||||
env: env,
|
||||
}
|
||||
executionTime.enabled()
|
||||
assert.Equal(t, expected, executionTime.output)
|
||||
}
|
|
@ -93,6 +93,11 @@ func (env *MockedEnvironment) lastErrorCode() int {
|
|||
return args.Int(0)
|
||||
}
|
||||
|
||||
func (env *MockedEnvironment) executionTime() float64 {
|
||||
args := env.Called(nil)
|
||||
return float64(args.Int(0))
|
||||
}
|
||||
|
||||
func (env *MockedEnvironment) isRunningAsRoot() bool {
|
||||
args := env.Called(nil)
|
||||
return args.Bool(0)
|
||||
|
|
|
@ -104,7 +104,8 @@
|
|||
"terraform",
|
||||
"go",
|
||||
"julia",
|
||||
"ytm"
|
||||
"ytm",
|
||||
"executiontime"
|
||||
]
|
||||
},
|
||||
"style": {
|
||||
|
@ -1131,6 +1132,29 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": {
|
||||
"properties": {
|
||||
"type": { "const": "executiontime" }
|
||||
}
|
||||
},
|
||||
"then": {
|
||||
"title": "Displays the execution time of the previously executed command",
|
||||
"description": "https://ohmyposh.dev/docs/executiontime",
|
||||
"properties": {
|
||||
"properties": {
|
||||
"properties": {
|
||||
"threshold": {
|
||||
"type": "number",
|
||||
"title": "Threshold",
|
||||
"description": "minimum duration (milliseconds) required to enable this segment",
|
||||
"default": 500
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue