Fix paragraph bug, Move to C++17 to allow compiling on older systems, get rid of cmake, this is simple enough we can do with a simple Makefile.

This commit is contained in:
John Sennesael 2022-03-24 19:17:56 -05:00
parent 0d397c20ed
commit ec8f985f39
7 changed files with 78 additions and 109 deletions

1
.gitignore vendored
View File

@ -3,3 +3,4 @@
*.*~
*.sw*
build/*
/justify

View File

@ -1,42 +0,0 @@
# Copyright© 2022 John Sennesael
#
# This file is part of justify.
#
# Justify 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.
#
# Justify 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 Justify. If not, see <https://www.gnu.org/licenses/>.
cmake_minimum_required(VERSION 3.5)
#set (CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -O0 -ggdb -fno-omit-frame-pointer -fsanitize=address")
#set (CMAKE_LINKER_FLAGS_DEBUG "${CMAKE_LINKER_FLAGS_DEBUG} -fno-omit-frame-pointer -fsanitize=address")
set (CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -O0 -ggdb -fno-omit-frame-pointer")
set (CMAKE_LINKER_FLAGS_DEBUG "${CMAKE_LINKER_FLAGS_DEBUG} -fno-omit-frame-pointer")
project(justify CXX)
set(CMAKE_CXX_STANDARD 20)
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
add_executable(justify
"src/columns.cpp"
"src/justify.cpp"
"src/justifyCenter.cpp"
"src/justifyCommon.cpp"
"src/justifyFill.cpp"
"src/justifyLeft.cpp"
"src/justifyRight.cpp"
)
include_directories("${CMAKE_SOURCE_DIR}/src")

13
Makefile Normal file
View File

@ -0,0 +1,13 @@
SOURCES := $(wildcard src/*.cpp)
OBJS = $(patsubst %.cpp,%.o,$(SOURCES))
CXXFLAGS += -Wall -pedantic -Werror -std=c++17 -I src/
%.o: %.cpp
$(CXX) -c $(CXXFLAGS) -o $@ $<
justify: $(OBJS)
$(CXX) $(CXXFLAGS) -o justify $(OBJS) $(LDFLAGS)
clean:
find . -name '*.o' -exec rm {} \;
rm justify

View File

@ -96,7 +96,7 @@ std::vector<std::wstring> columns(
}
// Otherwise, are we past 2/3 down?
if (distanceToMaxHeight < (maxColumnHeight / 3))
if (distanceToMaxHeight < (static_cast<int>(maxColumnHeight) / 3))
{
// If the current or next line starts a new paragraph, let's just
// start a new block here.
@ -109,7 +109,7 @@ std::vector<std::wstring> columns(
}
// Still here? ok... are we 1/4th of the way down?
if (distanceToMaxHeight < (maxColumnHeight / 4))
if (distanceToMaxHeight < (static_cast<int>(maxColumnHeight) / 4))
{
// We're almost to the end, we should probably start looking for a
// good spot to break now if we haven't found a new paragraph yet.

View File

@ -33,6 +33,7 @@
#include <fstream>
#include <iostream>
#include <memory>
#include <optional>
#include <string>
#include <vector>

View File

@ -26,76 +26,73 @@
#include <string>
#include <vector>
std::pair<std::wstring, std::wstring> splitAtWidth(
const std::wstring& input,
size_t width)
{
if (input.size() <= width) return std::make_pair(input, L"");
const size_t cutPos = input.find_last_of(
whitespace<wchar_t>(),
width
);
if ((cutPos == input.npos) || (cutPos > width))
{
throw std::runtime_error(
"Encountered a line that could be not be split "
"at given width. Try specifying a larger width."
);
}
std::wstring truncated = input.substr(0, cutPos);
std::wstring overflow = StringTrim(input.substr(cutPos)) + L" ";
return std::make_pair(truncated, overflow);
}
std::vector<std::wstring> truncateLinesToFitWidth(
std::shared_ptr<std::wistream> in,
size_t width)
{
// Re-arrange lines such that they aren't longer than width.
std::wstring line;
std::vector<std::wstring> parsedLines;
std::wstring overflow;
bool bufferDone{false};
std::vector<std::wstring> result;
// Slurp input and arrange into a vector holding paragraphs.
std::vector<std::vector<std::wstring>> paragraphs;
std::vector<std::wstring> currentParagraph;
while (true)
{
if (!bufferDone)
std::wstring line;
if (!std::getline(*in, line))
{
if (!std::getline(*in, line))
{
bufferDone = true;
}
break;
}
line = StringRightTrim(line);
if (line.empty())
{
paragraphs.emplace_back(currentParagraph);
currentParagraph.clear();
}
else
{
line.clear();
}
overflow = StringTrim(overflow);
if (overflow.empty() && bufferDone) break;
line = StringTrim(line);
line = StringRemoveDuplicateWhitespace(line);
if (line.empty() && !bufferDone)
{
parsedLines.emplace_back(L"");
if (overflow.empty()) continue;
}
if (!overflow.empty())
{
line = overflow + L' ' + line;
}
overflow.clear();
auto lastWordPos = line.find_last_of(' ', width);
if (line.size() > width)
{
if (lastWordPos != std::wstring::npos)
{
std::wstring outLine = line.substr(0, lastWordPos);
overflow = line.substr(lastWordPos, line.length());
parsedLines.emplace_back(outLine);
}
else
{
// We have a long word that we couldn't fit.
// there's really no good options here... either we
// truncate it, things still look pretty, but we lost content.
// Or we mess up all formatting behind this.
// So instead, let's just throw an error.
throw std::runtime_error(
"Encountered a word that's longer than the supplied width."
" Please provide a longer width so it fits."
);
}
}
else
{
parsedLines.emplace_back(line);
currentParagraph.emplace_back(line);
}
}
if (!overflow.empty())
// Truncate the lines in each paragraph to the correct width.
std::wstring overflow;
for (const auto& paragraph: paragraphs)
{
overflow = StringTrim(overflow);
parsedLines.emplace_back(overflow);
for (std::wstring line: paragraph)
{
line = overflow + line;
std::wstring truncatedLine;
std::tie(truncatedLine, overflow) = splitAtWidth(line, width);
result.emplace_back(truncatedLine);
}
while (true)
{
if (overflow.empty() || overflow == L" ") break;
std::wstring truncatedLine;
std::tie(truncatedLine, overflow) = splitAtWidth(overflow, width);
result.emplace_back(truncatedLine);
}
result.emplace_back(L"");
}
return parsedLines;
return result;
}

View File

@ -18,6 +18,7 @@
#pragma once
#include <algorithm>
#include <string>
#include <vector>
@ -112,16 +113,14 @@ template<typename T>
std::basic_string<T> StringRemoveDuplicateWhitespace(
const std::basic_string<T>& input)
{
std::basic_string<T> str{input};
const auto epos = std::unique(
str.begin(),
str.end(),
[](T a, T b){
return (std::isspace(a) && std::isspace(b));
std::basic_string<T> result;
std::unique_copy(input.begin(), input.end(),
std::back_insert_iterator<std::basic_string<T>>(result),
[](char a,char b){
return std::isspace(a) && std::isspace(b);
}
);
str.erase(epos, str.end());
return str;
return result;
}
template<typename T>