ddgbasic 1.0.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- ddgbasic-1.0.0/LICENSE +21 -0
- ddgbasic-1.0.0/PKG-INFO +473 -0
- ddgbasic-1.0.0/README.md +442 -0
- ddgbasic-1.0.0/pyproject.toml +49 -0
- ddgbasic-1.0.0/setup.cfg +4 -0
- ddgbasic-1.0.0/src/ddgbasic.egg-info/PKG-INFO +473 -0
- ddgbasic-1.0.0/src/ddgbasic.egg-info/SOURCES.txt +14 -0
- ddgbasic-1.0.0/src/ddgbasic.egg-info/dependency_links.txt +1 -0
- ddgbasic-1.0.0/src/ddgbasic.egg-info/entry_points.txt +2 -0
- ddgbasic-1.0.0/src/ddgbasic.egg-info/requires.txt +9 -0
- ddgbasic-1.0.0/src/ddgbasic.egg-info/top_level.txt +5 -0
- ddgbasic-1.0.0/src/ddgbasic.py +14883 -0
- ddgbasic-1.0.0/src/ddgformgen.py +295 -0
- ddgbasic-1.0.0/src/ddgide.py +1277 -0
- ddgbasic-1.0.0/src/ddgreport.py +175 -0
- ddgbasic-1.0.0/src/ddgscreen.py +2205 -0
ddgbasic-1.0.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025-2026 Dan Bailey
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
ddgbasic-1.0.0/PKG-INFO
ADDED
|
@@ -0,0 +1,473 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: ddgbasic
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: A procedural BASIC around SQLite and DuckDB: SQL in the program, loops over query results, text screens and an IDE
|
|
5
|
+
Author: Dan Bailey
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/ddgflorida/DDGBasic
|
|
8
|
+
Project-URL: Documentation, https://github.com/ddgflorida/DDGBasic/blob/main/docs/manual/README.md
|
|
9
|
+
Project-URL: Examples, https://github.com/ddgflorida/DDGBasic/blob/main/examples/README.md
|
|
10
|
+
Project-URL: Issues, https://github.com/ddgflorida/DDGBasic/issues
|
|
11
|
+
Keywords: basic,sqlite,duckdb,sql,etl,interpreter
|
|
12
|
+
Classifier: Programming Language :: Python :: 3
|
|
13
|
+
Classifier: Programming Language :: Other
|
|
14
|
+
Classifier: Operating System :: OS Independent
|
|
15
|
+
Classifier: Environment :: Console
|
|
16
|
+
Classifier: Topic :: Database
|
|
17
|
+
Classifier: Topic :: Software Development :: Interpreters
|
|
18
|
+
Requires-Python: >=3.10
|
|
19
|
+
Description-Content-Type: text/markdown
|
|
20
|
+
License-File: LICENSE
|
|
21
|
+
Requires-Dist: requests
|
|
22
|
+
Requires-Dist: duckdb>=1.2
|
|
23
|
+
Requires-Dist: numpy
|
|
24
|
+
Requires-Dist: xlrd3
|
|
25
|
+
Requires-Dist: openpyxl
|
|
26
|
+
Requires-Dist: beautifulsoup4
|
|
27
|
+
Requires-Dist: lxml
|
|
28
|
+
Requires-Dist: xmltodict
|
|
29
|
+
Requires-Dist: pyarrow
|
|
30
|
+
Dynamic: license-file
|
|
31
|
+
|
|
32
|
+
# DDGBasic: A Data-Centric BASIC Interpreter and Procedural Language for SQLite and DuckDB
|
|
33
|
+
|
|
34
|
+

|
|
35
|
+

|
|
36
|
+

|
|
37
|
+

