Skip to content

Commit 976106e

Browse files
committed
feat(launcher): Add file search plugin
1 parent 7a2f36d commit 976106e

File tree

7 files changed

+134
-20
lines changed

7 files changed

+134
-20
lines changed

debian/control

+2-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@ Package: pop-shell
1616
Architecture: all
1717
Depends:
1818
${misc:Depends},
19-
pop-shell-shortcuts
19+
pop-shell-shortcuts,
20+
fd-find
2021
Recommends: pop-shell-plugin-system76-power
2122
Replaces: gnome-control-center-data (<< 1:3.38.1-2ubuntu1pop1~)
2223
Breaks: gnome-control-center-data (<< 1:3.38.1-2ubuntu1pop1~)

src/launcher_plugins.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@ export interface Selection {
1010
id: number,
1111
name: string,
1212
description: string,
13-
fill?: string
13+
fill?: string,
14+
content_type?: string
1415
}
1516

1617
/** The trait which all builtin plugins implement */

src/launcher_service.ts

+22-1
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,10 @@ import type { Plugin as PluginType, Response } from 'launcher_plugins'
1212

1313
const { Plugin } = plugins
1414

15+
import * as plugin_files from 'plugin_files'
16+
import * as plugin_help from 'plugin_help'
1517
import * as plugin_scripts from 'plugin_scripts'
1618
import * as plugin_shell from 'plugin_shell'
17-
import * as plugin_help from 'plugin_help'
1819

