Skip to content

Commit 1163979

Browse files
committed
feat(serverHandler/sort): add sort by file type
1 parent 4bfbdd7 commit 1163979

File tree

11 files changed

+132
-4
lines changed

11 files changed

+132
-4
lines changed

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,8 @@ server [options]
122122
Available sort key:
123123
- `n` sort by name ascending
124124
- `N` sort by name descending
125+
- `e` sort by type(suffix) ascending
126+
- `E` sort by type(suffix) descending
125127
- `s` sort by size ascending
126128
- `S` sort by size descending
127129
- `t` sort by modify time ascending

README.zh-CN.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,8 @@ server [选项]
121121
可用的排序key:
122122
- `n` 按名称递增排序
123123
- `N` 按名称递减排序
124+
- `e` 按类型(后缀)递增排序
125+
- `E` 按类型(后缀)递减排序
124126
- `s` 按大小递增排序
125127
- `S` 按大小递减排序
126128
- `t` 按修改时间递增排序

doc/en-US/api.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ Should work no matter tailing “/” is present or not in path.
77
Available sort key:
88
- `n` sort by name ascending
99
- `N` sort by name descending
10+
- `e` sort by type(suffix) ascending
11+
- `E` sort by type(suffix) descending
1012
- `s` sort by size ascending
1113
- `S` sort by size descending
1214
- `t` sort by modify time ascending

doc/zh-CN/api.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ GET <path>[?sort=sortBy]
77
可用的排序key:
88
- `n` 按名称递增排序
99
- `N` 按名称递减排序
10+
- `e` 按类型(后缀)递增排序
11+
- `E` 按类型(后缀)递减排序
1012
- `s` 按大小递增排序
1113
- `S` 按大小递减排序
1214
- `t` 按修改时间递增排序

src/serverHandler/sort.go

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package serverHandler
22

