-
Notifications
You must be signed in to change notification settings - Fork 18
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #215 from gjsify/iterators
Inject more IterableIterator and AsyncIterableIterator types for Gtk 4 and Gio
- Loading branch information
Showing
9 changed files
with
305 additions
and
64 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
@types/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
import GLib from 'gi://GLib' | ||
import Gio from 'gi://Gio' | ||
|
||
Gio._promisify(Gio.File.prototype, 'enumerate_children_async', 'enumerate_children_finish') | ||
|
||
const textDecoder = new TextDecoder('utf-8') | ||
|
||
function readFileInChunksSync() { | ||
// Open a file | ||
const file = Gio.File.new_for_path('/etc/os-release') | ||
const inputStream = file.read(null) | ||
|
||
// Read file in chunks of 4 bytes using SyncIterator | ||
console.log('\nReading file in chunks using SyncIterator:') | ||
for (const bytes of inputStream.createSyncIterator(4)) { | ||
const text = textDecoder.decode(bytes.toArray()) | ||
console.log('Chunk:', text) | ||
} | ||
} | ||
|
||
async function readFileInChunksAsync() { | ||
// Open a file | ||
const file = Gio.File.new_for_path('/etc/os-release') | ||
const inputStream = file.read(null) | ||
|
||
// Read file in chunks of 4 bytes using AsyncIterator | ||
console.log('Reading file in chunks using AsyncIterator:') | ||
for await (const bytes of inputStream.createAsyncIterator(4)) { | ||
const text = textDecoder.decode(bytes.toArray()) | ||
console.log('Chunk:', text) | ||
} | ||
} | ||
|
||
function listDirectoryContentsSync() { | ||
// List root directory contents synchronously | ||
console.log('\nListing . directory contents (sync):') | ||
const dir = Gio.File.new_for_path('.') | ||
const enumerator = dir.enumerate_children('standard::name', Gio.FileQueryInfoFlags.NOFOLLOW_SYMLINKS, null) | ||
|
||
for (const fileInfo of enumerator) { | ||
console.log(fileInfo.get_name()) | ||
} | ||
} | ||
|
||
async function listDirectoryContentsAsync() { | ||
// List root directory contents asynchronously | ||
console.log('\nListing . directory contents (async):') | ||
const dir = Gio.File.new_for_path('.') | ||
const enumerator = await dir.enumerate_children_async( | ||
'standard::name', | ||
Gio.FileQueryInfoFlags.NOFOLLOW_SYMLINKS, | ||
GLib.PRIORITY_DEFAULT, | ||
null, | ||
) | ||
|
||
for await (const file_info of enumerator) { | ||
console.log(file_info.get_name()) | ||
} | ||
} | ||
|
||
// Run all examples | ||
const loop = new GLib.MainLoop(null, false) | ||
|
||
const start = async () => { | ||
readFileInChunksSync() | ||
listDirectoryContentsSync() | ||
await readFileInChunksAsync() | ||
await listDirectoryContentsAsync() | ||
} | ||
|
||
start().then(() => { | ||
loop.quit() | ||
}) | ||
|
||
loop.run() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
{ | ||
"name": "@ts-for-gir-example/gio-2-iterate", | ||
"version": "4.0.0-beta.18", | ||
"description": "Example demonstrating GIO async and sync iterators", | ||
"type": "module", | ||
"private": true, | ||
"scripts": { | ||
"build:app": "tsc", | ||
"build": "yarn build:app", | ||
"start:app": "gjs -m dist/main.js", | ||
"start": "yarn build && yarn start:app", | ||
"validate": "yarn validate:types", | ||
"validate:types": "tsc --noEmit", | ||
"clear": "rm -rf dist" | ||
}, | ||
"devDependencies": { | ||
"typescript": "^5.6.3" | ||
}, | ||
"dependencies": { | ||
"@girs/gio-2.0": "workspace:^", | ||
"@girs/gjs": "workspace:^", | ||
"@girs/glib-2.0": "workspace:^" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
{ | ||
"compilerOptions": { | ||
"lib": ["ESNext"], | ||
"types": ["@girs/gjs", "@girs/gjs/dom", "@girs/glib-2.0", "@girs/gio-2.0"], | ||
"target": "ESNext", | ||
"module": "ESNext", | ||
"moduleResolution": "bundler", | ||
"strict": true, | ||
"noImplicitAny": true, | ||
"strictNullChecks": true, | ||
"noImplicitThis": true, | ||
"alwaysStrict": true, | ||
"outDir": "./dist" | ||
}, | ||
"files": [ | ||
"main.ts" | ||
] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,76 +3,75 @@ | |
* SPDX-FileCopyrightText: 2020 Andy Holmes <[email protected]> | ||
* @source https://gitlab.gnome.org/GNOME/gjs/-/blob/master/examples/glistmodel.js | ||
*/ | ||
import GObject from 'gi://GObject?version=2.0'; | ||
import Gio from 'gi://Gio?version=2.0'; | ||
import GObject from 'gi://GObject?version=2.0' | ||
import Gio from 'gi://Gio?version=2.0' | ||
|
||
/** | ||
* An example of implementing the GListModel interface in GJS. The only real | ||
* requirement here is that the class be derived from some GObject. | ||
*/ | ||
export class IGjsListStore extends GObject.Object implements Gio.ListModel { | ||
|
||
_items: GObject.Object[] = []; | ||
_items: GObject.Object[] = [] | ||
|
||
_init() { | ||
super._init(); | ||
super._init() | ||
|
||
/* We'll use a native Array as internal storage for the list model */ | ||
this._items = []; | ||
this._items = [] | ||
} | ||
|
||
// TODO: It should not be necessary to implement this method | ||
get_item_type() { | ||
const res = GObject.Object.$gtype; | ||
print("get_item_type", res); | ||
return res; | ||
const res = GObject.Object.$gtype | ||
print('get_item_type', res) | ||
return res | ||
} | ||
|
||
// TODO: It should not be necessary to implement this method | ||
get_item(position: number) { | ||
const res = this._items[position] || null; | ||
print("get_item", res); | ||
return res; | ||
const res = this._items[position] || null | ||
print('get_item', res) | ||
return res | ||
} | ||
|
||
// TODO: It should not be necessary to implement this method | ||
items_changed(position: number, removed: number, added: number) { | ||
print(`items_changed position: ${position}, removed: ${removed}, added: ${added}`); | ||
print(`items_changed position: ${position}, removed: ${removed}, added: ${added}`) | ||
} | ||
|
||
// TODO: It should not be necessary to implement this method | ||
get_n_items() { | ||
const res = this._items.length; | ||
print("get_n_items", res); | ||
return res; | ||
const res = this._items.length | ||
print('get_n_items', res) | ||
return res | ||
} | ||
|
||
/* Implementing this function amounts to returning a GType. This could be a | ||
* more specific GType, but must be a subclass of GObject. | ||
*/ | ||
vfunc_get_item_type() { | ||
const res = GObject.Object.$gtype; | ||
print("vfunc_get_item_type", res); | ||
return res; | ||
const res = GObject.Object.$gtype | ||
print('vfunc_get_item_type', res) | ||
return res | ||
} | ||
|
||
/* Implementing this function just requires returning the GObject at | ||
* @position or %null if out-of-range. This must explicitly return %null, | ||
* not `undefined`. | ||
*/ | ||
vfunc_get_item(position: number) { | ||
const res = this._items[position] || null; | ||
print("vfunc_get_item", res); | ||
return res; | ||
const res = this._items[position] || null | ||
print('vfunc_get_item', res) | ||
return res | ||
} | ||
|
||
/* Implementing this function is as simple as return the length of the | ||
* storage object, in this case an Array. | ||
*/ | ||
vfunc_get_n_items() { | ||
const res = this._items.length; | ||
print("vfunc_get_n_items", res); | ||
return res; | ||
const res = this._items.length | ||
print('vfunc_get_n_items', res) | ||
return res | ||
} | ||
|
||
/** | ||
|
@@ -84,14 +83,12 @@ export class IGjsListStore extends GObject.Object implements Gio.ListModel { | |
* @param position - the position to add the item | ||
*/ | ||
insertItem(item: GObject.Object, position: number) { | ||
if (!(item instanceof GObject.Object)) | ||
throw new TypeError('not a GObject'); | ||
if (!(item instanceof GObject.Object)) throw new TypeError('not a GObject') | ||
|
||
if (position < 0 || position > this._items.length) | ||
position = this._items.length; | ||
if (position < 0 || position > this._items.length) position = this._items.length | ||
|
||
this._items.splice(position, 0, item); | ||
this.items_changed(position, 0, 1); | ||
this._items.splice(position, 0, item) | ||
this.items_changed(position, 0, 1) | ||
} | ||
|
||
/** | ||
|
@@ -100,13 +97,12 @@ export class IGjsListStore extends GObject.Object implements Gio.ListModel { | |
* @param item - the item to add | ||
*/ | ||
appendItem(item: GObject.Object) { | ||
if (!(item instanceof GObject.Object)) | ||
throw new TypeError('not a GObject'); | ||
if (!(item instanceof GObject.Object)) throw new TypeError('not a GObject') | ||
|
||
let position = this._items.length; | ||
let position = this._items.length | ||
|
||
this._items.push(item); | ||
this.items_changed(position, 0, 1); | ||
this._items.push(item) | ||
this.items_changed(position, 0, 1) | ||
} | ||
|
||
/** | ||
|
@@ -115,11 +111,10 @@ export class IGjsListStore extends GObject.Object implements Gio.ListModel { | |
* @param item - the item to add | ||
*/ | ||
prependItem(item: GObject.Object) { | ||
if (!(item instanceof GObject.Object)) | ||
throw new TypeError('not a GObject'); | ||
if (!(item instanceof GObject.Object)) throw new TypeError('not a GObject') | ||
|
||
this._items.unshift(item); | ||
this.items_changed(0, 0, 1); | ||
this._items.unshift(item) | ||
this.items_changed(0, 0, 1) | ||
} | ||
|
||
/** | ||
|
@@ -129,16 +124,14 @@ export class IGjsListStore extends GObject.Object implements Gio.ListModel { | |
* @param item - the item to remove | ||
*/ | ||
removeItem(item: GObject.Object) { | ||
if (!(item instanceof GObject.Object)) | ||
throw new TypeError('not a GObject'); | ||
if (!(item instanceof GObject.Object)) throw new TypeError('not a GObject') | ||
|
||
let position = this._items.indexOf(item); | ||
let position = this._items.indexOf(item) | ||
|
||
if (position === -1) | ||
return; | ||
if (position === -1) return | ||
|
||
this._items.splice(position, 1); | ||
this.items_changed(position, 1, 0); | ||
this._items.splice(position, 1) | ||
this.items_changed(position, 1, 0) | ||
} | ||
|
||
/** | ||
|
@@ -148,36 +141,37 @@ export class IGjsListStore extends GObject.Object implements Gio.ListModel { | |
* @param position - the position of the item to remove | ||
*/ | ||
removePosition(position: number) { | ||
if (position < 0 || position >= this._items.length) | ||
return; | ||
if (position < 0 || position >= this._items.length) return | ||
|
||
this._items.splice(position, 1); | ||
this.items_changed(position, 1, 0); | ||
this._items.splice(position, 1) | ||
this.items_changed(position, 1, 0) | ||
} | ||
|
||
/** | ||
* Clear the list of all items. | ||
*/ | ||
clear() { | ||
let length = this._items.length; | ||
let length = this._items.length | ||
|
||
if (length === 0) | ||
return; | ||
if (length === 0) return | ||
|
||
this._items = []; | ||
this.items_changed(0, length, 0); | ||
this._items = [] | ||
this.items_changed(0, length, 0) | ||
} | ||
} | ||
|
||
/** | ||
* An example of implementing the GListModel interface in GJS. The only real | ||
* requirement here is that the class be derived from some GObject. | ||
*/ | ||
export const GjsListStore = GObject.registerClass({ | ||
GTypeName: 'GjsListStore', | ||
Implements: [Gio.ListModel], | ||
}, IGjsListStore); | ||
|
||
// TODO: Expand the example which also demonstrates the use of the listStore | ||
const listStore = new GjsListStore(); | ||
listStore.insertItem(new GObject.Object(), 0); | ||
export const GjsListStore = GObject.registerClass( | ||
{ | ||
GTypeName: 'GjsListStore', | ||
Implements: [Gio.ListModel], | ||
}, | ||
IGjsListStore, | ||
) | ||
|
||
// TODO: Expand the example which also demonstrates the use of the listStore | ||
const listStore = new GjsListStore() | ||
listStore.insertItem(new GObject.Object(), 0) |
Oops, something went wrong.