|
|
38
|
+
|
|
39
|
+
**DDGBasic wraps a procedural language around SQLite and DuckDB.** SQL is written straight into the program, query results come back as rows you can loop over, and program variables go into queries as bind variables (`:name`). Around the SQL you get what SQL lacks: variables, `IF` rules, loops, functions, error handling, files, HTTP and a text-mode UI.
|
|
40
|
+
|
|
41
|
+
- **Load, clean and check data in one statement:** `LOAD CSV` calls your own BASIC functions on every cell (`TRANSFORM phone WITH normalize_phone$`) and drops rows that fail a check (`VALIDATE email WITH is_valid_email`).
|
|
42
|
+
- **Rules over query results:** `FOR row IN (SELECT ...)` loops apply logic that is awkward in SQL (tiers, allocations, alerts) and write back with bind variables, inside transactions.
|
|
43
|
+
- **Two engines in one program:** SQLite for records (a file, constraints, transactions), DuckDB for analytics (columnar, fast, querying Parquet and CSV files directly), with `DATABASE ENGINE` to switch.
|
|
44
|
+
- **Results anywhere:** the same query to the console, CSV, JSON, Excel, Parquet, HTML or SQL, or to a grouped `REPORT`.
|
|
45
|
+
|
|
46
|
+
The language is a modern BASIC, and it comes with 1990s-style text screens and a QBasic-style IDE. See [Examples](#-examples) for programs that show this off.
|
|
47
|
+
|
|
48
|
+
---
|
|
49
|
+
|
|
50
|
+
## ✨ Key Features
|
|
51
|
+
|
|
52
|
+
DDGBasic combines the simplicity of classic BASIC syntax with powerful, modern features for today's data-driven world.
|
|
53
|
+
|
|
54
|
+
* ### Dual Database Engines
|
|
55
|
+
* **SQLite & DuckDB Support:** Seamlessly switch between the world's most deployed database engine (**SQLite**) for general-purpose tasks and a high-performance analytical engine (**DuckDB**) for complex queries.
|
|
56
|
+
* **SQL:** Directly embed SQL statements, iterate over resultsets.
|
|
57
|
+
* **Engine Switching:** Use the `DATABASE ENGINE [SQLITE|DUCKDB]` command to change the backend at any time within a script.
|
|
58
|
+
|
|
59
|
+
* ### Powerful Data Ingestion & Transformation
|
|
60
|
+
* **`LOAD` Command:** Ingest data from `.csv`, fixed-width, `.json`, `.jsonl`, `.xml`, `.parquet`, `.html`, and `.xls`/`.xlsx` (**Excel**) files into database tables or for file-to-file conversion.
|
|
61
|
+
* **First-class TRANSFORM and VALIDATE clauses:** Apply user-defined functions (UDFs) or built-ins per cell or per row during loading: `LOAD CSV "raw.csv" CREATE TABLE clean TRANSFORM phone WITH normalize_phone$ VALIDATE email WITH is_valid_email TRANSFORM ROW WITH derive_full_name`.
|
|
62
|
+
* **OPTIONS string:** Headers, delimiters, encoding, and simple built-in transform/validate rules (upper, lower, trim, REQUIRED, MINLENGTH, REGEX).
|
|
63
|
+
* **Field manipulation:** Select, rename (`fields=[Name] as N`), and exclude (`fields=*,-[Name]`) columns on the fly during data loading.
|
|
64
|
+
|
|
65
|
+
* ### User-Defined Functions
|
|
66
|
+
* **`FUNCTION ... END FUNCTION`:** Define your own functions with parameters and return values.
|
|
67
|
+
* **Local scope:** Parameters are local by shadow. Use `DIM` inside a function body to declare additional locals — outer same-named variables are preserved across the call.
|
|
68
|
+
* **Recursion:** Functions can call themselves; recursion is safe when locals are declared via `DIM`.
|
|
69
|
+
* **Early return:** `EXIT FUNCTION` returns immediately.
|
|
70
|
+
* **Call as statement or expression:** `log_event("started")` discards the return; `score = lead_score(row)` uses it.
|
|
71
|
+
|
|
72
|
+
* ### Higher-Order Functions
|
|
73
|
+
* **`FILTER`, `MAP`, `REDUCE`** accept either a UDF or a built-in by name: `MAP(words, UCASE$)`, `REDUCE(nums, MAX)`, `FILTER(leads, is_qualified)`.
|
|
74
|
+
* **`SORT array WITH fn`:** Sort by a function-computed key — `SORT names WITH UCASE$ ASC` for case-insensitive sort, or use a UDF for composite/numeric/custom keys.
|
|
75
|
+
* **Composition:** Pipelines like `REDUCE(MAP(FILTER(nums, is_even), square), add, 0)` work cleanly.
|
|
76
|
+
|
|
77
|
+
* ### 1990s-Style Text Screens
|
|
78
|
+
* Blue screens, boxes and data-entry forms the way they used to be: `CLS`, `COLOR 15, 1`, `BOX`, `@ 5, 10 SAY "Name: " GET name$ PICTURE "@!" VALID name$ <> ""`, `READ`, light-bar `MENU()` and a scrolling `BROWSE (SELECT ...)` that can edit cells in place (`EDIT`). Keyboard and mouse. No extra packages. See `examples/retro_contacts.bas`, and the short `contact`, `form_demo`, `menu_demo`, `grid_demo`, `orders_demo`, `invoice_demo`, `progress_demo`, `themes_demo`, `report_demo`, `notes_demo` and `mouse_demo` examples.
|
|
79
|
+
|
|
80
|
+
* ### A QBasic-style IDE
|
|
81
|
+
* `ddgbasic --ide program.bas` opens a full-screen editor with syntax colouring and a menu bar. F5 runs the program and, if it stops with an error, puts the cursor on the error's line; F1 shows the help for the keyword under the cursor, the Immediate window (F6) runs a line at a time (`? x`, a quick `SELECT`), and F9/F8 set breakpoints and step through the program, with the Immediate window seeing its variables.
|
|
82
|
+
|
|
83
|
+
* ### String Interpolation
|
|
84
|
+
* Backtick-delimited strings (`` ` ``) support `${expr}` interpolation: `` `Hello, ${name$}! Total: ${FORMAT$(amount, "$#,##0.00")}` ``.
|
|
85
|
+
* Full expressions allowed inside `${...}` — including UDF calls, hash lookups, arithmetic.
|
|
86
|
+
* Lone `{` and `}` remain literal (so JSON, code snippets, and regex survive intact).
|
|
87
|
+
* `$$` produces a literal `$`. Double-quoted strings are unaffected (no interpolation).
|
|
88
|
+
|
|
89
|
+
* ### Modern Connectivity & Tooling
|
|
90
|
+
* **`FETCH` Command:** HTTP `GET`/`POST`/`PUT`/`PATCH`/`DELETE`. Send a hash as the body, attach custom request headers, upload files (multipart), capture the response into a variable or file, and optionally capture response headers as a hash.
|
|
91
|
+
* **`SHELL` Command:** Execute shell commands directly from the script.
|
|
92
|
+
* **Data Analysis:** `ANALYZE [CSV|JSON|JSONL|FIXED|TEXT|XML]` commands provide detailed statistical reports and schema information about local files.
|
|
93
|
+
* **Format Conversion:** `LOAD` combined with `SET OUTPUT FORMAT [format]` and a `SELECT` statement converts files between formats.
|
|
94
|
+
|
|
95
|
+
* ### Rich Language & SQL Integration
|
|
96
|
+
* **Full control flow:** `IF...THEN...ELSE...END IF`, `FOR...TO...NEXT`, `WHILE...WEND`, `DO...LOOP`, `FOR EACH`.
|
|
97
|
+
* **Row-streaming `FOR ... IN`:** Iterate over CSV, JSON, JSONL, files, text lines, or a SQL result set — `FOR row IN (SELECT * FROM sales) ... NEXT`.
|
|
98
|
+
* **`EXIT` statements:** Reliably exit any loop (`EXIT FOR`, `EXIT WHILE`, `EXIT DO`), even from within nested blocks.
|
|
99
|
+
* **Direct SQL execution:** Run any SQL query directly. Supports transactions (`BEGIN`, `COMMIT`, `ROLLBACK`) and logical checks like `IF EXISTS (...)`.
|
|
100
|
+
* **Embedded subqueries:** Use scalar SQL subqueries directly in assignment statements: `LET count = (SELECT COUNT(*) FROM my_table;)`.
|
|
101
|
+
* **Modern data types:** `HASH` (dictionary) and dynamic `ARRAY`, with a rich library of built-in functions.
|
|
102
|
+
|
|
103
|
+
---
|
|
104
|
+
|
|
105
|
+
## 📦 Installation
|
|
106
|
+
|
|
107
|
+
DDGBasic needs Python 3.10 or newer.
|
|
108
|
+
|
|
109
|
+
```bash
|
|
110
|
+
pip install ddgbasic
|
|
111
|
+
ddgbasic examples/hello.bas # run a script
|
|
112
|
+
ddgbasic # interactive REPL
|
|
113
|
+
ddgbasic --ide examples/contact.bas # the QBasic-style IDE: F5 runs, F1 helps
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
To run from a copy of the source instead, install the dependencies with `pip install -r requirements.txt` and use `python3 src/ddgbasic.py` in place of `ddgbasic`. `pip install .` in the copy installs the `ddgbasic` command from it.
|
|
117
|
+
|
|
118
|
+
To build a standalone executable, install `requirements-build.txt` and run `./compilenuitka.sh` (macOS/Linux; installs to `~/.local/bin`) or `compilenuitka.bat` (Windows; installs to `%USERPROFILE%\bin`). Both build `src/ddgbasic.py` from any folder and take another install folder as an argument, for example `compilenuitka.bat d:\tools`. Add the install folder to your `PATH` to run `ddgbasic` from anywhere. The build bundles the DuckDB of the Python that runs it, so both scripts stop if that DuckDB is older than 1.2 (`pip install --upgrade duckdb` fixes it).
|
|
119
|
+
|
|
120
|
+
The full **Programmer's Reference Manual** is in [`docs/manual/`](https://github.com/ddgflorida/DDGBasic/blob/main/docs/manual/README.md). Run the test suite with `python3 tests/run_tests.py`.
|
|
121
|
+
|
|
122
|
+
---
|
|
123
|
+
|
|
124
|
+
## 🚀 Quick Start Example
|
|
125
|
+
|
|
126
|
+
The following DDGBasic script demonstrates several key features: it downloads a CSV file, loads it into a DuckDB in-memory table, and queries the result.
|
|
127
|
+
|
|
128
|
+
```basic
|
|
129
|
+
REM --- Set engine to DuckDB for high-speed analytics ---
|
|
130
|
+
DATABASE ENGINE DUCKDB
|
|
131
|
+
DATABASE OPEN ":memory:"
|
|
132
|
+
|
|
133
|
+
REM --- Download a CSV and create a table from it in one command ---
|
|
134
|
+
PRINT "Fetching and loading data..."
|
|
135
|
+
CREATE TABLE domains AS
|
|
136
|
+
SELECT * FROM read_csv_auto('https://raw.githubusercontent.com/cisagov/dotgov-data/main/current-full.csv');
|
|
137
|
+
|
|
138
|
+
REM --- Run a query on the loaded data ---
|
|
139
|
+
PRINT "Top 5 States with the most .gov domains:"
|
|
140
|
+
SELECT State, COUNT(*) AS DomainCount
|
|
141
|
+
FROM domains
|
|
142
|
+
GROUP BY State
|
|
143
|
+
ORDER BY DomainCount DESC
|
|
144
|
+
LIMIT 5;
|
|
145
|
+
|
|
146
|
+
DATABASE CLOSE
|
|
147
|
+
END
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
---
|
|
151
|
+
|
|
152
|
+
## 🧩 ETL Pipeline Example
|
|
153
|
+
|
|
154
|
+
This shows the declarative ETL style enabled by UDFs and first-class TRANSFORM/VALIDATE clauses.
|
|
155
|
+
|
|
156
|
+
```basic
|
|
157
|
+
FUNCTION normalize_phone$(p$)
|
|
158
|
+
DIM digits$
|
|
159
|
+
digits$ = ""
|
|
160
|
+
FOR i = 1 TO LEN(p$)
|
|
161
|
+
c$ = MID$(p$, i, 1)
|
|
162
|
+
IF ISDIGIT(c$) THEN digits$ = digits$ & c$
|
|
163
|
+
NEXT
|
|
164
|
+
IF LEN(digits$) = 11 AND LEFT$(digits$, 1) = "1" THEN digits$ = MID$(digits$, 2, 10)
|
|
165
|
+
IF LEN(digits$) = 10 THEN
|
|
166
|
+
normalize_phone$ = "(" & LEFT$(digits$,3) & ") " & MID$(digits$,4,3) & "-" & RIGHT$(digits$,4)
|
|
167
|
+
ELSE
|
|
168
|
+
normalize_phone$ = ""
|
|
169
|
+
END IF
|
|
170
|
+
END FUNCTION
|
|
171
|
+
|
|
172
|
+
FUNCTION is_valid_email(addr$)
|
|
173
|
+
is_valid_email = 0
|
|
174
|
+
at_pos = INSTR(addr$, "@")
|
|
175
|
+
IF at_pos < 2 THEN EXIT FUNCTION
|
|
176
|
+
IF INSTR(MID$(addr$, at_pos+1, LEN(addr$)), ".") = 0 THEN EXIT FUNCTION
|
|
177
|
+
is_valid_email = -1
|
|
178
|
+
END FUNCTION
|
|
179
|
+
|
|
180
|
+
DATABASE ENGINE SQLITE
|
|
181
|
+
DATABASE OPEN "leads.sqlite"
|
|
182
|
+
|
|
183
|
+
LOAD CSV "raw_leads.csv" CREATE TABLE leads _
|
|
184
|
+
OPTIONS "header=true" _
|
|
185
|
+
TRANSFORM name WITH PROPER$ _
|
|
186
|
+
TRANSFORM phone WITH normalize_phone$ _
|
|
187
|
+
VALIDATE email WITH is_valid_email
|
|
188
|
+
|
|
189
|
+
PRINT `Imported ${(SELECT COUNT(*) FROM leads;)} clean rows.`
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
---
|
|
193
|
+
|
|
194
|
+
## 🗂️ Examples
|
|
195
|
+
|
|
196
|
+
The `examples/` folder has some 60 programs; [`examples/README.md`](https://github.com/ddgflorida/DDGBasic/blob/main/examples/README.md) lists them all. These show what DDGBasic is for:
|
|
197
|
+
|
|
198
|
+
| Example | Shows |
|
|
199
|
+
|---|---|
|
|
200
|
+
| [`etl_pipeline.bas`](https://github.com/ddgflorida/DDGBasic/blob/main/examples/etl_pipeline.bas) | A messy CSV becomes a clean table: BASIC functions clean every cell as `LOAD` reads it and drop bad rows; BASIC rules flag duplicates and assign customer tiers; SQL totals; JSON, Excel and a grouped report out |
|
|
201
|
+
| [`duckdb_analytics.bas`](https://github.com/ddgflorida/DDGBasic/blob/main/examples/duckdb_analytics.bas) | Half a million rows in DuckDB, queried straight from Parquet and CSV files, window functions, and BASIC rules (targets per region, in a hash) over the results, with timings |
|
|
202
|
+
| [`two_engines.bas`](https://github.com/ddgflorida/DDGBasic/blob/main/examples/two_engines.bas) | SQLite keeps the records (constraints, a transaction), DuckDB analyses them from a Parquet file (median, best month), and the results go back to SQLite |
|
|
203
|
+
| [`row_logic.bas`](https://github.com/ddgflorida/DDGBasic/blob/main/examples/row_logic.bas) | Allocating limited stock to orders by priority, row by row, with all-or-nothing and partial rules, in a transaction that `ON ERROR` rolls back |
|
|
204
|
+
| [`invoice_demo.bas`](https://github.com/ddgflorida/DDGBasic/blob/main/examples/invoice_demo.bas) | A 1990s-style invoice screen on the Chinook database: a header form, a lines grid, business rules |
|
|
205
|
+
| [`retro_contacts.bas`](https://github.com/ddgflorida/DDGBasic/blob/main/examples/retro_contacts.bas) | A complete text-mode application: menu bar, editable grid, forms, memo editor, report |
|
|
206
|
+
|
|
207
|
+
Run one with `ddgbasic examples/etl_pipeline.bas`, or open it in the IDE with `ddgbasic --ide examples/etl_pipeline.bas`.
|
|
208
|
+
|
|
209
|
+
---
|
|
210
|
+
|
|
211
|
+
## 📜 Statements Reference
|
|
212
|
+
|
|
213
|
+
A summary. The [Programmer's Reference Manual](https://github.com/ddgflorida/DDGBasic/blob/main/docs/manual/README.md) has the full syntax, options and examples for every statement and function.
|
|
214
|
+
|
|
215
|
+
| Statement Keyword | Description |
|
|
216
|
+
|-------------------------|--------------------------------------------------------|
|
|
217
|
+
| @ ... SAY ... GET | Writes text at a screen position (`SAY`) and adds an entry field (`GET`) for a variable, a hash field such as `rec.name`, or an array element, with optional `PICTURE`, `VALID ... MESSAGE`, `WHEN` and `LOOKUP (SELECT ...)` clauses, date fields (`@D`), numeric masks, `CHECKBOX` and drop-down `LIST` fields, and `HINT` help lines. See `READ`. |
|
|
218
|
+
| @ ... BUTTON | Adds a `[ label ]` button to a form; pressing it ends `READ`, and `BUTTON$` returns its label (`CANCEL` buttons put the old values back). |
|
|
219
|
+
| ANALYZE CSV | Provides a detailed statistical report on a CSV file, including delimiter detection, header presence, and column data types. |
|
|
220
|
+
| ANALYZE FIXED | Analyzes a fixed-width text file, automatically guessing column breaks if not specified, and reports on the layout. |
|
|
221
|
+
| ANALYZE JSON | Analyzes a JSON file, reporting on its structure, record count, and the consistency of object keys. |
|
|
222
|
+
| ANALYZE JSONL | Analyzes a JSON Lines file, reporting on structural consistency, and counting valid and invalid JSON objects. |
|
|
223
|
+
| ANALYZE TEXT | Provides a statistical analysis of a plain text file, including character, word, and line counts, encoding, and newline style. |
|
|
224
|
+
| ANALYZE XML | Analyzes an XML file to determine its structure, infer the primary record tag, and list its fields. |
|
|
225
|
+
| BELL | Emits an audible system beep sound. |
|
|
226
|
+
| BOX | Draws a single- or double-line box with an optional title and `SHADOW` on the text screen. Pop-ups have drop shadows unless `SET SHADOW OFF`. |
|
|
227
|
+
| BROWSE | Shows query results in a scrolling grid; `INTO var` receives the chosen row as a hash. With `EDIT`, cells are edited in place and saved to the table, Ins adds a row and Del deletes one. Click a heading (or F3) to sort, type to jump to a row; `FREEZE`, `FORMAT` and `COLOR` set frozen columns, number masks and row colours. `DETAIL` adds a second grid for the rows of the current one (an order's lines). |
|
|
228
|
+
| BROWSER | Opens a specified URL in the system's default web browser. |
|
|
229
|
+
| CHAIN | Transfers program execution to a different DDGBasic script, optionally preserving variables. |
|
|
230
|
+
| CHDIR | Changes the current working directory. |
|
|
231
|
+
| CLEAR | Deletes all variables. User-defined functions stay defined. |
|
|
232
|
+
| CLOSE | Closes a specific file handle or all open file handles. |
|
|
233
|
+
| CLS | Clears the screen in the current colours. |
|
|
234
|
+
| COLOR | Sets the text colours (0-15) and the colours of entry fields and menu bars. |
|
|
235
|
+
| COPY ... AS | Copies a source file to a destination file. |
|
|
236
|
+
| DATABASE | Manages the database connection, allowing you to open a file-based database or switch the database engine (SQLite/DuckDB). |
|
|
237
|
+
| DESCRIBE | Lists a table's columns and types. Use `SHOW CREATE TABLE` for the CREATE TABLE statement. |
|
|
238
|
+
| DIM | Declares a variable (scalar, ARRAY, or HASH). When used inside a FUNCTION body, the declared name is scoped to the function and the outer variable of the same name is preserved across the call. |
|
|
239
|
+
| DO ... LOOP | Defines a block of code that executes repeatedly, with optional WHILE or UNTIL conditions at the beginning or end. |
|
|
240
|
+
| DUMP | A debugging command to print the internal state of the interpreter, such as tokens, variables, or labels. |
|
|
241
|
+
| EDIT RECORD | A one-line entry form: one labelled field per column of a query's row, saved with UPDATE (or INSERT when there is no row). |
|
|
242
|
+
| EDIT TEXT | A boxed memo editor for a multi-line string (a variable or a field such as `rec.notes`); Ctrl-W saves, Esc cancels. |
|
|
243
|
+
| EMAIL | Sends an email using the configured provider (see `HELP SET EMAIL`), with support for HTML body, CC/BCC, and attachments. |
|
|
244
|
+
| END | Terminates the program execution. |
|
|
245
|
+
| ERROR | Triggers a user-defined runtime error with a specific error code and optional message. |
|
|
246
|
+
| EVAL | Executes a DDGBasic source string as code. |
|
|
247
|
+
| EXECUTE | Executes a SQL statement that is dynamically constructed in a string variable. |
|
|
248
|
+
| EXIT | Immediately exits the current loop structure (`EXIT FOR`, `EXIT DO`, `EXIT WHILE`) or function (`EXIT FUNCTION`). |
|
|
249
|
+
| FETCH | Performs an HTTP request (GET, POST, PUT, PATCH, or DELETE). Supports request body hashes, custom request headers, multipart file uploads, INTO var$ or TO FILE destinations, and optional `HEADERS INTO h` capture of response headers. |
|
|
250
|
+
| FILES | Lists files and directories in the filesystem, similar to DIR or ls, with options for recursion and details. |
|
|
251
|
+
| FOR ... NEXT | Iterates a set number of times, over the results of a SQL query, or through records in a CSV, JSON, JSONL, TEXT, or FILES list. |
|
|
252
|
+
| FOR EACH ... NEXT | Iterates over each key in a HASH variable. |
|
|
253
|
+
| FUNCTION ... END FUNCTION | Defines a user-defined function. Parameters are local (shadow outer same-named variables). Use `DIM` inside the body for additional locals. The function returns the value of its own name. `EXIT FUNCTION` returns early. |
|
|
254
|
+
| GOSUB ... RETURN | Jumps to a labeled subroutine and returns to the next statement after the GOSUB call. |
|
|
255
|
+
| GOTO | Unconditionally jumps program execution to a specified label. |
|
|
256
|
+
| HELP | Help system when running in interactive mode. |
|
|
257
|
+
| IF ... THEN ... ELSE ... END IF | Executes blocks of code conditionally. |
|
|
258
|
+
| INPUT | Prompts the user for input from the console and stores it in a variable. |
|
|
259
|
+
| KILL | Deletes a file from the filesystem. |
|
|
260
|
+
| LET | Assigns a value to a variable (the LET keyword is optional). |
|
|
261
|
+
| LINE INPUT | Reads a single line of text from an open file into a variable. |
|
|
262
|
+
| LOAD | Loads data from a file (CSV, JSON, JSONL, XML, HTML, FIXED, EXCEL, PARQUET, TEXT) into a database table. Supports first-class `TRANSFORM col WITH fn`, `VALIDATE col WITH fn`, `TRANSFORM ROW WITH fn`, `VALIDATE ROW WITH fn` clauses. |
|
|
263
|
+
| LOCATE | Moves the cursor to a row and column. |
|
|
264
|
+
| MAKE FORM | Writes a complete data-entry program for a table: menu bar, editable grid, and an entry form with fields chosen from the column types (dates, number masks, check boxes, drop-downs for foreign keys). |
|
|
265
|
+
| MKDIR | Creates a new directory. |
|
|
266
|
+
| NAME ... AS | Renames a file. |
|
|
267
|
+
| ON ERROR GOTO | Specifies a label to jump to when a runtime error occurs. |
|
|
268
|
+
| ON KEY | Makes a key (F1, CTRL-S, ALT-H, ...) run a FUNCTION whenever the program waits for a key, in any form, grid or menu. |
|
|
269
|
+
| OPEN | Opens a file for reading, writing, or appending, assigning it a file handle. |
|
|
270
|
+
| POP | Removes the last element from an array, optionally storing it in a variable. |
|
|
271
|
+
| PRINT | Outputs text, variables, or expressions to the console or an open file. |
|
|
272
|
+
| PROGRESS | Shows a centred box with a progress bar and percentage for a long job; `PROGRESS OFF` removes it. |
|
|
273
|
+
| PUSH | Adds a new element to the end of an array. |
|
|
274
|
+
| READ | Edits the pending `@ ... GET` fields; Esc restores the original values. |
|
|
275
|
+
| REPORT | Turns a query into a report with a title, group headings, subtotals, totals and pages, to the screen, a file, `VIEW` or a string. |
|
|
276
|
+
| RESTSCREEN | Puts back a screen area saved with `SAVESCREEN()`. |
|
|
277
|
+
| READ FILE | Reads the entire content of a text file into a single string variable. |
|
|
278
|
+
| REDIM | Resizes a previously declared ARRAY. |
|
|
279
|
+
| RESUME | Used within an error-handling routine to resume program execution at the statement after the one that caused the error. |
|
|
280
|
+
| REVERSE | Reverses the order of elements in an array. |
|
|
281
|
+
| RMDIR | Removes an empty directory. |
|
|
282
|
+
| RUN | Executes another DDGBasic script as a subroutine and returns control to the calling script upon completion. |
|
|
283
|
+
| SET | Configures global settings for the interpreter, such as OUTPUT redirection, output FORMAT, EMAIL provider, SQL_FATAL_ERRORS, or HASH_KEYS handling. `SET THEME "classic"` sets the screen colours from a named theme. |
|
|
284
|
+
| SHELL | Executes a command in the underlying operating system shell. |
|
|
285
|
+
| SHIFT | Removes the first element from an array, optionally storing it in a variable. |
|
|
286
|
+
| SHOW | Displays database schema information, such as `SHOW TABLES` or `SHOW INDEXES`. Also `SHOW VARIABLES`. |
|
|
287
|
+
| SORT | Sorts an array in-place. Use `ON "key"` to sort an array of hashes by a key. Use `WITH fn` to sort by a function-computed key (UDF or built-in). Optional `ASC` / `DESC`. |
|
|
288
|
+
| SPLICE | Modifies an array by removing, replacing, and/or adding elements at a specific index. |
|
|
289
|
+
| SQL Statement | Any line starting with a SQL keyword (e.g., SELECT, INSERT, UPDATE) is executed directly against the current database. Must end in semi-colon. |
|
|
290
|
+
| TROFF | Turns off (Trace Off) the line-by-line execution trace. |
|
|
291
|
+
| TRON | Turns on (Trace On) a line-by-line execution trace for debugging. |
|
|
292
|
+
| UNSHIFT | Adds a new element to the beginning of an array. |
|
|
293
|
+
| UNZIP | Extracts files from a zip archive into a specified directory. |
|
|
294
|
+
| VIEW | Shows a file (`VIEW FILE`), a query or a string in a read-only, scrolling box with search (`/`, `n`). |
|
|
295
|
+
| WHILE ... WEND | Executes a block of code as long as a specified condition is true. |
|
|
296
|
+
| WRITE | Writes a comma-separated list of expressions to the console or a file, automatically quoting strings. |
|
|
297
|
+
| ZIP | Creates a zip archive from a list of specified files. |
|
|
298
|
+
|
|
299
|
+
---
|
|
300
|
+
|
|
301
|
+
# DDGBasic Interpreter: Functions
|
|
302
|
+
|
|
303
|
+
This document provides a quick reference to all available functions in the DDGBasic language, categorized by function type.
|
|
304
|
+
|
|
305
|
+
| Function Name | Type | Description |
|
|
306
|
+
|-------------------------|-------------|-------------|
|
|
307
|
+
| ABS(number) | MATH | Returns the absolute value of a number. |
|
|
308
|
+
| ALERT(message$, [button$, ...]) | SCREEN | Shows a message box with buttons and returns the chosen button number (0 for Esc). |
|
|
309
|
+
| ARRAY(...) | ARRAY | A constructor that creates and returns a new ARRAY from the provided arguments. |
|
|
310
|
+
| ARRAY_JOIN(array, [delimiter$]) | ARRAY | Concatenates the elements of an array into a single string, separated by delimiter$ (default comma). |
|
|
311
|
+
| ARRAY_SIZE(array) | ARRAY | Returns the total number of elements in an array. |
|
|
312
|
+
| ASC(string$) | STRING | Returns the ASCII code of the first character in the string. |
|
|
313
|
+
| ATN(number) | MATH | Returns the arctangent of a number in radians. |
|
|
314
|
+
| ATAN2(y, x) | MATH | Returns the arctangent of y/x in radians. |
|
|
315
|
+
| BASENAME$(path$) | FILE | Returns the filename portion of a path. |
|
|
316
|
+
| BUTTON$ | SCREEN | The label of the button that ended the last `READ` ("" if none). |
|
|
317
|
+
| CARDINAL$(number) | STRING | Returns the English cardinal words for a number (e.g. 12 → "twelve", 1234 → "one thousand two hundred thirty-four"). Negative numbers prefix "negative". Decimals are spelled digit-by-digit after "point". |
|
|
318
|
+
| CEIL(number) | MATH | Rounds a number up to the nearest integer. |
|
|
319
|
+
| CENTER$(string$, width, [pad_char$]) | STRING | Centers a string within a field of the given width, padded with pad_char$ (default space). |
|
|
320
|
+
| CHR$(code) | STRING | Returns the character corresponding to the given ASCII code. |
|
|
321
|
+
| COMMAND$(index) | INFO | Returns the command-line argument at the specified index position. |
|
|
322
|
+
| CONTAINS(string$, substring$) | STRING | Returns true (-1) if string$ contains substring$, otherwise false (0). |
|
|
323
|
+
| COS(number) | MATH | Returns the cosine of an angle given in radians. |
|
|
324
|
+
| CURDIR$() | FILE | Returns the current working directory as a string. |
|
|
325
|
+
| DATE$() | DATE/TIME | Returns the current system date as a "YYYY-MM-DD" string. |
|
|
326
|
+
| DATEADD(date$, days) | DATE/TIME | Adds a specified number of days to a date$ and returns the new date string. |
|
|
327
|
+
| DATEDIFF(date1$, date2$)| DATE/TIME | Returns the number of days between two date strings. |
|
|
328
|
+
| DATESERIAL(year, month, day) | DATE/TIME | Returns a date string built from year, month, and day numbers. |
|
|
329
|
+
| DAY(date$) | DATE/TIME | Returns the day of the month (1-31) from a date string. |
|
|
330
|
+
| DAYSINMONTH(month, year) | DATE/TIME | Returns the number of days in the given month and year. (year, month) is also accepted. |
|
|
331
|
+
| DAYSINYEAR(year) | DATE/TIME | Returns 365 or 366 depending on whether the year is a leap year. |
|
|
332
|
+
| DEGREES(radians) | MATH | Converts an angle from radians to degrees. |
|
|
333
|
+
| DISKSPACE(path$) | FILE | Returns the number of free bytes on the disk containing the specified path. |
|
|
334
|
+
| ENDSWITH(string$, suffix$) | STRING | Returns true (-1) if string$ ends with suffix$, otherwise false (0). |
|
|
335
|
+
| ENVIRON$(var_name$) | INFO | Returns the value of a system environment variable. |
|
|
336
|
+
| EOF(file_num) | FILE | Returns true (-1) if the end of the specified file handle has been reached, otherwise false (0). |
|
|
337
|
+
| EXP(number) | MATH | Returns e (the base of natural logarithms) raised to the power of number. |
|
|
338
|
+
| EXTRACT$(string$, position, [delimiter$]) | STRING | Returns the field at position (1-based) when string$ is split on delimiter$ (default comma). |
|
|
339
|
+
| FILE_EXISTS(path$) | FILE | Returns true (-1) if the specified file or directory path exists, otherwise false (0). |
|
|
340
|
+
| FILEATTR(path$) | FILE | Returns a number representing the file's attributes (e.g., read-only, directory). |
|
|
341
|
+
| FILESIZE(path$) | FILE | Returns the size of the specified file in bytes. Returns -1 if the file doesn't exist. |
|
|
342
|
+
| FILETIME(path$) | FILE | Returns the last modification timestamp of the file as a string (e.g., "YYYY-MM-DD HH:MI:SS"). |
|
|
343
|
+
| FILTER(array, criteria) | ARRAY/HOF | Returns a new array of elements matching criteria. The criteria can be a substring (case-sensitive match against str(item)) OR a bare function name (UDF or built-in) called with each item. Optional third arg = 0 inverts (returns non-matches). |
|
|
344
|
+
| FIND(array, value) | ARRAY | Returns the zero-based index of the first occurrence of value in an array. Returns -1 if not found. |
|
|
345
|
+
| FIX(number) | MATH | Truncates the decimal part of a number. |
|
|
346
|
+
| FLOOR(number) | MATH | Rounds a number down to the nearest integer. |
|
|
347
|
+
| FORMAT$(value, mask$) | STRING | Formats a value according to a numeric mask (e.g. `"#,##0.00"`, `"$#,##0"`, `"0.00%"`). |
|
|
348
|
+
| FORMATDATE$(date$, output_mask$, [input_mask$]) | DATE/TIME | Formats a date string according to a specified mask (e.g. "YYYY-MM-DD"). Optional input_mask$ tells DDGBasic how to parse the input. |
|
|
349
|
+
| FREEFILE() | FILE | Returns the next available integer for use as a file handle. |
|
|
350
|
+
| HASH_COUNT(hash) | HASH | Returns the number of key-value pairs in a hash. |
|
|
351
|
+
| HASH_DELETE(hash, key$) | HASH | Deletes a key-value pair from a hash. Use it in an expression (`r = HASH_DELETE(h, k$)`); it returns -1 if the key was deleted, 0 if it was not present. |
|
|
352
|
+
| HASH_EXISTS(hash, key$) | HASH | Returns true (-1) if the key$ exists in the hash, otherwise false (0). |
|
|
353
|
+
| HASH_JOIN(hash1, hash2, ...) | HASH | Merges two or more hashes into a new hash. Keys from later hashes overwrite earlier ones. |
|
|
354
|
+
| HASH_KEYS(hash) | HASH | Returns an ARRAY containing all the keys from a hash. |
|
|
355
|
+
| HASH_RENAME(hash, old_key$, new_key$) | HASH | Renames a key in a hash. |
|
|
356
|
+
| HASH_VALUES(hash) | HASH | Returns an ARRAY containing all the values from a hash. |
|
|
357
|
+
| HEX$(number) | STRING | Returns the hexadecimal representation of a number as a string. |
|
|
358
|
+
| HTMLDECODE$(string$) | STRING | Decodes HTML entities back to characters. |
|
|
359
|
+
| HTMLENCODE$(string$) | STRING | Encodes a string for safe inclusion in HTML. |
|
|
360
|
+
| INKEY$ / INKEY$(seconds) | SCREEN | Returns the key pressed ("" if none). INKEY$(0) waits for a key. Special keys come back as names such as UP or F1. |
|
|
361
|
+
| INSTR([start_pos,] haystack$, needle$) | STRING | Finds the starting position of needle$ within haystack$. Returns 0 if not found. |
|
|
362
|
+
| INSTRREV(haystack$, needle$, [start]) | STRING | Like INSTR but searches from the end. start limits where the search ends. |
|
|
363
|
+
| INT(number) | MATH | Returns the integer portion of a number by rounding down (same as FLOOR). |
|
|
364
|
+
| IS_ARRAY(variable) | ARRAY | Returns true (-1) if the variable is an ARRAY, otherwise false (0). |
|
|
365
|
+
| IS_HASH(variable) | HASH | Returns true (-1) if the variable is a HASH, otherwise false (0). |
|
|
366
|
+
| ISALNUM(string$) | STRING | Returns true (-1) if all characters in the string are alphanumeric, otherwise false (0). |
|
|
367
|
+
| ISALPHA(string$) | STRING | Returns true (-1) if all characters in the string are alphabetic, otherwise false (0). |
|
|
368
|
+
| ISDATE(string$) | DATE/TIME | Returns true (-1) if the string parses as a date, otherwise false (0). |
|
|
369
|
+
| ISDIGIT(string$) | STRING | Returns true (-1) if all characters in the string are digits, otherwise false (0). |
|
|
370
|
+
| ISLEAP(year) | DATE/TIME | Returns true (-1) if the year is a leap year, otherwise false (0). |
|
|
371
|
+
| ISNUMERIC(string$) | STRING | Returns true (-1) if the string parses as a number, otherwise false (0). |
|
|
372
|
+
| JSON_SERIALIZE$(variable, [indent], [options...]) | HASH/ARRAY | Converts a DDGBasic HASH or ARRAY into a JSON formatted string. |
|
|
373
|
+
| LASTKEY$ | SCREEN | The key that ended the last READ, MENU or BROWSE. |
|
|
374
|
+
| LCASE$(string$) | STRING | Converts a string to all lowercase characters. |
|
|
375
|
+
| LEFT$(string$, length) | STRING | Returns the first length characters from the left of the string. |
|
|
376
|
+
| LEN(value) | STRING | Returns the number of characters in the string representation of a value. |
|
|
377
|
+
| LOG(number) | MATH | Returns the natural logarithm of a number. |
|
|
378
|
+
| LTRIM$(string$) | STRING | Removes whitespace from the beginning (left side) of a string. |
|
|
379
|
+
| MAP(array, fn) | ARRAY/HOF | Returns a new array with each element passed through fn (a UDF or built-in name). |
|
|
380
|
+
| MAX(num1, num2, ...) | MATH | Returns the largest number from a list of arguments. |
|
|
381
|
+
| MENU(row, col, item$, ...) | SCREEN | Shows a light-bar menu and returns the chosen item number (0 for Esc). |
|
|
382
|
+
| MENUBAR$([row,] "Title:item|...", ...) | SCREEN | Shows a menu bar with pull-down menus and returns "Title.Item" ("" for Esc). |
|
|
383
|
+
| MID$(string$, start_pos, [length]) | STRING | Returns a substring of a specified length starting from start_pos. |
|
|
384
|
+
| MIN(num1, num2, ...) | MATH | Returns the smallest number from a list of arguments. |
|
|
385
|
+
| MOD(number1, number2) | MATH | Returns the remainder of number1 divided by number2. |
|
|
386
|
+
| MONTH(date$) | DATE/TIME | Returns the month (1-12) from a date string. |
|
|
387
|
+
| MONTHCAL$(year, month) | DATE/TIME | Returns a calendar of the given month as a multi-line string. |
|
|
388
|
+
| MONTHNAME$(month_num) | DATE/TIME | Returns the English name of the given month (1-12). |
|
|
389
|
+
| MOUSECOL | SCREEN | The column of the last mouse click or wheel turn. |
|
|
390
|
+
| MOUSEROW | SCREEN | The row of the last mouse click or wheel turn. |
|
|
391
|
+
| NOW() | DATE/TIME | Returns the current date and time as "YYYY-MM-DD HH:MI:SS". |
|
|
392
|
+
| NVL(value, default, ...) | UTILITY | Returns the first argument that is not empty (`""` or 0). |
|
|
393
|
+
| OCT$(number) | STRING | Returns the octal representation of a number as a string. |
|
|
394
|
+
| ORDINAL$(number) | STRING | Returns the English ordinal words for a number (e.g. 1 → "first", 21 → "twenty-first", 100 → "one hundredth"). |
|
|
395
|
+
| PADLEFT$(text$, length, pad_char$) | STRING | Pads a string on the left to a total length using pad_char$. |
|
|
396
|
+
| PADRIGHT$(text$, length, pad_char$) | STRING | Pads a string on the right to a total length using pad_char$. |
|
|
397
|
+
| PARSEJSON(string$) | HASH/ARRAY | Parses a JSON string into a HASH or ARRAY. |
|
|
398
|
+
| PATHNAME$(path$) | FILE | Returns the directory portion of a path. |
|
|
399
|
+
| POWER(base, exponent) | MATH | Returns the value of base raised to the power of exponent. |
|
|
400
|
+
| PROPER$(string$) | STRING | Converts a string to title case (e.g., "hello world" becomes "Hello World"). |
|
|
401
|
+
| RADIANS(degrees) | MATH | Converts an angle from degrees to radians. |
|
|
402
|
+
| REDUCE(array, fn, [initial]) | ARRAY/HOF | Folds an array into a single value using fn(acc, item). If initial is omitted, the first element is used as the initial accumulator. |
|
|
403
|
+
| REPEAT$(string$, count) | STRING | Returns a string consisting of string$ repeated count times. |
|
|
404
|
+
| REPLACE$(source$, old$, new$, [count], [ignore_case]) | STRING | Replaces occurrences of old$ with new$ in the source$ string. |
|
|
405
|
+
| REVERSE$(string$) | STRING | Reverses the order of characters in a string. |
|
|
406
|
+
| RIGHT$(string$, length) | STRING | Returns the last length characters from the right of the string. |
|
|
407
|
+
| RND([max_val]) | MATH | Returns a random number. If max_val is provided, returns an integer between 1 and max_val. Otherwise, returns a float between 0 and 1. |
|
|
408
|
+
| ROUND(number, [decimals]) | MATH | Rounds a number to a specified number of decimals. |
|
|
409
|
+
| RTRIM$(string$) | STRING | Removes whitespace from the end (right side) of a string. |
|
|
410
|
+
| SAVESCREEN([top, left, bottom, right]) | SCREEN | Copies the screen or an area (with colours) into a string for `RESTSCREEN`. |
|
|
411
|
+
| SECOND(time$) | DATE/TIME | Returns the seconds component (0-59) from a time/datetime string. |
|
|
412
|
+
| MINUTE(time$) | DATE/TIME | Returns the minutes component (0-59) from a time/datetime string. |
|
|
413
|
+
| HOUR(time$) | DATE/TIME | Returns the hours component (0-23) from a time/datetime string. |
|
|
414
|
+
| SGN(number) | MATH | Returns the sign of a number (-1 for negative, 0 for zero, 1 for positive). |
|
|
415
|
+
| SIN(number) | MATH | Returns the sine of an angle given in radians. |
|
|
416
|
+
| SOUNDEX$(string$) | STRING | Returns the Soundex phonetic code of a string. |
|
|
417
|
+
| SPACE$(count) | STRING | Returns a string consisting of count spaces. |
|
|
418
|
+
| SPLIT(string$, delimiter$, [limit]) | ARRAY | Splits a string by a delimiter$ and returns an ARRAY of substrings. |
|
|
419
|
+
| SQR(number) | MATH | Returns the square root of a number. |
|
|
420
|
+
| STARTSWITH(string$, prefix$) | STRING | Returns true (-1) if string$ starts with prefix$, otherwise false (0). |
|
|
421
|
+
| STR$(number) | STRING | Converts a number to a string as `PRINT` shows it, with a leading space for zero and positive numbers. |
|
|
422
|
+
| STRIPHTML$(string$) | STRING | Removes HTML tags from a string. |
|
|
423
|
+
| TAN(number) | MATH | Returns the tangent of an angle given in radians. |
|
|
424
|
+
| TIME$() | DATE/TIME | Returns the current system time as an "HH:MI:SS" string. |
|
|
425
|
+
| TIMER | DATE/TIME | Seconds since midnight, with fractions of a second: take it before and after some work to time it. |
|
|
426
|
+
| TRIM$(string$) | STRING | Removes whitespace from both the beginning and end of a string. |
|
|
427
|
+
| TYPENAME$(value) | UTILITY | Returns the name of the value's type: "FLOAT", "STRING", "ARRAY" or "HASH". |
|
|
428
|
+
| UBOUND(array) | ARRAY | Returns the upper bound (the highest index) of an array. Returns -1 for an empty array. |
|
|
429
|
+
| UCASE$(string$) | STRING | Converts a string to all uppercase characters. |
|
|
430
|
+
| URL_FILENAME$(url$) | STRING | Returns the filename portion of a URL path. |
|
|
431
|
+
| URL_HOSTNAME$(url$) | STRING | Returns the hostname component of a URL. |
|
|
432
|
+
| URL_PATH$(url$) | STRING | Returns the directory portion of a URL path. |
|
|
433
|
+
| URL_SCHEME$(url$) | STRING | Returns the scheme (e.g., "http", "https") of a URL. |
|
|
434
|
+
| URLDECODE$(string$) | STRING | URL-decodes a percent-encoded string. |
|
|
435
|
+
| URLENCODE$(string$) | STRING | Percent-encodes a string for safe use in a URL. |
|
|
436
|
+
| VAL(string$) | STRING/MATH | Returns the number at the start of string$ (`VAL("12abc")` is 12), or 0. |
|
|
437
|
+
| WEEKDAY(date$) | DATE/TIME | Returns the day of the week as a number (1 for Sunday, 7 for Saturday). |
|
|
438
|
+
| WEEKDAYNAME$(weekday_num) | DATE/TIME | Returns the English name of the given weekday (1 = Sunday ... 7 = Saturday, matching WEEKDAY). |
|
|
439
|
+
| YEAR(date$) | DATE/TIME | Returns the year from a date string. |
|
|
440
|
+
| YEARCAL$(year) | DATE/TIME | Returns a calendar of the given year as a multi-line string. |
|
|
441
|
+
|
|
442
|
+
---
|
|
443
|
+
|
|
444
|
+
**Note:** All functions return a value and can be used in expressions, assignments, or as arguments to other functions/statements.
|
|
445
|
+
|
|
446
|
+
### Function References as First-Class Arguments
|
|
447
|
+
|
|
448
|
+
`FILTER`, `MAP`, `REDUCE`, and `SORT WITH` accept a bare function name (without parentheses) as a first-class argument. The name may be a user-defined function or any of the built-ins above. Examples:
|
|
449
|
+
|
|
450
|
+
```basic
|
|
451
|
+
upper_names = MAP(names, UCASE$)
|
|
452
|
+
positives = FILTER(values, ISNUMERIC)
|
|
453
|
+
total = REDUCE(amounts, MAX)
|
|
454
|
+
SORT items WITH UCASE$ ASC
|
|
455
|
+
```
|
|
456
|
+
|
|
457
|
+
### String Interpolation in Backtick Strings
|
|
458
|
+
|
|
459
|
+
Backtick-delimited string literals support `${expr}` interpolation. Expressions may include arithmetic, built-in calls, UDF calls, and hash/array access:
|
|
460
|
+
|
|
461
|
+
```basic
|
|
462
|
+
PRINT `Hello, ${name$}!`
|
|
463
|
+
PRINT `Total: ${FORMAT$(amount, "$#,##0.00")}`
|
|
464
|
+
PRINT `Row ${i}: ${row("city$")} (${CARDINAL$(row("count"))})`
|
|
465
|
+
```
|
|
466
|
+
|
|
467
|
+
`$$` produces a literal `$`. Lone `{` and `}` are literal, so JSON, regex, and code snippets pass through intact. Regular double-quoted strings are unaffected.
|
|
468
|
+
|
|
469
|
+
---
|
|
470
|
+
|
|
471
|
+
## 📄 License
|
|
472
|
+
|
|
473
|
+
DDGBasic is released under the [MIT License](https://github.com/ddgflorida/DDGBasic/blob/main/LICENSE). The sample data in `examples/dotgov.csv` is the public list of .gov domains published by CISA, and `examples/data/chinook.sqlite` is the [Chinook sample database](https://github.com/lerocha/chinook-database) by Luis Rocha (MIT License).
|