Skip to content

Commit 4340792

Browse files
committed
fixing shellcheck finding and addin a CI
1 parent c251b22 commit 4340792

File tree

8 files changed

+110
-35
lines changed

8 files changed

+110
-35
lines changed

.github/workflows/ci.yml

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
name: CI
2+
3+
on:
4+
push:
5+
branches: [ main ]
6+
pull_request:
7+
branches: [ main ]
8+
workflow_dispatch:
9+
10+
jobs:
11+
test:
12+
runs-on: ubuntu-latest
13+
14+
steps:
15+
- uses: actions/checkout@v3
16+
17+
- name: Install shellcheck
18+
run: sudo apt-get update && sudo apt-get install -y shellcheck
19+
20+
- name: Check for syntax errors (lint)
21+
run: make lint
22+
23+
- name: Run tests
24+
run: make test

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
template_poc.html

Makefile

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Makefile for bash-ini-parser
22

3-
.PHONY: web clean
3+
.PHONY: web clean lint test
44

55
# Build the web demo
66
web:
@@ -15,8 +15,25 @@ clean:
1515
@rm -f index.html
1616
@echo "Clean complete."
1717

18+
# Lint shell scripts with shellcheck
19+
lint:
20+
@echo "Running shellcheck..."
21+
@shellcheck lib_ini.sh
22+
@shellcheck build_web_demo.sh
23+
@shellcheck run_tests.sh
24+
@echo "Lint complete."
25+
26+
# Run all tests
27+
test:
28+
@echo "Running tests..."
29+
@chmod +x run_tests.sh
30+
@./run_tests.sh
31+
@echo "Tests complete."
32+
1833
help:
1934
@echo "Available targets:"
2035
@echo " web - Build the interactive web demo (index.html)"
2136
@echo " clean - Remove generated files"
37+
@echo " lint - Check shell scripts with shellcheck"
38+
@echo " test - Run all tests"
2239
@echo " help - Show this help message"

README.md

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,8 @@
11
# Bash INI Parser
22

