Skip to content

Commit e7e58c6

Browse files
committed
Add check_keywords_txt()
#15
1 parent 18d551c commit e7e58c6

File tree

3 files changed

+139
-0
lines changed

3 files changed

+139
-0
lines changed

.travis.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,8 @@ script:
126126

127127
- check_library_properties "${SKETCHBOOK_FOLDER}/libraries/NewPing"
128128

129+
- check_keywords_txt "${SKETCHBOOK_FOLDER}/libraries/NewPing"
130+
129131
# Test library installed from .zip with rename
130132
# Test library installed from .zip with dot in the folder name
131133
# Test board from hardware package manually installed from compressed file download

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,10 @@ Check a library to ensure they have the correct structure. This will also run `c
121121
Check [library.properties](https://github.com/arduino/Arduino/wiki/Arduino-IDE-1.5:-Library-specification#libraryproperties-file-format) metadata files for errors.
122122
- Parameter: **searchPath** - Path containing library.properties files. The path will be searched recursively and all library.properties files found under it will be checked.
123123

124+
##### `check_keywords_txt searchPath'
125+
Check [keywords.txt](https://github.com/arduino/Arduino/wiki/Arduino-IDE-1.5:-Library-specification#keywords) files for errors.
126+
- Parameter: **searchPath** - Path containing keywords.txt files. The path will be searched recursively and all keywords.txt files found under it will be checked.
127+
124128
##### `build_sketch sketchPath boardID allowFail IDEversion`
125129
##### `build_sketch sketchPath boardID allowFail [IDEversionList]`
126130
##### `build_sketch sketchPath boardID allowFail startIDEversion endIDEversion`

arduino-ci-script.sh

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1579,6 +1579,139 @@ function check_library_properties()
15791579
}
15801580

15811581

