Skip to content

Commit

Permalink
made the clean function os agnostic and breaked it into smaller fn's,…
Browse files Browse the repository at this point in the history
… added action for different os's
  • Loading branch information
avifenesh committed Jun 29, 2024
1 parent 78a5749 commit e459342
Show file tree
Hide file tree
Showing 5 changed files with 146 additions and 87 deletions.
16 changes: 13 additions & 3 deletions .github/workflows/Install-dependencies/action.yml
Original file line number Diff line number Diff line change
@@ -1,11 +1,21 @@
name: Install Zig
name: Install Dependencies

inputs:
which-dependencies:
description: "Which dependencies to install"
required: true
default: "codespell"

runs:
using: "composite"
steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: Install Zig
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
if: ${{ inputs.which-dependencies == 'codespell'}}
with:
python-version: "3.9"
- run: pip install codespell
shell: bash
run: sudo snap install --beta zig --classic
14 changes: 8 additions & 6 deletions .github/workflows/test-spelling.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,18 @@ on:

jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
runs-on: ${{ matrix.os }}
steps:
- name: Checkout code
uses: actions/checkout@v4

- name: install dependencies
run: |
sudo apt-get update
sudo apt-get install python3-pip
pip3 install codespell
- name: Install Dependencies
uses: ./.github/workflows/Install-dependencies
with:
which-dependencies: codespell

- name: Run codespell
working-directory: ./
Expand Down
41 changes: 29 additions & 12 deletions .github/workflows/test-zig-files.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,28 +10,45 @@ on:
- ".github/workflows/test-zig-files.yml"

jobs:
test:
Simple-tests:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Install Dependencies
uses: ./.github/workflows/Install-dependencies

- name: Run tests on ZIG file change
working-directory: ziging
shell: bash
run: |
- uses: actions/checkout@v2
- uses: goto-bus-stop/setup-zig@v2
- run: |
zig test beginner_basics.zig
zig test testing_stuff.zig
zig test intermediate_basics.zig
zig test advanced_basics.zig
echo 'Avi Fenesh' | zig test standard_library.zig
- name: Run tests on Project0
working-directory: Project0-word
working-directory: ziging
shell: bash
run: |
HW-test:
strategy:
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
runs-on: ${{ matrix.os }}
steps:
- name: Checkout code
uses: actions/checkout@v4

- uses: actions/checkout@v2
- uses: goto-bus-stop/setup-zig@v2
- run: |
echo 'testing P0-tests.zig'
zig test P0-tests.zig
echo 'testing utils.zig'
zig test utils.zig
working-directory: Project0-word
shell: bash
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: goto-bus-stop/setup-zig@v2
- run: zig fmt --check .
4 changes: 2 additions & 2 deletions Project0-word/main.zig
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ pub fn main() !void {
const exit_message = printErrMessageAndExit(err);
std.process.exit(exit_message);
};
count_words.countWords(path);
_ = count_words.countWords(path);
} else {
const stdin = std.io.getStdIn();
defer stdin.close();
Expand Down Expand Up @@ -56,7 +56,7 @@ pub fn main() !void {
const exit_message = printErrMessageAndExit(err);
std.process.exit(exit_message);
};
count_words.countWords(path);
_ = count_words.countWords(path);
}
}

Expand Down
158 changes: 94 additions & 64 deletions Project0-word/utils.zig
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,23 @@ const std = @import("std");
const Reader = std.fs.File.Reader;
const print = std.debug.print;
const os_tag = @import("builtin").os.tag;
const eql = std.mem.eql;
const File = std.fs.File;
const CreateFlags = File.CreateFlags;
const isAlphabetic = std.ascii.isAlphabetic;
const isWhitespace = std.ascii.isWhitespace;
const expect = @import("std").testing.expect;
const test_allocator = std.testing.allocator;
const unicode = std.unicode;
const cwd = std.fs.cwd;
const mem = std.mem;
const eql = mem.eql;
const GPA = std.heap.GeneralPurposeAllocator;
const Allocator = std.mem.Allocator;