1920
const BUILTIN_HELP: PluginType.Source = {
2021
backend: {
@@ -30,6 +31,21 @@ const BUILTIN_HELP: PluginType.Source = {
3031
pattern: null
3132
};
3233

34+
export var BUILTIN_FILES: PluginType.Source = {
35+
backend: {
36+
builtin: new plugin_files.ShellBuiltin()
37+
},
38+
config: {
39+
name: "File Search",
40+
description: "Search files in your home folder",
41+
examples: "file COSMIC",
42+
pattern: "^(file)\\s.*",
43+
exec: "",
44+
icon: "system-file-manager"
45+
},
46+
pattern: null
47+
}
48+
3349
export var BUILTINS: Array<PluginType.Source> = [
3450
{
3551
backend: {
@@ -144,6 +160,11 @@ export class LauncherService {
144160
return
145161
}
146162

163+
if (query.startsWith("file ")) {
164+
yield BUILTIN_FILES;
165+
return;
166+
}
167+
147168
for (const plugin of BUILTINS) {
148169
if (!plugin.pattern || plugin.pattern.test(query)) {
149170
yield plugin

src/plugin_files.ts

+85
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
// @ts-ignore
2+
const Me = imports.misc.extensionUtils.getCurrentExtension()
3+
4+
const { Gio, GLib } = imports.gi
5+
6+
import * as plugins from 'launcher_plugins'
7+
import * as utils from 'utils'
8+
9+
import type { Response, Selection } from 'launcher_plugins'
10+
import type { Ext } from './extension'
11+
12+
function add(id: number, file: string, content_type: string): Selection {
13+
const pos = file.lastIndexOf("/")
14+
return {
15+
id,
16+
name: pos === 0 ? file : file.substr(pos + 1),
17+
description: "~/" + file,
18+
content_type
19+
}
20+
}
21+
22+
export class ShellBuiltin extends plugins.Builtin {
23+
selections: Array<Selection> = []
24+
25+
init() {}
26+
27+
query(_ :Ext, query: string): Response.Response {
28+
let id = 0
29+
this.selections.splice(0)
30+
const search = query.substr(query.indexOf(" ") + 1).trim()
31+
if (search.length > 2) {
32+
const cmd = utils.async_process_ipc(["fdfind", search])
33+
if (cmd) {
34+
while (true) {
35+
try {
36+
const [bytes,read] = cmd.stdout.read_line(null)
37+
if (bytes === null || read === 0) break
38+
const file = imports.byteArray.toString(bytes)
39+
const gfile = Gio.File.new_for_path(file)
40+
if (gfile.query_exists(null)) {
41+
let content_type
42+
if (GLib.file_test (file, GLib.FileTest.IS_DIR)) {
43+
content_type = "inode/directory"
44+
} else {
45+
const [c,] = Gio.content_type_guess(file, null)
46+
content_type = c
47+
}
48+
49+
this.selections.push(add(id, file, content_type))
50+
id += 1
51+
}
52+
} catch (e) {
53+
global.log(`pop-shell: plugin-files: ${e.message}`)
54+
break
55+
}
56+
}
57+
}
58+
} else {
59+
this.selections.push({ id: 0, name: "file <requires 3 characters minimum>", description: "" })
60+
}
61+
62+
return {
63+
event: "queried",
64+
selections: this.selections
65+
}
66+
}
67+
68+
submit(_: Ext, id: number): Response.Response {
69+
const result = this.selections[id]
70+
71+
if (result) {
72+
if (result.description.length === 0) {
73+
return { event: "noop" }
74+
}
75+
76+
try {
77+
GLib.spawn_command_line_async(`xdg-open '${result.description.substr(2)}'`)
78+
} catch (e) {
79+
global.log(`xdg-open failed: ${e}`)
80+
}
81+
}
82+
83+
return { event: "close" }
84+
}
85+
}

src/plugin_help.ts

+18-13
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
const Me = imports.misc.extensionUtils.getCurrentExtension()
33

44
import * as plugins from 'launcher_plugins'
5+
import * as service from 'launcher_service'
56

67
import type { Response, Selection } from 'launcher_plugins'
78
import type { Ext } from './extension'
@@ -15,22 +16,26 @@ export class ShellBuiltin extends plugins.Builtin {
1516
this.selections.splice(0);
1617
let id = 0;
1718

18-
for (const [name, service] of ext.window_search.service.plugins) {
19-
if (service.config.pattern?.length > 0) {
20-
const example = service.config.examples
21-
? service.config.examples
22-
: service.config.pattern;
23-
24-
this.selections.push({
25-
id,
26-
name,
27-
description: service.config.description + `: ${example}`,
28-
fill: service.config.fill
29-
})
30-
id += 1;
19+
const files = new Map([[service.BUILTIN_FILES.config.name, service.BUILTIN_FILES]])
20+
for (const map of [files, ext.window_search.service.plugins]) {
21+
for (const [name, service] of map) {
22+
if (service.config.pattern?.length > 0) {
23+
const example = service.config.examples
24+
? service.config.examples
25+
: service.config.pattern;
26+
27+
this.selections.push({
28+
id,
29+
name,
30+
description: service.config.description + `: ${example}`,
31+
fill: service.config.fill
32+
})
33+
id += 1;
34+
}
3135
}
3236
}
3337

38+
3439
return {
3540
event: "queried",
3641
selections: this.selections

src/plugins/recent/main.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ class App {
6262
}
6363

6464
query(input) {
65-
input = input.trim()
65+
input = input.substr(input.indexOf(" ") + 1).trim()
6666

6767
const items = this.items()
6868

@@ -74,7 +74,7 @@ class App {
7474
this.results = items
7575
.filter(item => item.display_name.toLowerCase().includes(normalized))
7676
.sort((a, b) => a.display_name.localeCompare(b.display_name))
77-
.slice(0, 20)
77+
.slice(0, 7)
7878

7979
let id = 0
8080

src/plugins/recent/meta.json

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
{
22
"name": "Recent Documents",
3-
"description": "Show recent documents in search results",
4-
"pattern": "",
3+
"description": "Show recently-opened files",
4+
"pattern": "^(recent)\\s.*",
5+
"examples": "recent COSMIC",
56
"exec": "main.js",
67
"icon": "system-file-manager"
78
}

0 commit comments

Comments
 (0)