1582+
# https://github.com/arduino/Arduino/wiki/Arduino-IDE-1.5:-Library-specification#keywords
1583+
function check_keywords_txt()
1584+
{
1585+
local -r searchPath="$1"
1586+
1587+
# Replace backslashes with slashes
1588+
local -r searchPathWithSlashes="${searchPath//\\//}"
1589+
# Remove trailing slash
1590+
local -r normalizedSearchPath="${searchPathWithSlashes%/}"
1591+
1592+
# Check whether folder exists
1593+
if [[ ! -d "$normalizedSearchPath" ]]; then
1594+
echo "ERROR: Specified folder: $normalizedSearchPath doesn't exist."
1595+
return 1
1596+
fi
1597+
1598+
# find all folders that contain a keywords.txt file
1599+
find "$normalizedSearchPath" -type f -regex '.*/[kK][eE][yY][wW][oO][rR][dD][sS]\.[tT][xX][tT]' | while read -r keywordsTxtPath; do
1600+
1601+
# Check for incorrect filename case
1602+
if [[ "${keywordsTxtPath: -12}" != 'keywords.txt' ]]; then
1603+
echo "ERROR: $keywordsTxtPath uses incorrect filename case, which causes it to not be recognized on a filename case-sensitive OS such as Linux."
1604+
return 2
1605+
fi
1606+
1607+
# Read the keywords.txt file line by line
1608+
# Split into lines by CR
1609+
while IFS='' read -d $'\r' -r keywordsTxtCRline || [[ -n "$keywordsTxtCRline" ]]; do
1610+
# Split into lines by LN
1611+
while IFS='' read -r keywordsTxtLine || [[ -n "$keywordsTxtLine" ]]; do
1612+
local blankLineRegex='^[[:space:]]*$'
1613+
local commentRegex='^[[:space:]]*#'
1614+
if ! [[ ("$keywordsTxtLine" =~ $blankLineRegex) || ("$keywordsTxtLine" =~ $commentRegex) ]]; then
1615+
1616+
# Check for invalid separator
1617+
local validSeparatorRegex='^[[:space:]]*[^[:space:]]+[[:space:]]*'$'\t''+[^[:space:]]+'
1618+
if ! [[ "$keywordsTxtLine" =~ $validSeparatorRegex ]]; then
1619+
echo "ERROR: $keywordsTxtPath uses invalid field separator. It must be a true tab."
1620+
return 3
1621+
fi
1622+
1623+
# Check for multiple tabs used as separator where this causes unintended results
1624+
local consequentialMultipleSeparatorRegex='^[[:space:]]*[^[:space:]]+[[:space:]]*'$'\t\t''+((KEYWORD1)|(LITERAL1))'
1625+
if [[ "$keywordsTxtLine" =~ $consequentialMultipleSeparatorRegex ]]; then
1626+
echo "ERROR: $keywordsTxtPath uses multiple tabs as field separator. It must be a single tab. This causes the default keyword coloring (as used by KEYWORD2, KEYWORD3, LITERAL2) to be used rather than the intended coloration."
1627+
return 4
1628+
fi
1629+
1630+
# Get the field values
1631+
# Use a unique, non-whitespace field separator character
1632+
fieldSeparator=$'\a'
1633+
IFS=$fieldSeparator
1634+
# Change tabs to the field separator character for line splitting
1635+
local keywordsTxtLineSwappedTabs=(${keywordsTxtLine//$'\t'/$fieldSeparator})
1636+
1637+
# Unused, so commented
1638+
# # KEYWORD is the 1st field
1639+
# local keywordRaw=${keywordsTxtLineSwappedTabs[0]}
1640+
# # The Arduino IDE strips leading whitespace and trailing spaces from KEYWORD
1641+
# # Strip leading whitespace
1642+
# local keywordFrontStripped="${keywordRaw#"${keywordRaw%%[![:space:]]*}"}"
1643+
# # Strip trailing spaces
1644+
# local keyword="${keywordFrontStripped%"${keywordFrontStripped##*[! ]}"}"
1645+
1646+
# KEYWORD_TOKENTYPE is the 2nd field
1647+
local keywordTokentypeRaw=${keywordsTxtLineSwappedTabs[1]}
1648+
# The Arduino IDE strips trailing spaces from KEYWORD_TOKENTYPE
1649+
# Strip trailing spaces
1650+
local keywordTokentype="${keywordTokentypeRaw%"${keywordTokentypeRaw##*[! ]}"}"
1651+
1652+
# REFERENCE_LINK is the 3rd field
1653+
local referenceLinkRaw=${keywordsTxtLineSwappedTabs[2]}
1654+
# The Arduino IDE strips leading and trailing whitespace from REFERENCE_LINK
1655+
# Strip leading spaces
1656+
local referenceLinkFrontStripped="${referenceLinkRaw#"${referenceLinkRaw%%[! ]*}"}"
1657+
# Strip trailing spaces
1658+
local referenceLink="${referenceLinkFrontStripped%"${referenceLinkFrontStripped##*[! ]}"}"
1659+
1660+
# RSYNTAXTEXTAREA_TOKENTYPE is the 4th field
1661+
local rsyntaxtextareaTokentypeRaw=${keywordsTxtLineSwappedTabs[3]}
1662+
# The Arduino IDE strips trailing spaces from RSYNTAXTEXTAREA_TOKENTYPE
1663+
# Strip trailing spaces
1664+
local rsyntaxtextareaTokentype="${rsyntaxtextareaTokentypeRaw%"${rsyntaxtextareaTokentypeRaw##*[! ]}"}"
1665+
1666+
# Reset IFS to default
1667+
unset IFS
1668+
1669+
# Check for multiple tabs used as separator where this causes no unintended results
1670+
# A large percentage of Arduino libraries have this problem
1671+
local inconsequentialMultipleSeparatorRegex='^[[:space:]]*[^[:space:]]+[[:space:]]*'$'\t\t''+((KEYWORD2)|(KEYWORD3)|(LITERAL2))'
1672+
if [[ "$keywordsTxtLine" =~ $inconsequentialMultipleSeparatorRegex ]]; then
1673+
echo "WARNING: $keywordsTxtPath uses multiple tabs as field separator. It must be a single tab. This causes the default keyword coloring (as used by KEYWORD2, KEYWORD3, LITERAL2). In this case that doesn't cause the keywords to be incorrectly colored as expected but it's recommended to fully comply with the Arduino library specification."
1674+
else
1675+
# The rest of the checks will be borked by the use of multiple tabs as a separator
1676+
1677+
# Check for invalid KEYWORD_TOKENTYPE
1678+
local validKeywordTokentypeRegex='^((KEYWORD1)|(KEYWORD2)|(KEYWORD3)|(LITERAL1)|(LITERAL2))$'
1679+
if ! [[ "$keywordTokentype" =~ $validKeywordTokentypeRegex ]]; then
1680+
echo "ERROR: $keywordsTxtPath uses invalid KEYWORD_TOKENTYPE: ${keywordTokentype}, which causes the default keyword coloration to be used. See: https://github.com/arduino/Arduino/wiki/Arduino-IDE-1.5:-Library-specification#keyword_tokentype"
1681+
return 5
1682+
fi
1683+
1684+
# Check for invalid RSYNTAXTEXTAREA_TOKENTYPE
1685+
if [[ "$rsyntaxtextareaTokentype" != "" ]]; then
1686+
local validRsyntaxtextareaTokentypeRegex='^((RESERVED_WORD)|(RESERVED_WORD2)|(DATA_TYPE)|(PREPROCESSOR))$'
1687+
if ! [[ "$rsyntaxtextareaTokentype" =~ $validRsyntaxtextareaTokentypeRegex ]]; then
1688+
echo "ERROR: $keywordsTxtPath uses invalid RSYNTAXTEXTAREA_TOKENTYPE: ${rsyntaxtextareaTokentype}, which causes the default keyword coloration to be used. See: https://github.com/arduino/Arduino/wiki/Arduino-IDE-1.5:-Library-specification#rsyntaxtextarea_tokentype"
1689+
return 6
1690+
fi
1691+
fi
1692+
1693+
# Check for invalid REFERENCE_LINK
1694+
if [[ "$referenceLink" != "" ]]; then
1695+
# The Arduino IDE must be installed to check if the reference page exists
1696+
if [[ "$NEWEST_INSTALLED_IDE_VERSION" == "" ]]; then
1697+
echo "WARNING: Arduino IDE is not installed so unable to check for invalid reference links. Please call install_ide before running check_keywords_txt."
1698+
else
1699+
install_ide_version "$NEWEST_INSTALLED_IDE_VERSION"
1700+
if ! [[ -e "${ARDUINO_CI_SCRIPT_APPLICATION_FOLDER}/${ARDUINO_CI_SCRIPT_IDE_INSTALLATION_FOLDER}/reference/www.arduino.cc/en/Reference/${referenceLink}.html" ]]; then
1701+
echo "ERROR: $keywordsTxtPath uses a REFERENCE_LINK value: $referenceLink that is not a valid Arduino Language Reference page. See: https://github.com/arduino/Arduino/wiki/Arduino-IDE-1.5:-Library-specification#reference_link"
1702+
return 7
1703+
fi
1704+
fi
1705+
fi
1706+
1707+
fi
1708+
fi
1709+
done <<< "$keywordsTxtCRline"
1710+
done < "$keywordsTxtPath"
1711+
done
1712+
}
1713+
1714+
15821715
# Set default verbosity (must be called after the function definitions
15831716
set_script_verbosity 0
15841717

0 commit comments

Comments
 (0)