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:
parent
0d397c20ed
commit
ec8f985f39
|
@ -3,3 +3,4 @@
|
|||
*.*~
|
||||
*.sw*
|
||||
build/*
|
||||
/justify
|
||||
|
|
|
@ -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")
|
||||
|
|
@ -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
|
|
@ -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.
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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>
|
||||
|
|
Loading…
Reference in New Issue