Skip to content

Commit

Permalink
Merge remote-tracking branch 'refs/remotes/source/main'
Browse files Browse the repository at this point in the history
  • Loading branch information
ccjmne committed Dec 16, 2024
2 parents ecc9d7f + e30df9d commit 25f9be5
Show file tree
Hide file tree
Showing 18 changed files with 475 additions and 383 deletions.
39 changes: 39 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
name: Run Tests

on:
push:
branches: [ "*" ]
pull_request:
branches: [ main ]

jobs:
test:

runs-on: ubuntu-latest

steps:
- name: Checkout Code
uses: actions/checkout@v3

- name: Install Make Dependencies
run: |
sudo apt-get update
sudo apt-get install libtool-bin autoconf automake cmake g++ pkg-config unzip gettext curl -y
- name: Install Neovim
run: |
sudo snap install nvim --classic
- name: Install Plenary
run: |
git clone https://github.com/nvim-lua/plenary.nvim.git
mkdir -p .local/share/nvim/lazy/
mv plenary.nvim .local/share/nvim/lazy/
- name: Tests
env:
XDG_CONFIG_HOME: ${{ github.workspace }}/.config
XDG_DATA_HOME: ${{ github.workspace }}/.local/share
XDG_STATE_HOME: ${{ github.workspace }}/.local/state
XDG_CACHE_HOME: ${{ github.workspace }}/.cache
run: make test
6 changes: 2 additions & 4 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@ TESTS_DIR=tests

.PHONY: test

# TODO I want test to contain a lua-language-server pass

test_nvim:
@nvim \
--headless \
Expand All @@ -13,7 +11,7 @@ test_nvim:
-c "PlenaryBustedDirectory ${TESTS_DIR} { minimal_init = '${TESTS_INIT}' }"

test:
-$(MAKE) test_nvim || exit 1
$(MAKE) test_nvim

