command-t 3.0.2 → 4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +8 -2
- data/doc/command-t.txt +312 -147
- data/ruby/command-t.rb +13 -12
- data/ruby/command-t/controller.rb +86 -15
- data/ruby/command-t/depend +4 -0
- data/ruby/command-t/ext.h +9 -2
- data/ruby/command-t/extconf.rb +2 -2
- data/ruby/command-t/finder.rb +6 -2
- data/ruby/command-t/finder/buffer_finder.rb +3 -3
- data/ruby/command-t/finder/command_finder.rb +23 -0
- data/ruby/command-t/finder/file_finder.rb +3 -3
- data/ruby/command-t/finder/help_finder.rb +25 -0
- data/ruby/command-t/finder/history_finder.rb +27 -0
- data/ruby/command-t/finder/jump_finder.rb +3 -3
- data/ruby/command-t/finder/line_finder.rb +23 -0
- data/ruby/command-t/finder/mru_buffer_finder.rb +3 -3
- data/ruby/command-t/finder/tag_finder.rb +3 -3
- data/ruby/command-t/heap.c +146 -0
- data/ruby/command-t/heap.h +22 -0
- data/ruby/command-t/match.c +183 -116
- data/ruby/command-t/match.h +16 -10
- data/ruby/command-t/match_window.rb +10 -1
- data/ruby/command-t/matcher.c +203 -63
- data/ruby/command-t/metadata/fallback.rb +2 -2
- data/ruby/command-t/mru.rb +2 -2
- data/ruby/command-t/path_utilities.rb +2 -2
- data/ruby/command-t/progress_reporter.rb +38 -0
- data/ruby/command-t/prompt.rb +4 -4
- data/ruby/command-t/scanner.rb +22 -2
- data/ruby/command-t/scanner/buffer_scanner.rb +3 -3
- data/ruby/command-t/scanner/command_scanner.rb +33 -0
- data/ruby/command-t/scanner/file_scanner.rb +30 -6
- data/ruby/command-t/scanner/file_scanner/find_file_scanner.rb +12 -7
- data/ruby/command-t/scanner/file_scanner/git_file_scanner.rb +11 -8
- data/ruby/command-t/scanner/file_scanner/ruby_file_scanner.rb +7 -4
- data/ruby/command-t/scanner/file_scanner/watchman_file_scanner.rb +13 -5
- data/ruby/command-t/scanner/help_scanner.rb +40 -0
- data/ruby/command-t/scanner/history_scanner.rb +24 -0
- data/ruby/command-t/scanner/jump_scanner.rb +3 -3
- data/ruby/command-t/scanner/line_scanner.rb +45 -0
- data/ruby/command-t/scanner/mru_buffer_scanner.rb +3 -3
- data/ruby/command-t/scanner/tag_scanner.rb +3 -3
- data/ruby/command-t/scm_utilities.rb +2 -2
- data/ruby/command-t/settings.rb +2 -2
- data/ruby/command-t/stub.rb +7 -2
- data/ruby/command-t/util.rb +2 -2
- data/ruby/command-t/vim.rb +27 -2
- data/ruby/command-t/vim/screen.rb +3 -3
- data/ruby/command-t/vim/window.rb +3 -3
- data/ruby/command-t/watchman.c +1 -1
- metadata +13 -2
data/ruby/command-t.rb
CHANGED
@@ -8,16 +8,17 @@ module CommandT
|
|
8
8
|
require 'command-t/metadata/fallback'
|
9
9
|
end
|
10
10
|
|
11
|
-
autoload :Controller,
|
12
|
-
autoload :Finder,
|
13
|
-
autoload :MRU,
|
14
|
-
autoload :MatchWindow,
|
11
|
+
autoload :Controller, 'command-t/controller'
|
12
|
+
autoload :Finder, 'command-t/finder'
|
13
|
+
autoload :MRU, 'command-t/mru'
|
14
|
+
autoload :MatchWindow, 'command-t/match_window'
|
15
15
|
autoload :PathUtilities, 'command-t/path_utilities'
|
16
|
-
autoload :
|
17
|
-
autoload :
|
18
|
-
autoload :
|
19
|
-
autoload :
|
20
|
-
autoload :
|
21
|
-
autoload :
|
22
|
-
autoload :
|
23
|
-
|
16
|
+
autoload :ProgressReporter, 'command-t/progress_reporter'
|
17
|
+
autoload :Prompt, 'command-t/prompt'
|
18
|
+
autoload :SCMUtilities, 'command-t/scm_utilities'
|
19
|
+
autoload :Scanner, 'command-t/scanner'
|
20
|
+
autoload :Settings, 'command-t/settings'
|
21
|
+
autoload :Stub, 'command-t/stub'
|
22
|
+
autoload :Util, 'command-t/util'
|
23
|
+
autoload :VIM, 'command-t/vim'
|
24
|
+
end
|
@@ -67,6 +67,27 @@ module CommandT
|
|
67
67
|
end
|
68
68
|
guard :show_buffer_finder
|
69
69
|
|
70
|
+
def show_command_finder
|
71
|
+
@path = VIM::pwd
|
72
|
+
@active_finder = command_finder
|
73
|
+
show
|
74
|
+
end
|
75
|
+
guard :show_command_finder
|
76
|
+
|
77
|
+
def show_help_finder
|
78
|
+
@path = VIM::pwd
|
79
|
+
@active_finder = help_finder
|
80
|
+
show
|
81
|
+
end
|
82
|
+
guard :show_help_finder
|
83
|
+
|
84
|
+
def show_history_finder
|
85
|
+
@path = VIM::pwd
|
86
|
+
@active_finder = history_finder
|
87
|
+
show
|
88
|
+
end
|
89
|
+
guard :show_history_finder
|
90
|
+
|
70
91
|
def show_jump_finder
|
71
92
|
@path = VIM::pwd
|
72
93
|
@active_finder = jump_finder
|
@@ -74,6 +95,13 @@ module CommandT
|
|
74
95
|
end
|
75
96
|
guard :show_jump_finder
|
76
97
|
|
98
|
+
def show_line_finder
|
99
|
+
@path = VIM::pwd
|
100
|
+
@active_finder = line_finder
|
101
|
+
show
|
102
|
+
end
|
103
|
+
guard :show_line_finder
|
104
|
+
|
77
105
|
def show_mru_finder
|
78
106
|
@path = VIM::pwd
|
79
107
|
@active_finder = mru_finder
|
@@ -81,6 +109,13 @@ module CommandT
|
|
81
109
|
end
|
82
110
|
guard :show_mru_finder
|
83
111
|
|
112
|
+
def show_search_finder
|
113
|
+
@path = VIM::pwd
|
114
|
+
@active_finder = search_finder
|
115
|
+
show
|
116
|
+
end
|
117
|
+
guard :show_search_finder
|
118
|
+
|
84
119
|
def show_tag_finder
|
85
120
|
@path = VIM::pwd
|
86
121
|
@active_finder = tag_finder
|
@@ -161,7 +196,7 @@ module CommandT
|
|
161
196
|
key = ::VIM::evaluate('a:arg').to_i.chr
|
162
197
|
if @focus == prompt
|
163
198
|
prompt.add! key
|
164
|
-
|
199
|
+
update
|
165
200
|
else
|
166
201
|
@match_window.find key
|
167
202
|
end
|
@@ -171,7 +206,7 @@ module CommandT
|
|
171
206
|
def backspace
|
172
207
|
if @focus == prompt
|
173
208
|
prompt.backspace!
|
174
|
-
|
209
|
+
update
|
175
210
|
end
|
176
211
|
end
|
177
212
|
guard :backspace
|
@@ -179,7 +214,7 @@ module CommandT
|
|
179
214
|
def delete
|
180
215
|
if @focus == prompt
|
181
216
|
prompt.delete!
|
182
|
-
|
217
|
+
update
|
183
218
|
end
|
184
219
|
end
|
185
220
|
guard :delete
|
@@ -266,6 +301,9 @@ module CommandT
|
|
266
301
|
)
|
267
302
|
@match_window.matches = @matches
|
268
303
|
|
304
|
+
# Scanner may have overwritten prompt to show progress.
|
305
|
+
prompt.redraw
|
306
|
+
|
269
307
|
@needs_update = false
|
270
308
|
end
|
271
309
|
guard :list_matches
|
@@ -284,6 +322,14 @@ module CommandT
|
|
284
322
|
|
285
323
|
private
|
286
324
|
|
325
|
+
def update
|
326
|
+
if @debounce_interval > 0
|
327
|
+
@needs_update = true
|
328
|
+
else
|
329
|
+
list_matches!
|
330
|
+
end
|
331
|
+
end
|
332
|
+
|
287
333
|
def prompt
|
288
334
|
@prompt ||= Prompt.new(
|
289
335
|
:cursor_color => VIM::get_string('g:CommandTCursorColor')
|
@@ -302,14 +348,16 @@ module CommandT
|
|
302
348
|
end
|
303
349
|
|
304
350
|
def show
|
305
|
-
@initial_window
|
306
|
-
@initial_buffer
|
307
|
-
@
|
351
|
+
@initial_window = $curwin
|
352
|
+
@initial_buffer = $curbuf
|
353
|
+
@debounce_interval = VIM::get_number('g:CommandTInputDebounce') || 0
|
354
|
+
@match_window = MatchWindow.new \
|
355
|
+
:encoding => VIM::get_string('g:CommandTEncoding'),
|
308
356
|
:highlight_color => VIM::get_string('g:CommandTHighlightColor'),
|
309
357
|
:match_window_at_top => VIM::get_bool('g:CommandTMatchWindowAtTop'),
|
310
358
|
:match_window_reverse => VIM::get_bool('g:CommandTMatchWindowReverse', true),
|
311
359
|
:min_height => min_height,
|
312
|
-
:debounce_interval =>
|
360
|
+
:debounce_interval => @debounce_interval,
|
313
361
|
:prompt => prompt,
|
314
362
|
:name => "Command-T [#{@active_finder.name}]"
|
315
363
|
@focus = prompt
|
@@ -422,8 +470,9 @@ module CommandT
|
|
422
470
|
numbers = ('0'..'9').to_a.join
|
423
471
|
lowercase = ('a'..'z').to_a.join
|
424
472
|
uppercase = lowercase.upcase
|
425
|
-
punctuation = '<>`@#~!"
|
426
|
-
|
473
|
+
punctuation = '<>`@#~!"$%^&/()=+*-_.,;:?\\|\'{}[]'
|
474
|
+
space = ' '
|
475
|
+
(numbers + lowercase + uppercase + punctuation + space).each_byte do |b|
|
427
476
|
map "<Char-#{b}>", 'HandleKey', b
|
428
477
|
end
|
429
478
|
|
@@ -463,10 +512,12 @@ module CommandT
|
|
463
512
|
end
|
464
513
|
|
465
514
|
def set_up_autocmds
|
466
|
-
|
467
|
-
|
468
|
-
|
469
|
-
|
515
|
+
if @debounce_interval > 0
|
516
|
+
::VIM::command 'augroup CommandTController'
|
517
|
+
::VIM::command 'autocmd!'
|
518
|
+
::VIM::command 'autocmd CursorHold <buffer> :call commandt#private#ListMatches()'
|
519
|
+
::VIM::command 'augroup END'
|
520
|
+
end
|
470
521
|
end
|
471
522
|
|
472
523
|
# Returns the desired maximum number of matches, based on available vertical
|
@@ -485,6 +536,10 @@ module CommandT
|
|
485
536
|
@buffer_finder ||= CommandT::Finder::BufferFinder.new
|
486
537
|
end
|
487
538
|
|
539
|
+
def command_finder
|
540
|
+
@command_finder ||= CommandT::Finder::CommandFinder.new
|
541
|
+
end
|
542
|
+
|
488
543
|
def mru_finder
|
489
544
|
@mru_finder ||= CommandT::Finder::MRUBufferFinder.new
|
490
545
|
end
|
@@ -502,13 +557,29 @@ module CommandT
|
|
502
557
|
:git_scan_submodules => VIM::get_bool('g:CommandTGitScanSubmodules')
|
503
558
|
end
|
504
559
|
|
560
|
+
def help_finder
|
561
|
+
@jump_finder ||= CommandT::Finder::HelpFinder.new
|
562
|
+
end
|
563
|
+
|
564
|
+
def history_finder
|
565
|
+
CommandT::Finder::HistoryFinder.new(:history_type => ':')
|
566
|
+
end
|
567
|
+
|
505
568
|
def jump_finder
|
506
569
|
@jump_finder ||= CommandT::Finder::JumpFinder.new
|
507
570
|
end
|
508
571
|
|
572
|
+
def line_finder
|
573
|
+
CommandT::Finder::LineFinder.new
|
574
|
+
end
|
575
|
+
|
576
|
+
def search_finder
|
577
|
+
CommandT::Finder::HistoryFinder.new(:history_type => '/')
|
578
|
+
end
|
579
|
+
|
509
580
|
def tag_finder
|
510
581
|
@tag_finder ||= CommandT::Finder::TagFinder.new \
|
511
582
|
:include_filenames => VIM::get_bool('g:CommandTTagIncludeFilenames')
|
512
583
|
end
|
513
|
-
end
|
514
|
-
end
|
584
|
+
end
|
585
|
+
end
|
data/ruby/command-t/depend
CHANGED
data/ruby/command-t/ext.h
CHANGED
@@ -13,5 +13,12 @@ extern VALUE mCommandTWatchmanUtils; // module CommandT::Watchman::Utils
|
|
13
13
|
// raised if it is not nil and not a hash.
|
14
14
|
VALUE CommandT_option_from_hash(const char *option, VALUE hash);
|
15
15
|
|
16
|
-
// Debugging
|
17
|
-
#define
|
16
|
+
// Debugging macros.
|
17
|
+
#define L(...) { \
|
18
|
+
fprintf(stdout, __VA_ARGS__); \
|
19
|
+
fflush(stdout); \
|
20
|
+
} while (0)
|
21
|
+
#define RUBY_INSPECT(obj) do { \
|
22
|
+
rb_funcall(rb_mKernel, rb_intern("p"), 1, obj); \
|
23
|
+
fflush(stdout); \
|
24
|
+
} while (0)
|
data/ruby/command-t/extconf.rb
CHANGED
data/ruby/command-t/finder.rb
CHANGED
@@ -12,8 +12,12 @@ module CommandT
|
|
12
12
|
# different kinds of search (files, buffers).
|
13
13
|
class Finder
|
14
14
|
autoload :BufferFinder, 'command-t/finder/buffer_finder'
|
15
|
+
autoload :CommandFinder, 'command-t/finder/command_finder'
|
15
16
|
autoload :FileFinder, 'command-t/finder/file_finder'
|
17
|
+
autoload :HelpFinder, 'command-t/finder/help_finder'
|
18
|
+
autoload :HistoryFinder, 'command-t/finder/history_finder'
|
16
19
|
autoload :JumpFinder, 'command-t/finder/jump_finder'
|
20
|
+
autoload :LineFinder, 'command-t/finder/line_finder'
|
17
21
|
autoload :MRUBufferFinder, 'command-t/finder/mru_buffer_finder'
|
18
22
|
autoload :TagFinder, 'command-t/finder/tag_finder'
|
19
23
|
|
@@ -42,5 +46,5 @@ module CommandT
|
|
42
46
|
def path=(path)
|
43
47
|
@scanner.path = path
|
44
48
|
end
|
45
|
-
end
|
46
|
-
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# Copyright 2011-present Greg Hurrell. All rights reserved.
|
2
|
+
# Licensed under the terms of the BSD 2-clause license.
|
3
|
+
|
4
|
+
module CommandT
|
5
|
+
class Finder
|
6
|
+
class CommandFinder < Finder
|
7
|
+
def initialize(options = {})
|
8
|
+
@scanner = Scanner::CommandScanner.new
|
9
|
+
@matcher = Matcher.new @scanner, :always_show_dot_files => true
|
10
|
+
end
|
11
|
+
|
12
|
+
def open_selection(command, selection, options = {})
|
13
|
+
::VIM::command "call feedkeys(':#{selection} ', 'nt')"
|
14
|
+
end
|
15
|
+
|
16
|
+
def flush; end
|
17
|
+
|
18
|
+
def name
|
19
|
+
'Commands'
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# Copyright 2011-present Greg Hurrell. All rights reserved.
|
2
|
+
# Licensed under the terms of the BSD 2-clause license.
|
3
|
+
|
4
|
+
module CommandT
|
5
|
+
class Finder
|
6
|
+
class HelpFinder < Finder
|
7
|
+
def initialize(options = {})
|
8
|
+
@scanner = Scanner::HelpScanner.new
|
9
|
+
@matcher = Matcher.new @scanner, :always_show_dot_files => true
|
10
|
+
end
|
11
|
+
|
12
|
+
def open_selection(command, selection, options = {})
|
13
|
+
::VIM::command "help #{selection}"
|
14
|
+
end
|
15
|
+
|
16
|
+
def flush
|
17
|
+
@scanner.flush
|
18
|
+
end
|
19
|
+
|
20
|
+
def name
|
21
|
+
'Help'
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# Copyright 2011-present Greg Hurrell. All rights reserved.
|
2
|
+
# Licensed under the terms of the BSD 2-clause license.
|
3
|
+
|
4
|
+
module CommandT
|
5
|
+
class Finder
|
6
|
+
class HistoryFinder < Finder
|
7
|
+
def initialize(options = {})
|
8
|
+
@history_type = options[:history_type] # / or :
|
9
|
+
@scanner = Scanner::HistoryScanner.new("silent history #{@history_type}")
|
10
|
+
@matcher = Matcher.new @scanner, :always_show_dot_files => true
|
11
|
+
end
|
12
|
+
|
13
|
+
def open_selection(command, selection, options = {})
|
14
|
+
# Need to unescape to reverse the work done by `#sanitize_path_string`.
|
15
|
+
unescaped = selection.gsub(/\\(.)/, '\1')
|
16
|
+
escaped = VIM.escape_for_single_quotes unescaped
|
17
|
+
::VIM::command "call feedkeys('#{@history_type}#{escaped} ', 'nt')"
|
18
|
+
end
|
19
|
+
|
20
|
+
def flush; end
|
21
|
+
|
22
|
+
def name
|
23
|
+
@history_type == ':' ? 'History' : 'Searches'
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# Copyright 2011-present Greg Hurrell. All rights reserved.
|
2
|
+
# Licensed under the terms of the BSD 2-clause license.
|
3
|
+
|
4
|
+
module CommandT
|
5
|
+
class Finder
|
6
|
+
class LineFinder < Finder
|
7
|
+
def initialize(options = {})
|
8
|
+
@scanner = Scanner::LineScanner.new
|
9
|
+
@matcher = Matcher.new @scanner, :always_show_dot_files => true
|
10
|
+
end
|
11
|
+
|
12
|
+
def open_selection(command, selection, options = {})
|
13
|
+
::VIM::command "#{selection.sub(/.+:(\d+)$/, '\1')}"
|
14
|
+
end
|
15
|
+
|
16
|
+
def flush; end
|
17
|
+
|
18
|
+
def name
|
19
|
+
'Lines'
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,146 @@
|
|
1
|
+
// Copyright 2016-present Greg Hurrell. All rights reserved.
|
2
|
+
// Licensed under the terms of the BSD 2-clause license.
|
3
|
+
|
4
|
+
#include <stdlib.h> /* for free(), malloc(), NULL */
|
5
|
+
|
6
|
+
#include "heap.h"
|
7
|
+
|
8
|
+
#define HEAP_PARENT(index) ((index - 1) / 2)
|
9
|
+
#define HEAP_LEFT(index) (2 * index + 1)
|
10
|
+
#define HEAP_RIGHT(index) (2 * index + 2)
|
11
|
+
|
12
|
+
/**
|
13
|
+
* Returns a new heap, or NULL on failure.
|
14
|
+
*/
|
15
|
+
heap_t *heap_new(long capacity, heap_compare_entries comparator) {
|
16
|
+
heap_t *heap = malloc(sizeof(heap_t));
|
17
|
+
if (!heap) {
|
18
|
+
return NULL;
|
19
|
+
}
|
20
|
+
heap->capacity = capacity;
|
21
|
+
heap->comparator = comparator;
|
22
|
+
heap->count = 0;
|
23
|
+
|
24
|
+
heap->entries = malloc(capacity * sizeof(void *));
|
25
|
+
if (!heap->entries) {
|
26
|
+
free(heap);
|
27
|
+
return NULL;
|
28
|
+
}
|
29
|
+
return heap;
|
30
|
+
}
|
31
|
+
|
32
|
+
/**
|
33
|
+
* Frees a previously created heap.
|
34
|
+
*/
|
35
|
+
void heap_free(heap_t *heap) {
|
36
|
+
free(heap->entries);
|
37
|
+
free(heap);
|
38
|
+
}
|
39
|
+
|
40
|
+
/**
|
41
|
+
* @internal
|
42
|
+
*
|
43
|
+
* Compare values at indices `a_idx` and `b_idx` using the heap's comparator
|
44
|
+
* function.
|
45
|
+
*/
|
46
|
+
int heap_compare(heap_t *heap, long a_idx, long b_idx) {
|
47
|
+
const void *a = heap->entries[a_idx];
|
48
|
+
const void *b = heap->entries[b_idx];
|
49
|
+
return heap->comparator(a, b);
|
50
|
+
}
|
51
|
+
|
52
|
+
/**
|
53
|
+
* @internal
|
54
|
+
*
|
55
|
+
* Returns 1 if the heap property holds (ie. parent < child).
|
56
|
+
*/
|
57
|
+
int heap_property(heap_t *heap, long parent_idx, long child_idx) {
|
58
|
+
return heap_compare(heap, parent_idx, child_idx) > 0;
|
59
|
+
}
|
60
|
+
|
61
|
+
/**
|
62
|
+
* @internal
|
63
|
+
*
|
64
|
+
* Swaps the values at indexes `a` and `b` within `heap`.
|
65
|
+
*/
|
66
|
+
void heap_swap(heap_t *heap, long a, long b) {
|
67
|
+
void *tmp = heap->entries[a];
|
68
|
+
heap->entries[a] = heap->entries[b];
|
69
|
+
heap->entries[b] = tmp;
|
70
|
+
}
|
71
|
+
|
72
|
+
/**
|
73
|
+
* Inserts `value` into `heap`.
|
74
|
+
*/
|
75
|
+
void heap_insert(heap_t *heap, void *value) {
|
76
|
+
long idx, parent_idx;
|
77
|
+
|
78
|
+
// If at capacity, ignore.
|
79
|
+
if (heap->count == heap->capacity) {
|
80
|
+
return;
|
81
|
+
}
|
82
|
+
|
83
|
+
// Insert into first empty slot.
|
84
|
+
idx = heap->count;
|
85
|
+
heap->entries[idx] = value;
|
86
|
+
heap->count++;
|
87
|
+
|
88
|
+
// Bubble upwards until heap property is restored.
|
89
|
+
parent_idx = HEAP_PARENT(idx);
|
90
|
+
while (idx && !heap_property(heap, parent_idx, idx)) {
|
91
|
+
heap_swap(heap, idx, parent_idx);
|
92
|
+
idx = parent_idx;
|
93
|
+
parent_idx = HEAP_PARENT(idx);
|
94
|
+
}
|
95
|
+
}
|
96
|
+
|
97
|
+
/**
|
98
|
+
* @internal
|
99
|
+
*
|
100
|
+
* Restores the heap property starting at `idx`.
|
101
|
+
*/
|
102
|
+
void heap_heapify(heap_t *heap, long idx) {
|
103
|
+
long left_idx = HEAP_LEFT(idx);
|
104
|
+
long right_idx = HEAP_RIGHT(idx);
|
105
|
+
long smallest_idx =
|
106
|
+
right_idx < heap->count ?
|
107
|
+
|
108
|
+
// Right (and therefore left) child exists.
|
109
|
+
(heap_compare(heap, left_idx, right_idx) > 0 ? left_idx : right_idx) :
|
110
|
+
|
111
|
+
left_idx < heap->count ?
|
112
|
+
|
113
|
+
// Only left child exists.
|
114
|
+
left_idx :
|
115
|
+
|
116
|
+
// No children exist.
|
117
|
+
idx;
|
118
|
+
|
119
|
+
if (
|
120
|
+
smallest_idx != idx &&
|
121
|
+
!heap_property(heap, idx, smallest_idx)
|
122
|
+
) {
|
123
|
+
// Swap with smallest_idx child.
|
124
|
+
heap_swap(heap, idx, smallest_idx);
|
125
|
+
heap_heapify(heap, smallest_idx);
|
126
|
+
}
|
127
|
+
}
|
128
|
+
|
129
|
+
/**
|
130
|
+
* Extracts the minimum value from `heap`.
|
131
|
+
*/
|
132
|
+
void *heap_extract(heap_t *heap) {
|
133
|
+
void *extracted = NULL;
|
134
|
+
if (heap->count) {
|
135
|
+
// Grab root value.
|
136
|
+
extracted = heap->entries[0];
|
137
|
+
|
138
|
+
// Move last item to root.
|
139
|
+
heap->entries[0] = heap->entries[heap->count - 1];
|
140
|
+
heap->count--;
|
141
|
+
|
142
|
+
// Restore heap property.
|
143
|
+
heap_heapify(heap, 0);
|
144
|
+
}
|
145
|
+
return extracted;
|
146
|
+
}
|