pub fn nextLine(reader: Reader, buffer: []u8) !?[]const u8 {
const line = reader.readUntilDelimiterOrEof(buffer, '\n') catch |err| {
print("Err: {}\n", .{err});
return err;
};
pub fn nextLine(reader: anytype, buffer: []u8) !?[]const u8 {
const line = (try reader.readUntilDelimiterOrEof(buffer, '\n')) orelse return null;
if (os_tag == .windows) {
return std.mem.trimRight(u8, line, '\r');
return mem.trimRight(u8, line, "\r");
} else {
return line;
}
Expand All @@ -29,114 +31,142 @@ pub fn parseArgs(args: [][]const u8) error{ InvalidCommand, ErrorWritingToStdout
return args[1];
} else if (eql(u8, args[0], "--help")) {
stdout.writeAll("Optional args are:\nFor counting words in a file: -cw <file> \nFor help: --help \n") catch |err| {
std.debug.print("Error writing to stdout: {any}\n", .{err});
print("Error writing to stdout: {any}\n", .{err});
return error.ErrorWritingToStdout;
};
return error.Retry;
} else {
std.debug.print("Unknown command: {any}\n", .{args[0]});
print("Unknown command: {any}\n", .{args[0]});
return error.InvalidCommand;
}
}

// TODO: Add different path encoding for different OS
// TODO: Break this function into smaller functions
pub fn cleanFile(path: []u8, buffer: []u8) ![]u8 {
var general_purpose_allocator = std.heap.GeneralPurposeAllocator(.{}){};
var general_purpose_allocator = GPA(.{}){};
const gpa = general_purpose_allocator.allocator();
var slices = [_][]const u8{ path, ".cleaned" };
var file_read: File = try std.fs.cwd().openFile(path, .{});
var encoded_path_buffer = gpa.alloc(u8, path.len) catch unreachable;
const encoded_file_sub_path = try encodePathForOs(path, encoded_path_buffer);
defer gpa.free(encoded_path_buffer);
var file_read: File = try cwd().openFile(encoded_file_sub_path, .{});
defer file_read.close();
const file_reader = file_read.reader();
const new_file_sub_path = std.mem.concat(gpa, u8, &slices) catch unreachable;
var new_file: File = try std.fs.cwd().createFile(new_file_sub_path, CreateFlags{ .truncate = true });

const new_file_sub_path = mem.concat(gpa, u8, &.{ path, ".cleaned" }) catch unreachable;
gpa.free(encoded_path_buffer);
encoded_path_buffer = gpa.alloc(u8, new_file_sub_path.len) catch unreachable;
const encoded_new_file_sub_path = try encodePathForOs(new_file_sub_path, encoded_path_buffer);
var new_file: File = try cwd().createFile(encoded_new_file_sub_path, CreateFlags{ .truncate = true });
defer new_file.close();
const writer = new_file.writer();

while (try file_reader.readUntilDelimiterOrEof(buffer, '\n')) |line| {
if (line.len == 0) {
continue;
}
if (eql(u8, line, " ")) {
continue;
}
if (eql(u8, line, "\n")) {
if (continueToNextLine(line)) {
continue;
}
if (eql(u8, line, "\r")) {
continue;
}
if (eql(u8, line, "\t")) {
continue;
}
if (line[0] == '#') {
continue;
}
if (line.len > 0) {
var word: [1024]u8 = undefined;
var i: usize = 0;
var c: usize = 0;
while (i < line.len) {
const char = line[i];
if (isAlphabetic(char)) {
word[c] = char;
c += 1;
} else if (isWhitespace(char)) {
if (c > 0) {
const string = std.ascii.lowerString(word[0..c], word[0..c]);
writer.writeAll(string) catch |err| {
return err;
};
writer.writeAll("\n") catch |err| {
return err;
};
c = 0;
}
var word: [1024]u8 = undefined;
var i: usize = 0;
var c: usize = 0;
while (i < line.len) {
const char = line[i];
if (isAlphabetic(char)) {
word[c] = char;
c += 1;
} else if (isWhitespace(char)) {
if (c > 0) {
const string = std.ascii.lowerString(word[0..c], word[0..c]);
writer.writeAll(string) catch |err| {
return err;
};
writer.writeAll("\n") catch |err| {
return err;
};
c = 0;
}
i += 1;
}
i += 1;
}
}

return new_file_sub_path;
}

fn encodePathForOs(path: []u8, encoded_path_buffer: []u8) ![]u8 {
if (os_tag == .windows) {
var i: usize = 0;
while (i < path.len) : (i += 1) {
const codepoint = try unicode.utf8Decode(path[i..]);
_ = try unicode.wtf8Encode(codepoint, encoded_path_buffer[i..]);
}
return encoded_path_buffer;
} else {
return path;
}
}

fn continueToNextLine(line: []u8) bool {
if (line.len == 0) {
return true;
}
if (eql(u8, line, " ")) {
return true;
}
if (eql(u8, line, "\n")) {
return true;
}
if (eql(u8, line, "\r")) {
return true;
}
if (eql(u8, line, "\t")) {
return true;
}
if (line[0] == '#') {
return true;
}
if (line.len == 0) {
return true;
}
return false;
}

test "clean file" {
var file_path = "test_file.txt".*;
var file: File = try std.fs.cwd().createFile(&file_path, CreateFlags{ .truncate = true, .read = true });
defer file.close();
var writer = file.writer();
writer.writeAll("Hello, this is a test file\n") catch |err| {
std.debug.print("Error writing to file: {any}\n", .{err});
print("Error writing to file: {any}\n", .{err});
return err;
};
writer.writeAll("This is a test file\n") catch |err| {
std.debug.print("Error writing to file: {any}\n", .{err});
print("Error writing to file: {any}\n", .{err});
return err;
};
writer.writeAll("This is a test file\n") catch |err| {
std.debug.print("Error writing to file: {any}\n", .{err});
print("Error writing to file: {any}\n", .{err});
return err;
};
writer.writeAll("This is a test file\n") catch |err| {
std.debug.print("Error writing to file: {any}\n", .{err});
print("Error writing to file: {any}\n", .{err});
return err;
};
var buffer: [1024]u8 = undefined;
const cleaned_file: []const u8 = try cleanFile(&file_path, &buffer);
const cleaned_file_read = try std.fs.cwd().openFile(cleaned_file, .{});
const cleaned_file: []const u8 = cleanFile(&file_path, &buffer) catch |err| {
print("Error cleaning file: {any}\n", .{err});
return err;
};
const cleaned_file_read = try cwd().openFile(cleaned_file, .{});
defer cleaned_file_read.close();
const cleaned_file_reader = cleaned_file_read.reader();
var cleaned_buffer: [1024]u8 = undefined;

const expected: [6][:0]u8 = .{ @constCast("hello"), @constCast("this"), @constCast("is"), @constCast("a"), @constCast("test"), @constCast("file") };
std.debug.print("expected: {s}\n", .{expected[0..expected.len]});
print("expected: {s}\n", .{expected[0..expected.len]});
var foundExpected = false;
while (try nextLine(cleaned_file_reader, &cleaned_buffer)) |line| {
std.debug.print("line: {s}\n", .{line});
print("line: {s}\n", .{line});
inner: for (&expected) |expectedValue| {
std.debug.print("{s}\n", .{expectedValue});
print("{s}\n", .{expectedValue});
if (eql(u8, line, expectedValue)) {
std.debug.print("found expected: {s}\n", .{expectedValue});
print("found expected: {s}\n", .{expectedValue});
foundExpected = true;
break :inner;
}
Expand Down

0 comments on commit e459342

Please sign in to comment.