test-watch:
nodemon -e lua -x "$(MAKE) test"
nodemon -e lua -x "$(MAKE) test || exit 1"
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
![build status](https://github.com/aaronik/treewalker.nvim/actions/workflows/test.yml/badge.svg)
<span style="height: 20px;">
<img alt="Static Badge" src="https://img.shields.io/badge/100%25_lua-purple" style="height: 20px;">
</span>
Expand Down Expand Up @@ -30,7 +31,8 @@ Moving slowly, showing each command
{
"aaronik/treewalker.nvim",
opts = {
highlight = true -- default is false; can also be a duration
highlight = true -- Whether to briefly highlight the node after jumping to it
-- Can be numeric to specify highlight duration instead
}
}
```
Expand Down
5 changes: 4 additions & 1 deletion lua/treewalker/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,11 @@ local Treewalker = {}

---@alias Opts { highlight: boolean | integer }

-- Default setup() options
---@type Opts
Treewalker.opts = {}
Treewalker.opts = {
highlight = true
}

---@param opts Opts | nil
function Treewalker.setup(opts)
Expand Down
116 changes: 74 additions & 42 deletions lua/treewalker/nodes.lua
Original file line number Diff line number Diff line change
@@ -1,36 +1,47 @@
local util = require "treewalker.util"
local lines= require "treewalker.lines"
local lines = require "treewalker.lines"

local NON_TARGET_NODE_MATCHERS = {
-- "chunk", -- lua
"^.*comment.*$",
-- These are regexes but just happen to be real simple so far
local TARGET_BLACKLIST_TYPE_MATCHERS = {
"comment",
}

local TARGET_DESCENDANT_TYPES = {
"body_statement", -- lua, rb
"block", -- lua
"statement_block", -- lua

-- "then", -- helps rb, hurts lua
"do_block", -- rb
local HIGHLIGHT_BLACKLIST_TYPE_MATCHERS = {
"module", -- python
"chunk", -- lua
"body", -- ruby
"block", -- ruby
"program", -- ruby
"haskell", -- guess which language starts their module tree with this node
"translation_unit", -- c module
"source_file", -- rust
}


local M = {}

---@param node TSNode
---@param matchers string[]
---@return boolean
function M.is_jump_target(node)
for _, matcher in ipairs(NON_TARGET_NODE_MATCHERS) do
-- If it's a banned type
local function is_matched_in(node, matchers)
for _, matcher in ipairs(matchers) do
if node:type():match(matcher) then
return false
return true
end
end
return true
return false
end

---@param node TSNode
---@return boolean
function M.is_jump_target(node)
return not is_matched_in(node, TARGET_BLACKLIST_TYPE_MATCHERS)
end

function M.is_descendant_jump_target(node)
return util.contains(TARGET_DESCENDANT_TYPES, node:type())
---@param node TSNode
---@return boolean
function M.is_highlight_target(node)
return not is_matched_in(node, HIGHLIGHT_BLACKLIST_TYPE_MATCHERS)
end

---Do the nodes have the same starting point
Expand All @@ -45,6 +56,14 @@ function M.have_same_start(node1, node2)
scol1 == scol2
end

---Do the nodes have the same starting row
---@param node1 TSNode
---@param node2 TSNode
---@return boolean
function M.have_same_row(node1, node2)
return M.get_row(node1) == M.get_row(node2)
end

---Do the nodes have the same level of indentation
---@param node1 TSNode
---@param node2 TSNode
Expand Down Expand Up @@ -83,41 +102,54 @@ end
---@param node TSNode
---@return TSNode[]
function M.get_descendants(node)
local descendants = {}

-- Helper function to recursively collect descendants
local function collect_descendants(current_node)
local child_count = current_node:child_count()
for i = 0, child_count - 1 do
local child = current_node:child(i)
table.insert(descendants, child)
-- Recursively collect descendants of the child
collect_descendants(child)
end
local descendants = {}

-- Helper function to recursively collect descendants
local function collect_descendants(current_node)
local child_count = current_node:child_count()
for i = 0, child_count - 1 do
local child = current_node:child(i)
table.insert(descendants, child)
-- Recursively collect descendants of the child
collect_descendants(child)
end
end

-- Start the recursive collection with the given node
collect_descendants(node)
-- Start the recursive collection with the given node
collect_descendants(node)

return descendants
return descendants
end

-- Get farthest ancestor (or self) at the same starting row
---@param node TSNode
---@return TSNode
function M.get_highest_coincident(node)
local parent = node:parent()
-- prefer row over start on account of lisps / S-expressions, which start with (identifier, ..)
while parent and M.have_same_row(node, parent) do
if M.is_highlight_target(parent) then node = parent end
parent = parent:parent()
end
return node
end

--- Take a list of nodes and unique them based on line start
---@param nodes TSNode[]
---@return TSNode[]
function M.unique_per_line(nodes)
local unique_nodes = {}
local seen_lines = {}

for _, node in ipairs(nodes) do
local line = node:start() -- Assuming node:start() returns the line number of the node
if not seen_lines[line] then
table.insert(unique_nodes, node)
seen_lines[line] = true
end
local unique_nodes = {}
local seen_lines = {}

for _, node in ipairs(nodes) do
local line = node:start() -- Assuming node:start() returns the line number of the node
if not seen_lines[line] then
table.insert(unique_nodes, node)
seen_lines[line] = true
end
end

return unique_nodes
return unique_nodes
end

-- Easy conversion to table
Expand Down
8 changes: 1 addition & 7 deletions lua/treewalker/ops.lua
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,6 @@ end

local M = {}

---set cursor without throwing error
---@param row integer
---@param col integer
function M.safe_set_cursor(row, col)
pcall(vim.api.nvim_win_set_cursor, 0, { row, col }) -- catch any errors in nvim_win_set_cursor
end

---Flash a highlight over the given range
---@param range Range4
---@param duration integer
Expand Down Expand Up @@ -65,6 +58,7 @@ function M.jump(row, node)
vim.cmd('normal! ^')
local highlight = require("treewalker").opts.highlight
if highlight and highlight ~= 0 then
node = nodes.get_highest_coincident(node)
M.highlight(nodes.range(node), highlight ~= true and highlight or 250)
end
end
Expand Down
6 changes: 0 additions & 6 deletions lua/treewalker/util.lua
Original file line number Diff line number Diff line change
Expand Up @@ -98,12 +98,6 @@ M.guid = function()
end)
end

---@param env_key string
---@return boolean
M.has_env_var = function(env_key)
return type(os.getenv(env_key)) ~= type(nil)
end

---reverse an array table
---@param t table
M.reverse = function (t)
Expand Down
3 changes: 1 addition & 2 deletions plugin/init.lua
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
local util = require "treewalker.util"

local function tw()
-- local util = require "treewalker.util"
-- return util.R('treewalker')
return require('treewalker')
end
Expand Down
57 changes: 57 additions & 0 deletions tests/fixtures/c.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
#include <stdio.h>
#include <stdlib.h>

// Structure to represent an account
typedef struct {
int accountNumber;
float balance;
} Account;

// Function to create a new account
Account* createAccount(int accountNumber, float initialBalance) {
Account* newAccount = (Account*)malloc(sizeof(Account));
if (!newAccount) {
printf("Memory error\n");
return NULL;
}
newAccount->accountNumber = accountNumber;
newAccount->balance = initialBalance;
return newAccount;
}

// Function to deposit money into an account
void deposit(Account* account, float amount) {
if (amount > 0.0f) {
account->balance += amount;
printf("Deposited $%.2f into account %d\n", amount, account->accountNumber);
} else {
printf("Invalid deposit amount: $%.2f\n", amount);
}
}

// Function to withdraw money from an account
void withdraw(Account* account, float amount) {
if (amount > 0.0f && amount <= account->balance) {
account->balance -= amount;
printf("Withdrawn $%.2f from account %d\n", amount, account->accountNumber);
} else {
printf("Invalid withdrawal amount: $%.2f\n", amount);
}
}

// Function to display account information
void printAccountInfo(Account* account) {
printf("Account Number: %d\nBalance: $%.2f\n", account->accountNumber, account->balance);
}

int main() {
Account* account = createAccount(12345, 1000.00f);

deposit(account, 500.00f);
withdraw(account, 200.00f);
printAccountInfo(account);

free(account);
return 0;
}

Loading

0 comments on commit 25f9be5

Please sign in to comment.