Skip to content

Commit

Permalink
bugfix: Duplicate path in vscode terminal, but normal in system termi…
Browse files Browse the repository at this point in the history
…nal.

* add a new struct: MapSet and SortedSet

fix #74
  • Loading branch information
aooohan committed Mar 7, 2024
1 parent 2956e35 commit e3c35b9
Show file tree
Hide file tree
Showing 4 changed files with 215 additions and 2 deletions.
4 changes: 3 additions & 1 deletion internal/env/macos_env.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ package env

import (
"fmt"
"github.com/version-fox/vfox/internal/util"
"os"
"strings"
)
Expand All @@ -34,7 +35,8 @@ type macosEnvManager struct {
}

func (m *macosEnvManager) Paths(paths []string) string {
return strings.Join(paths, ":")
set := util.NewSortedSetWithSlice[string](paths)
return strings.Join(set.Slice(), ":")
}

func (m *macosEnvManager) Close() error {
Expand Down
3 changes: 2 additions & 1 deletion internal/env/windows_env.go
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,8 @@ func (w *windowsEnvManager) broadcastEnvironment() error {
}

func (w *windowsEnvManager) Paths(paths []string) string {
return strings.Join(paths, ";")
set := util.NewSortedSetWithSlice[string](paths)
return strings.Join(set.Slice(), ";")
}

func NewEnvManager(vfConfigPath string) (Manager, error) {
Expand Down
126 changes: 126 additions & 0 deletions internal/util/set.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
/*
* Copyright 2024 Han Li and contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package util

type Set[T comparable] interface {
Add(v T) bool
Remove(v T)
Contains(v T) bool
Len() int
Slice() []T
}

type MapSet[T comparable] struct {
values map[T]struct{}
}

func (s *MapSet[T]) Add(v T) bool {
_, exists := s.values[v]
if !exists {
s.values[v] = struct{}{}
}
return !exists
}

func (s *MapSet[T]) Remove(v T) {
delete(s.values, v)
}

func (s *MapSet[T]) Contains(v T) bool {
_, exists := s.values[v]
return exists
}

func (s *MapSet[T]) Len() int {
return len(s.values)
}

func (s *MapSet[T]) Slice() []T {
slice := make([]T, 0, len(s.values))
for v := range s.values {
slice = append(slice, v)
}
return slice
}

func NewSet[T comparable]() Set[T] {
return &MapSet[T]{
values: make(map[T]struct{}),
}
}

func NewSetWithSlice[T comparable](slice []T) Set[T] {
s := NewSet[T]()
for _, v := range slice {
s.Add(v)
}
return s
}

type SortedSet[T comparable] struct {
elements []T
set MapSet[T]
}

func (s *SortedSet[T]) Add(v T) bool {
exist := s.set.Contains(v)
if !exist {
s.elements = append(s.elements, v)
s.set.Add(v)
}
return !exist
}

func (s *SortedSet[T]) Remove(v T) {
exists := s.set.Contains(v)
if exists {
delete(s.set.values, v)
for i, e := range s.elements {
if e == v {
s.elements = append(s.elements[:i], s.elements[i+1:]...)
break
}
}
}
}

func (s *SortedSet[T]) Contains(v T) bool {
return s.set.Contains(v)
}

func (s *SortedSet[T]) Len() int {
return len(s.elements)
}

func (s *SortedSet[T]) Slice() []T {
return s.elements
}

func NewSortedSet[T comparable]() Set[T] {
return &SortedSet[T]{
set: MapSet[T]{values: make(map[T]struct{})},
elements: make([]T, 0),
}
}

func NewSortedSetWithSlice[T comparable](slice []T) Set[T] {
s := NewSortedSet[T]()
for _, v := range slice {
s.Add(v)
}
return s
}
84 changes: 84 additions & 0 deletions internal/util/set_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
/*
* Copyright 2024 Han Li and contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package util

import (
"reflect"
"testing"
)

func TestMapSet(t *testing.T) {
s := NewSet[int]()

s.Add(1)
if !s.Contains(1) {
t.Errorf("Expected set to contain 1")
}

s.Remove(1)
if s.Contains(1) {
t.Errorf("Expected set to not contain 1")
}

if s.Len() != 0 {
t.Errorf("Expected set length to be 0, got %d", s.Len())
}
}

func TestOrderedSet(t *testing.T) {
s := NewSortedSet[int]()

s.Add(1)
if !s.Contains(1) {
t.Errorf("Expected set to contain 1")
}

s.Remove(1)
if s.Contains(1) {
t.Errorf("Expected set to not contain 1")
}

if s.Len() != 0 {
t.Errorf("Expected set length to be 0, got %d", s.Len())
}

for v := range s.Slice() {
t.Errorf("Expected no iteration over set, but got %v", v)
}
}

func TestSortedSetSort(t *testing.T) {
s := NewSortedSet[string]()

elements := []string{"ss23434444444jl2342342424s", "89999809898998bbb", "99234234234234aaa", "1232ssssssssssssssss414141fff"}

for _, r := range elements {
s.Add(r)
}

if !reflect.DeepEqual(s.Slice(), elements) {
t.Errorf("Expected set to contain %v, got %v", elements, s.Slice())
}

e := elements[0]
elements = elements[1:]
s.Remove(e)
if !reflect.DeepEqual(s.Slice(), elements) {
t.Errorf("Expected set to contain %v, got %v", elements, s.Slice())
}

}

0 comments on commit e3c35b9

Please sign in to comment.