3-
A robust shell script library for parsing and manipulating INI configuration files in Bash.
3+
[![CI](https://github.com/lsferreira42/bash-ini-parser/actions/workflows/ci.yml/badge.svg)](https://github.com/lsferreira42/bash-ini-parser/actions/workflows/ci.yml)
44

5-
- **Version:** 0.0.1
6-
- **Author:** Leandro Ferreira
7-
- **Website:** [leandrosf.com](https://leandrosf.com)
8-
- **GitHub:** [lsferreira42](https://github.com/lsferreira42)
5+
A robust shell script library for parsing and manipulating INI configuration files in Bash.
96

107
## Try It Online
118

@@ -231,7 +228,6 @@ This project is licensed under the BSD License, a permissive free software licen
231228

232229
- **Leandro Ferreira**
233230
- Website: [leandrosf.com](https://leandrosf.com)
234-
- GitHub: [lsferreira42](https://github.com/lsferreira42)
235231

236232
## Contributing
237233

build_web_demo.sh

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -117,8 +117,7 @@ const files = {
117117
content: '[app]\\nname=My Application\\nversion=1.0.0\\nsupported_formats=jpg,png,gif'
118118
},
119119
examples: {
120-
dir: 'examples',
121-
files: ['simple.ini', 'complex.ini', 'empty.ini', 'basic_usage.sh', 'demo.sh']
120+
dir: 'examples'
122121
}
123122
};
124123
@@ -152,11 +151,21 @@ console.log('Processing lib_ini.sh...');
152151
const libContent = readFileOrDefault(files.lib);
153152
templateContent = safeReplaceInHTML(templateContent, '<!-- LIB_INI_SH_CONTENT -->', libContent);
154153
155-
// Process example files
156-
console.log('Processing example files...');
154+
// Process all example files
155+
console.log('Processing all example files...');
157156
const examplesDir = files.examples.dir;
158-
for (const file of files.examples.files) {
157+
158+
// Read all files from the examples directory
159+
const exampleFiles = fs.readdirSync(examplesDir);
160+
161+
for (const file of exampleFiles) {
159162
const filePath = path.join(examplesDir, file);
163+
164+
// Skip directories, only process files
165+
if (fs.statSync(filePath).isDirectory()) {
166+
continue;
167+
}
168+
160169
console.log(\`Reading \${filePath}...\`);
161170
const content = readFileOrDefault(filePath);
162171

index.html

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -418,8 +418,15 @@ <h2>Examples</h2>
418418
'examples/complex.ini': "[sistema]\nnome=Sistema de Gerenciamento\ndescrição=Este é um sistema complexo com várias funcionalidades\nano-criação=2023\nversão=2.5.1\n\n[configurações]\nmodo debug=true\ndiretório de dados=C:\\Programa Files\\Sistema\\data\narquivos permitidos=.jpg, .png, .pdf, .docx\nURL=https://sistema.exemplo.com.br/api?token=abc123\ntempo-limite=60.5\n\n[usuários]\nadministrador=João Silva <joao@exemplo.com>\nformato_nome=Sobrenome, Nome\npermissões=leitura, escrita, execução ",
419419
'examples/empty.ini': "# Arquivo de configuração vazio ",
420420
'examples/basic_usage.sh': "#!/bin/bash\n# Basic usage example for the Bash INI Parser library\n\n# Load the library\nsource ../lib_ini.sh\n\necho \"Simple INI file operations example\"\necho\n\n# Set the configuration file\nCONFIG_FILE=\"simple_config.ini\"\necho \"Creating a test configuration file '$CONFIG_FILE'\"\n\n# Make sure we start with a clean file\nrm -f \"$CONFIG_FILE\"\n\n# Create sections and add values\necho \"1. Creating sections and adding values\"\nini_add_section \"$CONFIG_FILE\" \"general\"\nini_write \"$CONFIG_FILE\" \"general\" \"app_name\" \"My App\"\nini_write \"$CONFIG_FILE\" \"general\" \"version\" \"1.0.0\"\n\nini_add_section \"$CONFIG_FILE\" \"user\"\nini_write \"$CONFIG_FILE\" \"user\" \"name\" \"John Doe\"\nini_write \"$CONFIG_FILE\" \"user\" \"email\" \"john@example.com\"\n\n# Display the file contents\necho \"File contents after writing:\"\ncat \"$CONFIG_FILE\"\necho\n\n# Read values\necho \"2. Reading values\"\napp_name=$(ini_read \"$CONFIG_FILE\" \"general\" \"app_name\")\nversion=$(ini_read \"$CONFIG_FILE\" \"general\" \"version\")\nuser_name=$(ini_read \"$CONFIG_FILE\" \"user\" \"name\")\n\necho \"App name: $app_name\"\necho \"Version: $version\"\necho \"User name: $user_name\"\necho\n\n# List sections and keys\necho \"3. Listing sections and keys\"\necho \"Sections in the file:\"\nini_list_sections \"$CONFIG_FILE\" | while read section; do\n echo \"- $section\"\ndone\n\necho \"Keys in 'general' section:\"\nini_list_keys \"$CONFIG_FILE\" \"general\" | while read key; do\n echo \"- $key\"\ndone\necho\n\n# Update a value\necho \"4. Updating a value\"\necho \"Updating version to 1.1.0\"\nini_write \"$CONFIG_FILE\" \"general\" \"version\" \"1.1.0\"\nnew_version=$(ini_read \"$CONFIG_FILE\" \"general\" \"version\")\necho \"New version: $new_version\"\necho\n\n# Remove a key\necho \"5. Removing a key\"\necho \"Removing the 'email' key from 'user' section\"\nini_remove_key \"$CONFIG_FILE\" \"user\" \"email\"\necho \"File contents after removing key:\"\ncat \"$CONFIG_FILE\"\necho\n\n# Add a new section\necho \"6. Adding a new section\"\nini_add_section \"$CONFIG_FILE\" \"preferences\"\nini_write \"$CONFIG_FILE\" \"preferences\" \"theme\" \"dark\"\nini_write \"$CONFIG_FILE\" \"preferences\" \"language\" \"en-US\"\necho \"File contents after adding section:\"\ncat \"$CONFIG_FILE\"\necho\n\n# Remove a section\necho \"7. Removing a section\"\necho \"Removing the 'preferences' section\"\nini_remove_section \"$CONFIG_FILE\" \"preferences\"\necho \"File contents after removing section:\"\ncat \"$CONFIG_FILE\"\necho\n\n# Check if sections and keys exist\necho \"8. Checking existence\"\nif ini_section_exists \"$CONFIG_FILE\" \"general\"; then\n echo \"Section 'general' exists\"\nfi\n\nif ini_key_exists \"$CONFIG_FILE\" \"user\" \"name\"; then\n echo \"Key 'name' exists in section 'user'\"\nfi\n\nif ! ini_section_exists \"$CONFIG_FILE\" \"preferences\"; then\n echo \"Section 'preferences' does not exist anymore\"\nfi\necho\n\necho \"Basic operations completed successfully!\" ",
421+
'examples/advanced_usage.sh': "#!/bin/bash\n# Advanced usage example for the improved lib_ini.sh library\n\n# Source the library\nsource ../lib_ini.sh\n\n# Enable debug mode to see what's happening\nINI_DEBUG=1\necho \"Debug mode enabled, you will see detailed information about operations\"\necho\n\n# Create a test configuration file\necho \"Creating a test configuration file 'config.ini'\"\nCONFIG_FILE=\"config.ini\"\n\n# Make sure we start with a clean file\nrm -f \"$CONFIG_FILE\"\n\n# Basic operations\necho \"=== Basic Operations ===\"\nini_add_section \"$CONFIG_FILE\" \"app\"\nini_write \"$CONFIG_FILE\" \"app\" \"name\" \"My Advanced App\"\nini_write \"$CONFIG_FILE\" \"app\" \"version\" \"2.0.0\"\nini_write \"$CONFIG_FILE\" \"app\" \"debug\" \"false\"\n\nini_add_section \"$CONFIG_FILE\" \"database\"\nini_write \"$CONFIG_FILE\" \"database\" \"host\" \"localhost\"\nini_write \"$CONFIG_FILE\" \"database\" \"port\" \"3306\"\nini_write \"$CONFIG_FILE\" \"database\" \"user\" \"dbuser\"\nini_write \"$CONFIG_FILE\" \"database\" \"password\" \"s3cr3t\"\n\necho \"Reading a basic value:\"\napp_name=$(ini_read \"$CONFIG_FILE\" \"app\" \"name\")\necho \"App name: $app_name\"\necho\n\n# Working with default values\necho \"=== Default Values ===\"\necho \"Reading a value with default (exists):\"\ndebug=$(ini_get_or_default \"$CONFIG_FILE\" \"app\" \"debug\" \"true\")\necho \"Debug: $debug\"\n\necho \"Reading a value with default (doesn't exist):\"\ntimeout=$(ini_get_or_default \"$CONFIG_FILE\" \"app\" \"timeout\" \"30\")\necho \"Timeout: $timeout\"\necho\n\n# Working with arrays\necho \"=== Array Support ===\"\necho \"Writing array values:\"\nini_write_array \"$CONFIG_FILE\" \"app\" \"supported_formats\" \"jpg\" \"png\" \"gif\" \"svg\"\necho \"Reading array values:\"\nformats=$(ini_read_array \"$CONFIG_FILE\" \"app\" \"supported_formats\")\necho \"Supported formats:\"\nfor format in $formats; do\n echo \" - $format\"\ndone\necho\n\n# Complex values with spaces and special characters\necho \"=== Complex Values ===\"\nini_write \"$CONFIG_FILE\" \"app\" \"description\" \"This is a complex description with spaces and special characters: !@#$%^&*()\"\nini_write \"$CONFIG_FILE\" \"app\" \"welcome_message\" \"Welcome to \\\"My App\\\"\"\nini_write \"$CONFIG_FILE\" \"paths\" \"data_directory\" \"/path/with spaces/data\"\n\necho \"Reading complex values:\"\ndescription=$(ini_read \"$CONFIG_FILE\" \"app\" \"description\")\necho \"Description: $description\"\nmessage=$(ini_read \"$CONFIG_FILE\" \"app\" \"welcome_message\")\necho \"Welcome message: $message\"\necho\n\n# Export to environment variables\necho \"=== Environment Variables ===\"\nini_to_env \"$CONFIG_FILE\" \"CFG\"\necho \"Exported values to environment variables with prefix 'CFG'\"\necho \"Database host: $CFG_database_host\"\necho \"Database port: $CFG_database_port\"\necho \"App name: $CFG_app_name\"\necho\n\n# Import from another file\necho \"=== File Import ===\"\necho \"Creating another file 'defaults.ini'\"\nDEFAULTS_FILE=\"defaults.ini\"\nrm -f \"$DEFAULTS_FILE\"\n\nini_add_section \"$DEFAULTS_FILE\" \"logging\"\nini_write \"$DEFAULTS_FILE\" \"logging\" \"level\" \"info\"\nini_write \"$DEFAULTS_FILE\" \"logging\" \"file\" \"/var/log/app.log\"\nini_write \"$DEFAULTS_FILE\" \"logging\" \"max_size\" \"10M\"\n\nini_add_section \"$DEFAULTS_FILE\" \"security\"\nini_write \"$DEFAULTS_FILE\" \"security\" \"enable_2fa\" \"true\"\nini_write \"$DEFAULTS_FILE\" \"security\" \"password_expiry_days\" \"90\"\n\necho \"Importing from defaults.ini to config.ini\"\nini_import \"$DEFAULTS_FILE\" \"$CONFIG_FILE\"\n\necho \"Reading imported values:\"\nlog_level=$(ini_read \"$CONFIG_FILE\" \"logging\" \"level\")\necho \"Log level: $log_level\"\nenable_2fa=$(ini_read \"$CONFIG_FILE\" \"security\" \"enable_2fa\")\necho \"2FA enabled: $enable_2fa\"\necho\n\n# Check existence\necho \"=== Key Existence Check ===\"\nif ini_key_exists \"$CONFIG_FILE\" \"app\" \"version\"; then\n echo \"Key 'version' exists in section 'app'\"\nfi\n\nif ! ini_key_exists \"$CONFIG_FILE\" \"app\" \"non_existent_key\"; then\n echo \"Key 'non_existent_key' does not exist in section 'app'\"\nfi\necho\n\n# Remove operations\necho \"=== Remove Operations ===\"\necho \"Removing key 'debug' from section 'app'\"\nini_remove_key \"$CONFIG_FILE\" \"app\" \"debug\"\n\necho \"Removing section 'security'\"\nini_remove_section \"$CONFIG_FILE\" \"security\"\n\necho \"Final file contents:\"\ncat \"$CONFIG_FILE\"\necho\n\necho \"All operations completed successfully!\" ",
422+
'examples/config.ini': "[app]\nname=My Advanced App\nversion=2.0.0\n\nsupported_formats=jpg,png,gif,svg\ndescription=This is a complex description with spaces and special characters: !@#$%^&*()\nwelcome_message=Welcome to \"My App\"\n[database]\nhost=localhost\nport=3306\nuser=dbuser\npassword=s3cr3t\n\n[paths]\ndata_directory=/path/with spaces/data\n\n[logging]\nlevel=info\nfile=/var/log/app.log\nmax_size=10M\n\n",
423+
'examples/commented.ini': "# Configuração principal do serviço\n[service]\n# Nome do serviço\nname=FileManager\n# Porta que o serviço escuta\nport=8080\n; Comentário usando ponto e vírgula\ndebug=true\n\n; Seção de logging\n[logging]\n# Níveis: debug, info, warning, error\nlevel=info\n# Caminho para o arquivo de log\npath=/var/log/filemanager.log\n# Rotação de logs\nrotate=true\n# Tamanho máximo em MB\nmax_size=10\n\n# Configurações de autenticação\n[auth]\n# Tipo de autenticação: basic, token, oauth\ntype=oauth\n# Tempo de expiração do token em segundos\n; 3600 = 1 hora\nexpiration=3600 ",
424+
'examples/defaults.ini': "[logging]\nlevel=info\nfile=/var/log/app.log\nmax_size=10M\n\n[security]\nenable_2fa=true\npassword_expiry_days=90\n",
425+
'examples/extensive.ini': "[general]\napp_name=SuperApp\nversion=3.1.4\nbuild=2023.05.12\ndebug=false\nlocale=pt_BR\ntimezone=America/Sao_Paulo\nmax_connections=100\ntimeout=30\n\n[database_primary]\ntype=mysql\nhost=db-primary.example.com\nport=3306\nname=proddb\nuser=dbadmin\npassword=S3cureP@55\nmax_connections=50\ntimeout=15\nssl=true\ncharset=utf8mb4\n\n[database_replica]\ntype=mysql\nhost=db-replica.example.com\nport=3306\nname=proddb_replica\nuser=dbreader\npassword=R3@d0nly\nmax_connections=100\ntimeout=10\nssl=true\ncharset=utf8mb4\n\n[cache]\ntype=redis\nhost=cache.example.com\nport=6379\nmax_memory=2G\neviction_policy=lru\ndb_number=0\n\n[storage]\ntype=s3\nbucket=superapp-files\nregion=us-east-1\naccess_key=AKIAIOSFODNN7EXAMPLE\nsecret_key=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY\ncloudfront_url=https://d1234.cloudfront.net\nmax_file_size=50M\n\n[api]\nendpoint=https://api.example.com\nversion=v2\nrate_limit=1000\ntoken_expiration=86400\ncors_origins=https://app.example.com,https://admin.example.com\n\n[security]\nenable_2fa=true\npassword_min_length=10\npassword_require_special=true\npassword_require_numbers=true\npassword_require_uppercase=true\nfailed_login_attempts=5\nlockout_time=30\nsession_timeout=3600\n\n[email]\nsmtp_server=smtp.example.com\nsmtp_port=587\nsmtp_user=notifications@example.com\nsmtp_password=Em@ilP@55\nfrom_email=noreply@example.com\nfrom_name=SuperApp\ntemplate_dir=/var/templates/email\n\n[logging]\nlevel=info\nfile=/var/log/superapp.log\nmax_size=100M\nmax_files=10\nformat=json\nsentry_dsn=https://1234567890abcdef@sentry.example.com/1\n\n[monitoring]\nenable_apm=true\ndatadog_api_key=1234567890abcdef1234567890abcdef\nmetrics_interval=60\nhealth_check_endpoint=/health\nerror_threshold=5\n\n[features]\nenable_new_dashboard=true\nenable_beta_api=false\nenable_social_login=true\nenable_export=true\nmax_export_size=10000 ",
426+
'examples/simple_config.ini': "[general]\napp_name=My App\nversion=1.1.0\n\n[user]\nname=John Doe\n\n",
427+
'examples/demo.sh': "#!/bin/bash\n# Demo script for bash-ini-parser\n\n# Source the library\nsource ./lib_ini.sh\n\necho \"=== Bash INI Parser Demo ===\"\necho\n\n# Create a new INI file\nCONFIG_FILE=\"config.ini\"\necho \"Creating a new INI file: $CONFIG_FILE\"\nini_add_section \"$CONFIG_FILE\" \"app\"\nini_write \"$CONFIG_FILE\" \"app\" \"name\" \"My Application\"\nini_write \"$CONFIG_FILE\" \"app\" \"version\" \"1.0.0\"\n\n# Read values\necho\necho \"Reading values:\"\napp_name=$(ini_read \"$CONFIG_FILE\" \"app\" \"name\")\necho \"App name: $app_name\"\napp_version=$(ini_read \"$CONFIG_FILE\" \"app\" \"version\")\necho \"App version: $app_version\"\n\n# List sections\necho\necho \"Listing sections:\"\nini_list_sections \"$CONFIG_FILE\" | while read section; do\n echo \"- $section\"\ndone\n\n# List keys in a section\necho\necho \"Listing keys in 'app' section:\"\nini_list_keys \"$CONFIG_FILE\" \"app\" | while read key; do\n echo \"- $key\"\ndone\n\n# Write array values\necho \necho \"Writing array of supported formats...\"\nini_write_array \"$CONFIG_FILE\" \"app\" \"supported_formats\" \"jpg\" \"png\" \"gif\"\n\n# Read array values\necho\necho \"Reading array values:\"\nini_read_array \"$CONFIG_FILE\" \"app\" \"supported_formats\" | while read format; do\n echo \"- $format\"\ndone\n\necho\necho \"Demo completed successfully!\"\n",
421428
'run_demo.sh': "#!/bin/bash\n# Demo script for bash-ini-parser\n\n# Source the library\nsource ./lib_ini.sh\n\necho \"=== Bash INI Parser Demo ===\"\necho\n\n# Create a new INI file\nCONFIG_FILE=\"config.ini\"\necho \"Creating a new INI file: $CONFIG_FILE\"\nini_add_section \"$CONFIG_FILE\" \"app\"\nini_write \"$CONFIG_FILE\" \"app\" \"name\" \"My Application\"\nini_write \"$CONFIG_FILE\" \"app\" \"version\" \"1.0.0\"\n\n# Read values\necho\necho \"Reading values:\"\napp_name=$(ini_read \"$CONFIG_FILE\" \"app\" \"name\")\necho \"App name: $app_name\"\napp_version=$(ini_read \"$CONFIG_FILE\" \"app\" \"version\")\necho \"App version: $app_version\"\n\n# List sections\necho\necho \"Listing sections:\"\nini_list_sections \"$CONFIG_FILE\" | while read section; do\n echo \"- $section\"\ndone\n\n# List keys in a section\necho\necho \"Listing keys in 'app' section:\"\nini_list_keys \"$CONFIG_FILE\" \"app\" | while read key; do\n echo \"- $key\"\ndone\n\n# Write array values\necho \necho \"Writing array of supported formats...\"\nini_write_array \"$CONFIG_FILE\" \"app\" \"supported_formats\" \"jpg\" \"png\" \"gif\"\n\n# Read array values\necho\necho \"Reading array values:\"\nini_read_array \"$CONFIG_FILE\" \"app\" \"supported_formats\" | while read format; do\n echo \"- $format\"\ndone\n\necho\necho \"Demo completed successfully!\"\n",
422-
'config.ini': "[app]\nname=My Application\nversion=1.0.0\nsupported_formats=jpg,png,gif"
429+
'config.ini': "[app]\nname=My Advanced App\nversion=2.0.0\n\nsupported_formats=jpg,png,gif,svg\ndescription=This is a complex description with spaces and special characters: !@#$%^&*()\nwelcome_message=Welcome to \"My App\"\n[database]\nhost=localhost\nport=3306\nuser=dbuser\npassword=s3cr3t\n\n[paths]\ndata_directory=/path/with spaces/data\n\n[logging]\nlevel=info\nfile=/var/log/app.log\nmax_size=10M\n\n"
423430
};
424431

425432
// Configuração e inicialização do terminal

0 commit comments

Comments
 (0)