Skip to content

Instantly share code, notes, and snippets.

@nvlled
Last active July 16, 2025 05:07
Show Gist options
  • Save nvlled/4fb61d727a76dee53c3182a5043ee85c to your computer and use it in GitHub Desktop.
Save nvlled/4fb61d727a76dee53c3182a5043ee85c to your computer and use it in GitHub Desktop.
//! This is a tool used to change the indent size.
//!
//! ## Purpose
//! I wrote this tool because:
//! - some projects uses a non-standard indent-size (like 2-space)
//! - a lot of editors autoformat the file on save, hence converts the 2-space to 4-space)
//! - in particular, zls currently doesn't have an option to change indent size
//!
//! The solution: revert the indent size back to 2-space after I'm done editing
//! ```
//! $ indent-scale weird-file.zig 0.5
//! ```
//! Alternative 1: use notepad or other prehistoric editor
//! Alternative 2: turn off autoformat on save, but I still need autoformatting for other things
//! so nope
//!
//! ## Usage
//!
//! To build the file:
//! ```
//! zig build-exe indent-scale.zig
//! ```
//!
//! To run the file without building:
//! ```
//! zig run indent-scale.zig -- filename 2
//! ```
const std = @import("std");
const stderr = std.io.getStdErr().writer();
const debugf = std.debug.print;
pub fn usage(args: [][:0]u8) !void {
const progname = std.fs.path.basename(args[0]);
try stderr.print("usage: {s} <filename> <indent_scale>\n", .{progname});
try stderr.print("\n", .{});
try stderr.print("DESC: A tool used to change the indent size (spaces only).\n", .{});
try stderr.print(" An indent_scale of 0.5 will half the indent.\n", .{});
try stderr.print(" An indent_scale of 2.0 will double the indent.\n", .{});
try stderr.print("\n", .{});
try stderr.print("WARNING: This will modify the filename, make sure to use version control or have a backup first.\n", .{});
}
pub fn main() !void {
var gpa = std.heap.DebugAllocator(.{}){};
const allocator = gpa.allocator();
const args = try std.process.argsAlloc(allocator);
defer std.process.argsFree(allocator, args);
if (args.len < 3) {
try usage(args);
return;
}
const filename = args[1];
const file = try std.fs.cwd().openFile(filename, .{ .mode = .read_only });
defer file.close();
const indent_scale = std.fmt.parseFloat(f32, args[2]) catch {
try stderr.writeAll("invalid indent scale, must be a decimal number");
return;
};
const temp_name = try getTempFilename(allocator);
const temp_file = try std.fs.cwd().createFile(temp_name, .{});
defer temp_file.close();
defer allocator.free(temp_name);
var line_buf: [1024 * 1024]u8 = undefined;
const r = file.reader();
while (true) {
const line = try r.readUntilDelimiterOrEof(&line_buf, '\n') orelse break;
var i: usize = 0;
while (i < line.len) : (i += 1) {
if (line[i] != ' ') break;
}
const num_spaces: f32 = @floatFromInt(i);
const target_spaces: usize = @intFromFloat(std.math.ceil(num_spaces * indent_scale));
for (0..target_spaces) |_| {
try temp_file.writeAll(" ");
}
try temp_file.writeAll(line[i..]);
try temp_file.writeAll("\n");
}
try std.fs.cwd().rename(temp_name, filename);
}
fn getTempFilename(allocator: std.mem.Allocator) ![]const u8 {
var buf: std.ArrayList(u8) = .init(allocator);
var w = buf.writer();
try w.writeAll("./indent-temp-");
try w.print("{d}", .{std.time.milliTimestamp()});
return buf.toOwnedSlice();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment