Skip to content

Commit

Permalink
feat: add nix-shell segment
Browse files Browse the repository at this point in the history
  • Loading branch information
Yash-Garg committed Jul 30, 2024
1 parent 69f6982 commit 3ada1c4
Show file tree
Hide file tree
Showing 6 changed files with 211 additions and 0 deletions.
3 changes: 3 additions & 0 deletions src/config/segment_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,8 @@ const (
NPM SegmentType = "npm"
// NX writes which Nx version us currently active
NX SegmentType = "nx"
// NIX writes the active nix shell details
NixShell SegmentType = "nix_shell"
// OCAML writes the active Ocaml version
OCAML SegmentType = "ocaml"
// OS write os specific icon
Expand Down Expand Up @@ -266,6 +268,7 @@ var Segments = map[SegmentType]func() SegmentWriter{
NIGHTSCOUT: func() SegmentWriter { return &segments.Nightscout{} },
NODE: func() SegmentWriter { return &segments.Node{} },
NPM: func() SegmentWriter { return &segments.Npm{} },
NixShell: func() SegmentWriter { return &segments.NixShell{} },
NX: func() SegmentWriter { return &segments.Nx{} },
OCAML: func() SegmentWriter { return &segments.OCaml{} },
OS: func() SegmentWriter { return &segments.Os{} },
Expand Down
67 changes: 67 additions & 0 deletions src/segments/nixshell.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
package segments

import (
"path/filepath"
"strings"

"github.com/jandedobbeleer/oh-my-posh/src/properties"
"github.com/jandedobbeleer/oh-my-posh/src/runtime"
)

type NixShellType string

const (
PURE NixShellType = "pure"
IMPURE NixShellType = "impure"
UNKNOWN NixShellType = "unknown"
NONE NixShellType = "none"
)

type NixShell struct {
props properties.Properties
env runtime.Environment

ShellType string
}

func (n *NixShell) Template() string {
return "via {{ .ShellType }}-shell"
}

func (n *NixShell) DetectShellType() NixShellType {
switch n.env.Getenv("IN_NIX_SHELL") {
case "pure":
return PURE
case "impure":
return IMPURE
default:
if n.InNewNixShell() {
return UNKNOWN
}
return NONE
}
}

// Hack to detect if we're in a `nix shell` (in contrast to a `nix-shell`).
func (n *NixShell) InNewNixShell() bool {
paths := filepath.SplitList(n.env.Getenv("PATH"))

for _, p := range paths {
if strings.Contains(p, "/nix/store") {
return true
}
}

return false
}

func (n *NixShell) Init(props properties.Properties, env runtime.Environment) {
n.props = props
n.env = env

n.ShellType = string(n.DetectShellType())
}

func (n *NixShell) Enabled() bool {
return n.ShellType != string(NONE)
}
76 changes: 76 additions & 0 deletions src/segments/nixshell_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
package segments

import (
"fmt"
"testing"

"github.com/alecthomas/assert"
"github.com/jandedobbeleer/oh-my-posh/src/properties"
"github.com/jandedobbeleer/oh-my-posh/src/runtime/mock"
)

const (
nixPath = "/nix/store/zznw8fnzss1vaqfg5hmv3y79s3hkqczi-devshell-dir/bin"
defaultPath = "/users/xyz/testing"
fullNixPath = defaultPath + ":" + nixPath
)

func setupMockEnvironment(shellType string) *mock.Environment {
env := new(mock.Environment)
env.On("Getenv", "IN_NIX_SHELL").Return(shellType)
path := defaultPath
if shellType != "" {
path = fullNixPath
}
env.On("Getenv", "PATH").Return(path)
return env
}

func TestNixShellSegment(t *testing.T) {
cases := []struct {
name string
expectedString string
shellType string
enabled bool
}{
{
name: "Pure Nix Shell",
expectedString: "via pure-shell",
shellType: "pure",
enabled: true,
},
{
name: "Impure Nix Shell",
expectedString: "via impure-shell",
shellType: "impure",
enabled: true,
},
{
name: "Unknown Nix Shell",
expectedString: "via unknown-shell",
shellType: "unknown",
enabled: true,
},
{
name: "No Nix Shell",
expectedString: "",
shellType: "",
enabled: false,
},
}

for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
env := setupMockEnvironment(tc.shellType)
n := NixShell{}
n.Init(properties.Map{}, env)

if tc.enabled {
assert.True(t, n.Enabled(), fmt.Sprintf("Failed in case: %s", tc.name))
assert.Equal(t, tc.expectedString, renderTemplate(env, n.Template(), n), tc.name)
} else {
assert.False(t, n.Enabled())
}
})
}
}
25 changes: 25 additions & 0 deletions themes/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -4723,6 +4723,31 @@
}
}
}
},
{
"if": {
"properties": {
"type": {
"const": "nix_shell"
}
}
},
"then": {
"title": "Nix Shell Segment",
"description": "https://ohmyposh.dev/docs/segments/nix-shell",
"properties": {
"properties": {
"properties": {
"newprop": {
"type": "string",
"title": "New Property",
"description": "the default text to display",
"default": "Hello"
}
}
}
}
}
}
]
}
Expand Down
39 changes: 39 additions & 0 deletions website/docs/segments/cli/nix-shell.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
---
id: nix-shell
title: Nix Shell
sidebar_label: Nix Shell
---

## What

Display the [nix shell](https://nixos.org/guides/nix-pills/developing-with-nix-shell.html) status if inside a nix-shell environment.

## Sample Configuration

import Config from "@site/src/components/Config.js";

<Config
data={{
type: "nix_shell",
style: "powerline",
foreground: "blue",
background: "transparent",
template: "(nix-{{ .ShellType }})",
}}
/>

## Template ([info][templates])

:::note default template

```template
via {{ .ShellType }}-shell"
```

:::

### Properties

| Name | Type | Description |
| ------------ | -------- | ----------------------------------------------------------- |
| `.ShellType` | `string` | the type of nix shell, can be `pure`, `impure` or `unknown` |
1 change: 1 addition & 0 deletions website/sidebars.js
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ module.exports = {
"segments/cli/kubectl",
"segments/cli/mvn",
"segments/cli/nbgv",
"segments/cli/nix-shell",
"segments/cli/npm",
"segments/cli/nx",
"segments/cli/pnpm",
Expand Down

0 comments on commit 3ada1c4

Please sign in to comment.