feat: execution time segment

This commit is contained in:
TravisTX 2020-12-06 14:03:40 -07:00 committed by Jan De Dobbeleer
parent e92061428b
commit 5f7b1f6ac6
15 changed files with 361 additions and 42 deletions

View file

@ -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

View file

@ -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 🏎

View file

@ -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
```

View 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

View file

@ -19,6 +19,7 @@ module.exports = {
"command",
"dotnet",
"environment",
"executiontime",
"exit",
"git",
"golang",

View file

@ -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
}

21
main.go
View file

@ -11,14 +11,15 @@ import (
var Version = "development"
type args struct {
ErrorCode *int
PrintConfig *bool
PrintShell *bool
Config *string
Shell *string
PWD *string
Version *bool
Debug *bool
ErrorCode *int
PrintConfig *bool
PrintShell *bool
Config *string
Shell *string
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{

View file

@ -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

View file

@ -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

View file

@ -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)
}

View file

@ -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 {
@ -124,28 +126,29 @@ func (segment *Segment) shouldIgnoreFolder(cwd string) bool {
func (segment *Segment) mapSegmentWithWriter(env environmentInfo) error {
functions := map[SegmentType]SegmentWriter{
Session: &session{},
Path: &path{},
Git: &git{},
Exit: &exit{},
Python: &python{},
Root: &root{},
Text: &text{},
Time: &tempus{},
Cmd: &command{},
Battery: &batt{},
Spotify: &spotify{},
ShellInfo: &shell{},
Node: &node{},
Os: &osInfo{},
EnvVar: &envvar{},
Az: &az{},
Kubectl: &kubectl{},
Dotnet: &dotnet{},
Terraform: &terraform{},
Golang: &golang{},
Julia: &julia{},
YTM: &ytm{},
Session: &session{},
Path: &path{},
Git: &git{},
Exit: &exit{},
Python: &python{},
Root: &root{},
Text: &text{},
Time: &tempus{},
Cmd: &command{},
Battery: &batt{},
Spotify: &spotify{},
ShellInfo: &shell{},
Node: &node{},
Os: &osInfo{},
EnvVar: &envvar{},
Az: &az{},
Kubectl: &kubectl{},
Dotnet: &dotnet{},
Terraform: &terraform{},
Golang: &golang{},
Julia: &julia{},
YTM: &ytm{},
ExecutionTime: &executiontime{},
}
if writer, ok := functions[segment.Type]; ok {
props := &properties{

37
segment_executiontime.go Normal file
View 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
}

View 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)
}

View file

@ -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)

View file

@ -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
}
}
}
}
}
}
]
}