33
import (
44
"../util"
5+
"bytes"
56
"os"
67
"sort"
78
"strings"
@@ -58,6 +59,35 @@ func (xInfos infosNames) LessFilename(i, j int) (less, ok bool) {
5859
return util.CompareNumInFilename(xInfos.names[i], xInfos.names[j])
5960
}
6061

62+
func (xInfos infosNames) LessFileType(i, j int) (less, ok bool) {
63+
bufferI := xInfos.names[i]
64+
bufferJ := xInfos.names[j]
65+
for {
66+
dotIndexI := bytes.LastIndexByte(bufferI, '.')
67+
dotIndexJ := bytes.LastIndexByte(bufferJ, '.')
68+
if dotIndexI < 0 && dotIndexJ < 0 {
69+
break
70+
}
71+
if dotIndexI < 0 {
72+
return true, true
73+
}
74+
if dotIndexJ < 0 {
75+
return false, true
76+
}
77+
78+
typeI := bufferI[dotIndexI+1:]
79+
typeJ := bufferJ[dotIndexJ+1:]
80+
less, ok = util.CompareNumInFilename(typeI, typeJ)
81+
if ok {
82+
return less, ok
83+
}
84+
bufferI = bufferI[:dotIndexI]
85+
bufferJ = bufferJ[:dotIndexJ]
86+
}
87+
88+
return util.CompareNumInFilename(bufferI, bufferJ)
89+
}
90+
6191
func newInfosNames(infos []os.FileInfo, compareDir fnCompareDir) infosNames {
6292
names := make([][]byte, len(infos))
6393
for i := range infos {
@@ -117,6 +147,56 @@ func sortInfoNamesDesc(infos []os.FileInfo, compareDir fnCompareDir) {
117147
sort.Sort(nameCachedInfos)
118148
}
119149

150+
// sort type asc
151+
152+
type infosTypesAsc struct {
153+
infosNames
154+
}
155+
156+
func (xInfos infosTypesAsc) Less(i, j int) bool {
157+
less, ok := xInfos.LessDir(i, j)
158+
if ok {
159+
return less
160+
}
161+
162+
less, ok = xInfos.LessFileType(i, j)
163+
if ok {
164+
return less
165+
}
166+
167+
return i < j
168+
}
169+
170+
func sortInfoTypesAsc(infos []os.FileInfo, compareDir fnCompareDir) {
171+
nameCachedInfos := infosTypesAsc{newInfosNames(infos, compareDir)}
172+
sort.Sort(nameCachedInfos)
173+
}
174+
175+
// sort type desc
176+
177+
type infosTypesDesc struct {
178+
infosNames
179+
}
180+
181+
func (xInfos infosTypesDesc) Less(i, j int) bool {
182+
less, ok := xInfos.LessDir(i, j)
183+
if ok {
184+
return less
185+
}
186+
187+
less, ok = xInfos.LessFileType(j, i)
188+
if ok {
189+
return less
190+
}
191+
192+
return j < i
193+
}
194+
195+
func sortInfoTypesDesc(infos []os.FileInfo, compareDir fnCompareDir) {
196+
nameCachedInfos := infosTypesDesc{newInfosNames(infos, compareDir)}
197+
sort.Sort(nameCachedInfos)
198+
}
199+
120200
// sort size asc
121201

122202
func sortInfoSizesAsc(infos []os.FileInfo, compareDir fnCompareDir) {
@@ -270,6 +350,10 @@ func sortInfos(infos []os.FileInfo, rawQuery string, defaultSortBy string) (rawS
270350
sortInfoNamesAsc(infos, compareDir)
271351
case 'N':
272352
sortInfoNamesDesc(infos, compareDir)
353+
case 'e':
354+
sortInfoTypesAsc(infos, compareDir)
355+
case 'E':
356+
sortInfoTypesDesc(infos, compareDir)
273357
case 's':
274358
sortInfoSizesAsc(infos, compareDir)
275359
case 'S':

src/serverHandler/sortState.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ const (
1111
const (
1212
nameAsc byte = 'n'
1313
nameDesc byte = 'N'
14+
typeAsc byte = 'e'
15+
typeDesc byte = 'E'
1416
sizeAsc byte = 's'
1517
sizeDesc byte = 'S'
1618
timeAsc byte = 't'
@@ -68,6 +70,17 @@ func (info SortState) NextNameSort() string {
6870
return info.mergeDirWithKey(nextKey)
6971
}
7072

73+
func (info SortState) NextTypeSort() string {
74+
var nextKey byte
75+
switch info.key {
76+
case typeAsc:
77+
nextKey = typeDesc
78+
default:
79+
nextKey = typeAsc
80+
}
81+
return info.mergeDirWithKey(nextKey)
82+
}
83+
7184
func (info SortState) NextSizeSort() string {
7285
var nextKey byte
7386
switch info.key {

src/serverHandler/sortState_test.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,11 @@ func TestSortState_KeyState(t *testing.T) {
4646
t.Error(sortBy)
4747
}
4848

49+
sortBy = state.NextTypeSort()
50+
if sortBy != "/e" {
51+
t.Error(sortBy)
52+
}
53+
4954
sortBy = state.NextSizeSort()
5055
if sortBy != "/s" {
5156
t.Error(sortBy)

src/serverHandler/sort_test.go

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,9 @@ func TestSort(t *testing.T) {
2828
dir2 := dummyFileInfo{"item3", 300, now.Add(time.Minute), true}
2929
dir3 := dummyFileInfo{"item5", 200, now.Add(time.Minute * 10), true}
3030

31-
file1 := dummyFileInfo{"item2", 50, now.Add(time.Second), false}
32-
file2 := dummyFileInfo{"item4", 150, now.Add(time.Minute * 20), false}
33-
file3 := dummyFileInfo{"item6", 250, now.Add(time.Hour), false}
31+
file1 := dummyFileInfo{"item2.zip", 50, now.Add(time.Second), false}
32+
file2 := dummyFileInfo{"item4.tar", 150, now.Add(time.Minute * 20), false}
33+
file3 := dummyFileInfo{"item6.zip", 250, now.Add(time.Hour), false}
3434

3535
originInfos := []os.FileInfo{dir3, file2, dir1, file3, dir2, file1}
3636
infos := make([]os.FileInfo, len(originInfos))
@@ -84,6 +84,20 @@ func TestSort(t *testing.T) {
8484
t.Errorf("%+v\n", infos)
8585
}
8686

87+
copy(infos, originInfos)
88+
sortInfos(infos, "?sort=e", "")
89+
ok = expectInfos(infos, dir1, dir2, dir3, file2, file1, file3)
90+
if !ok {
91+
t.Errorf("%+v\n", infos)
92+
}
93+
94+
copy(infos, originInfos)
95+
sortInfos(infos, "?sort=E", "")
96+
ok = expectInfos(infos, file3, file1, file2, dir3, dir2, dir1)
97+
if !ok {
98+
t.Errorf("%+v\n", infos)
99+
}
100+
87101
copy(infos, originInfos)
88102
sortInfos(infos, "?sort=s", "")
89103
ok = expectInfos(infos, dir1, file1, file2, dir3, file3, dir2)

src/tpl/page.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@
6666
<span class="detail">
6767
<a class="field dir" href="{{.SubItemPrefix}}{{.Context.QueryStringOfSort .SortState.NextDirSort}}">Dir{{if eq $dirSort -1}}&uarr;{{else if eq $dirSort 1}}&darr;{{end}}</a>
6868
<a class="field name" href="{{.SubItemPrefix}}{{.Context.QueryStringOfSort .SortState.NextNameSort}}">Name{{if eq $sortKey "n"}}&uarr;{{else if eq $sortKey "N"}}&darr;{{end}}</a>
69+
<a class="field type" href="{{.SubItemPrefix}}{{.Context.QueryStringOfSort .SortState.NextTypeSort}}">Type{{if eq $sortKey "e"}}&uarr;{{else if eq $sortKey "E"}}&darr;{{end}}</a>
6970
<a class="field size" href="{{.SubItemPrefix}}{{.Context.QueryStringOfSort .SortState.NextSizeSort}}">Size{{if eq $sortKey "s"}}&uarr;{{else if eq $sortKey "S"}}&darr;{{end}}</a>
7071
<a class="field time" href="{{.SubItemPrefix}}{{.Context.QueryStringOfSort .SortState.NextTimeSort}}">Time{{if eq $sortKey "t"}}&uarr;{{else if eq $sortKey "T"}}&darr;{{end}}</a>
7172
</span>

src/tpl/page.html.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ return confirm('Delete?\n' + name);
7171
<span class="detail">
7272
<a class="field dir" href="{{.SubItemPrefix}}{{.Context.QueryStringOfSort .SortState.NextDirSort}}">Dir{{if eq $dirSort -1}}&uarr;{{else if eq $dirSort 1}}&darr;{{end}}</a>
7373
<a class="field name" href="{{.SubItemPrefix}}{{.Context.QueryStringOfSort .SortState.NextNameSort}}">Name{{if eq $sortKey "n"}}&uarr;{{else if eq $sortKey "N"}}&darr;{{end}}</a>
74+
<a class="field type" href="{{.SubItemPrefix}}{{.Context.QueryStringOfSort .SortState.NextTypeSort}}">Type{{if eq $sortKey "e"}}&uarr;{{else if eq $sortKey "E"}}&darr;{{end}}</a>
7475
<a class="field size" href="{{.SubItemPrefix}}{{.Context.QueryStringOfSort .SortState.NextSizeSort}}">Size{{if eq $sortKey "s"}}&uarr;{{else if eq $sortKey "S"}}&darr;{{end}}</a>
7576
<a class="field time" href="{{.SubItemPrefix}}{{.Context.QueryStringOfSort .SortState.NextTimeSort}}">Time{{if eq $sortKey "t"}}&uarr;{{else if eq $sortKey "T"}}&darr;{{end}}</a>
7677
</span>

0 commit comments

Comments
 (0)