# -*- coding: utf-8 -*- """ novelWriter – Various Tools =========================== Various core tool functions File History: Created: 2019-04-22 [0.0.1] countWords Created: 2020-07-05 [0.10.0] numberToRoman This file is a part of novelWriter Copyright 2018–2021, Veronica Berglyd Olsen This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . """ import logging from nw.constants import nwUnicode logger = logging.getLogger(__name__) # =============================================================================================== # # Simple Word Counter # =============================================================================================== # def countWords(theText): """Count words in a piece of text, skipping special syntax and comments. """ charCount = 0 wordCount = 0 paraCount = 0 prevEmpty = True # We need to treat dashes as word separators for counting words. # The check+replace apprach is much faster that direct replace for # large texts, and a bit slower for small texts, but in the latter # case it doesn't matter. if nwUnicode.U_ENDASH in theText: theText = theText.replace(nwUnicode.U_ENDASH, " ") if nwUnicode.U_EMDASH in theText: theText = theText.replace(nwUnicode.U_EMDASH, " ") for aLine in theText.splitlines(): countPara = True theLen = len(aLine) if theLen == 0: prevEmpty = True continue if aLine[0] == "@" or aLine[0] == "%": continue if aLine[0:5] == "#### ": wordCount -= 1 charCount -= 5 countPara = False elif aLine[0:4] == "### ": wordCount -= 1 charCount -= 4 countPara = False elif aLine[0:3] == "## ": wordCount -= 1 charCount -= 3 countPara = False elif aLine[0:2] == "# ": wordCount -= 1 charCount -= 2 countPara = False wordCount += len(aLine.split()) charCount += theLen if countPara and prevEmpty: paraCount += 1 prevEmpty = not countPara return charCount, wordCount, paraCount # =============================================================================================== # # Convert an Integer to a Roman Number # =============================================================================================== # def numberToRoman(numVal, isLower=False): """Convert an integer to a roman number. """ if not isinstance(numVal, int): return "NAN" if numVal < 1 or numVal > 4999: return "OOR" theValues = [ (1000, "M"), (900, "CM"), (500, "D"), (400, "CD"), (100, "C"), (90, "XC"), (50, "L"), (40, "XL"), (10, "X"), (9, "IX"), (5, "V"), (4, "IV"), (1, "I"), ] romNum = "" for theDiv, theSym in theValues: n = numVal//theDiv romNum += n*theSym numVal -= n*theDiv if numVal <= 0: break return romNum.lower() if isLower else romNum