summaryrefslogtreecommitdiff
path: root/scripts/code_tools
diff options
context:
space:
mode:
Diffstat (limited to 'scripts/code_tools')
-rw-r--r--scripts/code_tools/fix_whitespace.py87
-rw-r--r--scripts/code_tools/fix_xml_indentations.py125
-rw-r--r--scripts/code_tools/modified-strings.sh14
-rw-r--r--scripts/code_tools/modified_strings.py16
4 files changed, 227 insertions, 15 deletions
diff --git a/scripts/code_tools/fix_whitespace.py b/scripts/code_tools/fix_whitespace.py
new file mode 100644
index 0000000000..7a88265479
--- /dev/null
+++ b/scripts/code_tools/fix_whitespace.py
@@ -0,0 +1,87 @@
+#!/usr/bin/env python
+"""\
+
+This script replaces tab characters with spaces in source code files.
+
+$LicenseInfo:firstyear=2024&license=viewerlgpl$
+Second Life Viewer Source Code
+Copyright (C) 2024, Linden Research, Inc.
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation;
+version 2.1 of the License only.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+$/LicenseInfo$
+"""
+
+import argparse
+import os
+
+def convert_tabs_to_spaces(file_path, tab_stop):
+ """Convert tabs in a file to spaces, considering tab stops."""
+ with open(file_path, 'r') as file:
+ lines = file.readlines()
+
+ # Skip files with no tabs
+ if not any('\t' in line for line in lines):
+ return
+
+ new_lines = []
+ for line in lines:
+ # Remove trailing spaces
+ line = line.rstrip()
+ new_line = ''
+ column = 0 # Track the column index for calculating tab stops
+ for char in line:
+ if char == '\t':
+ # Calculate spaces needed to reach the next tab stop
+ spaces_needed = tab_stop - (column % tab_stop)
+ new_line += ' ' * spaces_needed
+ column += spaces_needed
+ else:
+ new_line += char
+ column += 1
+
+ new_lines.append(new_line + '\n')
+
+ with open(file_path, 'w', newline='\n') as file:
+ file.writelines(new_lines)
+
+def process_directory(directory, extensions, tab_stop):
+ """Recursively process files in directory, considering tab stops."""
+ extensions = tuple(extensions)
+ for root, dirs, files in os.walk(directory):
+ for file in files:
+ if file.endswith(extensions):
+ file_path = os.path.join(root, file)
+ print(f"Processing {file_path}")
+ convert_tabs_to_spaces(file_path, tab_stop)
+
+def main():
+ parser = argparse.ArgumentParser(description='Convert tabs to spaces in files, considering tab stops.')
+ parser.add_argument('-e', '--extensions', type=str, default='c,cpp,h,hpp,inl,py,glsl,cmake', help='Comma-separated list of file extensions to process (default: "c,cpp,h,hpp,inl,py,glsl,cmake")')
+ parser.add_argument('-t', '--tabstop', type=int, default=4, help='Tab stop size (default: 4)')
+ parser.add_argument('-d', '--directory', type=str, required=True, help='Directory to process')
+
+ args = parser.parse_args()
+
+ extensions = args.extensions.split(',')
+ # Add a dot prefix to each extension if not present
+ extensions = [ext if ext.startswith('.') else f".{ext}" for ext in extensions]
+
+ process_directory(args.directory, extensions, args.tabstop)
+ print("Processing completed.")
+
+if __name__ == "__main__":
+ main()
diff --git a/scripts/code_tools/fix_xml_indentations.py b/scripts/code_tools/fix_xml_indentations.py
new file mode 100644
index 0000000000..e317e4f7f6
--- /dev/null
+++ b/scripts/code_tools/fix_xml_indentations.py
@@ -0,0 +1,125 @@
+#!/usr/bin/env python3
+"""\
+
+This script formats XML files in a given directory with options for indentation and space removal.
+
+$LicenseInfo:firstyear=2023&license=viewerlgpl$
+Second Life Viewer Source Code
+Copyright (C) 2023, Linden Research, Inc.
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation;
+version 2.1 of the License only.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+$/LicenseInfo$
+"""
+
+import os
+import sys
+import glob
+import io
+import xml.etree.ElementTree as ET
+
+def get_xml_declaration(file_path):
+ with open(file_path, 'r', encoding='utf-8') as file:
+ first_line = file.readline().strip()
+ if first_line.startswith('<?xml'):
+ return first_line
+ return None
+
+def parse_xml_file(file_path):
+ try:
+ tree = ET.parse(file_path)
+ return tree
+ except ET.ParseError as e:
+ print(f"Error parsing XML file {file_path}: {e}")
+ return None
+
+def indent(elem, level=0, indent_text=False, indent_tab=False):
+ indent_string = "\t" if indent_tab else " "
+ i = "\n" + level * indent_string
+ if len(elem):
+ if not elem.text or not elem.text.strip():
+ elem.text = i + indent_string
+ if not elem.tail or not elem.tail.strip():
+ elem.tail = i
+ for elem in elem:
+ indent(elem, level + 1, indent_text, indent_tab)
+ if not elem.tail or not elem.tail.strip():
+ elem.tail = i
+ else:
+ if level and (not elem.tail or not elem.tail.strip()):
+ elem.tail = i
+ if indent_text and elem.text and not elem.text.isspace():
+ elem.text = "\n" + (level + 1) * indent_string + elem.text.strip() + "\n" + level * indent_string
+
+def save_xml(tree, file_path, xml_decl, indent_text=False, indent_tab=False, rm_space=False, rewrite_decl=False):
+ if tree is not None:
+ root = tree.getroot()
+ indent(root, indent_text=indent_text, indent_tab=indent_tab)
+ xml_string = ET.tostring(root, encoding='unicode')
+ if rm_space:
+ xml_string = xml_string.replace(' />', '/>')
+
+ xml_decl = (xml_decl if (xml_decl and not rewrite_decl)
+ else '<?xml version="1.0" encoding="utf-8" standalone="yes" ?>')
+
+ try:
+ with io.open(file_path, 'wb') as file:
+ file.write(xml_decl.encode('utf-8'))
+ file.write('\n'.encode('utf-8'))
+ if xml_string:
+ file.write(xml_string.encode('utf-8'))
+ if not xml_string.endswith('\n'):
+ file.write('\n'.encode('utf-8'))
+ except IOError as e:
+ print(f"Error saving file {file_path}: {e}")
+
+def process_directory(directory_path, indent_text=False, indent_tab=False, rm_space=False, rewrite_decl=False):
+ if not os.path.isdir(directory_path):
+ print(f"Directory not found: {directory_path}")
+ return
+
+ xml_files = glob.glob(os.path.join(directory_path, "*.xml"))
+ if not xml_files:
+ print(f"No XML files found in directory: {directory_path}")
+ return
+
+ for file_path in xml_files:
+ xml_decl = get_xml_declaration(file_path)
+ tree = parse_xml_file(file_path)
+ if tree is not None:
+ save_xml(tree, file_path, xml_decl, indent_text, indent_tab, rm_space, rewrite_decl)
+
+if __name__ == "__main__":
+ if len(sys.argv) < 2 or '--help' in sys.argv:
+ print("This script formats XML files in a given directory. Useful to fix XUI XMLs after processing by other tools.")
+ print("\nUsage:")
+ print(" python fix_xml_indentations.py <path/to/directory> [options]")
+ print("\nOptions:")
+ print(" --indent-text Indents text within XML tags.")
+ print(" --indent-tab Uses tabs instead of spaces for indentation.")
+ print(" --rm-space Removes spaces in self-closing tags.")
+ print(" --rewrite_decl Replaces the XML declaration line.")
+ print("\nCommon Usage:")
+ print(" To format XML files with text indentation, tab indentation, and removal of spaces in self-closing tags:")
+ print(" python fix_xml_indentations.py /path/to/xmls --indent-text --indent-tab --rm-space")
+ sys.exit(1)
+
+ directory_path = sys.argv[1]
+ indent_text = '--indent-text' in sys.argv
+ indent_tab = '--indent-tab' in sys.argv
+ rm_space = '--rm-space' in sys.argv
+ rewrite_decl = '--rewrite_decl' in sys.argv
+ process_directory(directory_path, indent_text, indent_tab, rm_space, rewrite_decl)
diff --git a/scripts/code_tools/modified-strings.sh b/scripts/code_tools/modified-strings.sh
index 435dda3f5d..932b0a4bfc 100644
--- a/scripts/code_tools/modified-strings.sh
+++ b/scripts/code_tools/modified-strings.sh
@@ -38,11 +38,11 @@ do
-h|--help)
Action=USAGE
;;
-
+
-v|--verbose)
Verbose=true
;;
-
+
##
## Select the revision to compare against
##
@@ -79,7 +79,7 @@ do
break
fi
;;
- esac
+ esac
shift # always consume 1
done
@@ -107,10 +107,10 @@ then
cat <<USAGE
Usage:
-
+
modified-strings.sh [ { -v | --verbose } ] [-r <revision>] [<path-to-xui>]
- where
+ where
--verbose shows progress messages on stderr (the command takes a while, so this is reassuring)
-r <revision> specifies a git revision (branch, tag, commit, or relative specifier)
@@ -124,9 +124,9 @@ Usage:
the path of a file that has a string change (columns 2 and 3 are empty for lines with a filename)
name
the name attribute of a string or label whose value changed
- English value
+ English value
the current value of the string or label whose value changed
- for strings, newlines are changed to '\n' and tab characters are changed to '\t'
+ for strings, newlines are changed to '\n' and tab characters are changed to '\t'
There is also a column for each of the language directories following the English.
diff --git a/scripts/code_tools/modified_strings.py b/scripts/code_tools/modified_strings.py
index 20ed1b0555..c777fc8c0d 100644
--- a/scripts/code_tools/modified_strings.py
+++ b/scripts/code_tools/modified_strings.py
@@ -49,7 +49,7 @@ into google sheets.
If the --rev revision already contains a translation for the text, it
will be included in the spreadsheet for reference.
-
+
Normally you would want --rev_base to be the last revision to have
translations added, and --rev to be the tip of the current
project. You can find the last commit with translation work using "git log --grep INTL- | head"
@@ -242,7 +242,7 @@ def find_deletions(mod_tree, base_tree, lang, args, f):
mod_filename = transl_filename.replace("/xui/{}/".format(lang), "/xui/{}/".format(args.base_lang))
#print("checking",transl_filename,"against",mod_filename)
try:
- mod_blob = mod_tree[mod_filename]
+ mod_blob = mod_tree[mod_filename]
except:
print(" delete file", transl_filename, file=f)
continue
@@ -257,7 +257,7 @@ def find_deletions(mod_tree, base_tree, lang, args, f):
if not elt_key in mod_dict:
if lines == 0:
print(" in file", transl_filename, file=f)
- lines += 1
+ lines += 1
print(" delete element", elt_key, file=f)
else:
transl_elt = transl_dict[elt_key]
@@ -266,14 +266,14 @@ def find_deletions(mod_tree, base_tree, lang, args, f):
if not a in mod_elt.attrib:
if lines == 0:
print(" in file", transl_filename, file=f)
- lines += 1
+ lines += 1
print(" delete attribute", a, "from", elt_key, file=f)
if transl_elt.text and (not mod_elt.text):
if lines == 0:
print(" in file", transl_filename, file=f)
- lines += 1
+ lines += 1
print(" delete text from", elt_key, file=f)
-
+
def save_translation_file(per_lang_data, aux_data, outfile):
langs = sorted(per_lang_data.keys())
@@ -310,12 +310,12 @@ def save_translation_file(per_lang_data, aux_data, outfile):
# Reference info, not for translation
for aux, data in list(aux_data.items()):
- df = pd.DataFrame(data, columns = ["Key", "Value"])
+ df = pd.DataFrame(data, columns = ["Key", "Value"])
df.to_excel(writer, index=False, sheet_name=aux)
worksheet = writer.sheets[aux]
worksheet.set_column('A:A', 50, bold_wrap_format)
worksheet.set_column('B:B', 80, wrap_format)
-
+
print("Writing", outfile)
writer.save()