I never know what to write here
162 stories
·
61 followers

DIY Neovim fzy search

1 Comment

This post originally appeared on Chris DeLuca's blog

There are plenty of fuzzy search solutions for Neovim, most notably Telescope  , but sometimes you just want something fast and simple.

Enter fzy  , a fast command line program with a slick search algorithm. It is a good unix citizen, operating on newline delimited lists passed through stdin  , making it easy to integrate into all sorts of tools, including editors.

It’s own documentation shows an example integration with Vim. However, that implementation relies on the system()  function to display the fuzzy finder, which no longer works for interactive commands in Neovim  .

Yes, there is a fzy plugin for neovim  , but why not take the opportunity to learn some Neovim Lua, and write an implementation ourselves.

Along the way, we’ll learn how to load and test Lua files, invoke floating windows, handle interactive terminal inputs, create flexible functions, and add mappings.

This guide assumes some familiarity with Vim/Neovim, as well as a basic understanding of Lua. If you’re unfamiliar with Lua, I’d recommend reading Learn Lua in 15 minutes  before starting. If that sounds fun, fire up your terminal and follow along. Otherwise, skip to the end for the final script .

Setup

Neovim picks up Lua files to include in the lua folder, so we’ll create a file there called fuzzy-search.lua.

mkdir -p "${XDG_CONFIG_HOME:-$HOME/.config}/nvim/lua"
nvim "${XDG_CONFIG_HOME:-$HOME/.config}/nvim/lua/fuzzy-search.lua"

We’ll need a function for our fuzzy searching, so let’s add one with a debug value to test. We need to access this function from anywhere, so we’ll make it global by omitting the local keyword. By convention, global variables in Lua start with an uppercase letter.

FuzzySearch = function()
print('Hello, search!')
end

Neovim provides some handy methods for loading Lua files and functions. We’ll use luafile  to load our fuzzy-search.lua into Neovim’s memory, and the lua  command to then call our newly added FuzzySearch command while we’re testing.

:luafile % " Interpret the current file as lua.
:lua FuzzySearch() " Should print 'Hello, search!' in the message area.

We’ll need to re-run those two commands every time we make a change to see their effects.

Summoning the floating window

We can no longer use the system() hack to interact with terminal programs inside Neovim, but we have access to something better: floating windows! We could make it a split buffer, but since a search interface is an ephemeral UI component that is fine to overlap existing content and should be dismissed the moment a selection is made, a floating window seems ideal.

To do this, Neovim provides the nvim_open_win()  API method, which we can access from the vim.api Lua table. This method takes 3 arguments:

  1. {buffer}, for which buffer to display, by buffer ID.
  2. {enter}, boolean for whether to enter the window or not.
  3. {config}, a table of options.

For {buffer}, we ultimately want to display a new terminal buffer with the search, so we’ll need to create one here. We’ll use the nvim_create_buf  API method to create a fresh buffer, and we’ll start a terminal session inside it in a later step. nvim_create_buf returns the ID of the buffer it just created, so it can be passed to nvim_open_win() directly. It has 2 boolean arguments; the first for whether the buffer will be “listed” by commands like :ls  , and the second for if it should be treated as a “scratch” buffer, which sets some options common to throw-away work. Since this is a temporary window, we’ll want to set this to unlisted and scratch.

For {enter}, we want to start typing our search as soon as the popup window is invoked, without having to do C-w C-l or whatever, so we’ll set this to true.

So far, our function should now look like this:

FuzzySearch = function()
vim.api.nvim_open_win(
vim.api.nvim_create_buf(false, true),
true,
{}
)
end

Finally, for {config}, we’ll be setting several options here, largely to position the window. There are five required properties, relative/external, width, height, col, and row, so let’s set them first.

Every Neovim window requires either the relative or external key to be set. external is only relevant for external GUI applications, so we’ll keep it simple and only set relative. relative controls where the window is positioned relative to, aka, where it’s x/y position originates from. Our window can be relative to the editor, the current window, or the cursor position. This is a global search, so we’ll set relative to editor. This means that our new window’s 0/0 x and y position starts at the 0/0 x and y values of the entire editor.

Width and height are simple: how many rows, for height, and columns, for width, does our window occupy? Let’s keep this straight forward for now, and set width to 10 and height to 5.

col and row control where on the grid the window should appear from. This is our starting x and y values. Again, let’s keep this simple and set each to 0.

Our function should now look like this.

FuzzySearch = function()
vim.api.nvim_open_win(
vim.api.nvim_create_buf(false, true),
true,
{
relative = 'editor',
width = 10,
height = 5,
col = 0,
row = 0,
}
)
end

Now, if you run luafile on your fuzzy-search.lua file again, and then lua FuzzySearch(), our floating window should appear over the top right of your editor!

Our basic floating window

Type :bd to close it.

Great, we have a floating window, but it’s not going to be very helpful looking like a postage stamp in the upper left. Let’s adjust the size, and center the window.

Centering the window

To center the window, we’ll need to calculate the mid-point for our window’s horizontal and vertical edge based on the window size and the size of Neovim itself, with our good friend Math.

We can get the width of the editor via the columns  global option, exposed in the vim.o  options table, and the height via lines  , exposed in the same.

Let’s start with the width. Our formula is pretty simple: subtract the width of the popup from the total columns in the editor (the width), and divide that by two to get the midway point. We need to subtract the popup’s width, since it would be pushed too far to the right without compensating for the space it takes up. We’ll finish by wrapping the whole expression in the Lua built-in math.min, since col expects whole numbers.

math.min((vim.o.columns - 10) / 2)

We’ll do something almost identical for row (aka height), but instead of using vim.o.columns, we’ll use vim.o.lines.

math.min((vim.o.lines - 5) / 2 - 1)

Notice that we’re also adding an extra subtraction by one. This is because vim.o.lines returns the total lines in the current window, including the status line and the message area. That’s an extra two lines to account for. Since we want to center the popup vertically, to find how much to compensate by, we divide the extra lines by two, giving us one to subtract.

Our function should now look like this.

FuzzySearch = function()
vim.api.nvim_open_win(
vim.api.nvim_create_buf(false, true),
true,
{
relative = 'editor',
width = 10,
height = 5,
col = math.min((vim.o.columns - 10) / 2),
row = math.min((vim.o.lines - 5) / 2 - 1),
}
)
end

Looking over this code, there’s some repetition causing maintenance overhead: we’re writing literals for the width and height twice. We’ll need to change these values soon, so let’s refactor to use local variables for these values. Add a variable for width and height at the top of the FuzzySearch function, since we’ll want them to be available throughout the scope. Our code should now look like this:

FuzzySearch = function()
local width = 10
local height = 5
vim.api.nvim_open_win(
vim.api.nvim_create_buf(false, true),
true,
{
relative = 'editor',
width = width,
height = height,
col = math.min((vim.o.columns - width) / 2),
row = math.min((vim.o.lines - height) / 2 - 1),
}
)
end

If you test this code, you’ll get something like this.

Basic centered floating window

Not much to look at, but at least it’s centered. But why is it only one line high, instead of five? Well, it actually is five lines high, but we can’t tell because our window has no outline style or contents. Let’s fix the former, then move on to the latter.

Styling the window

Floating window styles are controlled by two properties, style and border. As of this writing, style only has one valid value: "minimal". Fortunately, this option disables lots of inappropriate UI configurations for our search window, such as number and spell (see the docs for the full list).

border has several built in options, as well as an option to define your own border characters (this is what Telescope does). Feel free to play around with the options, but for the purpose of this guide we’ll be using "shadow". I like this style because it’s visually uncluttered, and makes clear that this window is “above” others.

While it’s not styling, let’s take a moment here to set the noautocmd option to true. This disables buffer events for the window, since we won’t be using them and it’s a good practice to limit the scope of our programs as much as sensible. Feel free to set this to false later if you do end up using these methods.

Our function should now look like this.

FuzzySearch = function()
local width = 10
local height = 5
vim.api.nvim_open_win(
vim.api.nvim_create_buf(false, true),
true,
{
relative = 'editor',
style = 'minimal',
border = 'shadow',
noautocmd = true,
width = width,
height = height,
col = math.min((vim.o.columns - width) / 2),
row = math.min((vim.o.lines - height) / 2 - 1),
}
)
end

Test this code and you should get something like this.

Styled floating window

Looking good. Or, at least like a stylish postage stamp. Alright, let’s move on to the contents of the window.

Launching a fzy terminal

There are several ways Neovim offers for creating a new terminal instance, but we’ll be using the termopen()  function, since it offers the most API control.

We can ask it to provide a “standard” interactive terminal session, or to launch running a specific command. We’ll call it after our floating window setup code, using a basic command to gather files for fzy to search, taken from their documentation, that should work on most systems.

vim.fn.termopen('find . -type f | fzy')

The find command will grab every regular file in your current directory tree, and pass it to fzy. Testing this code will produce a result similar to this.

Cramped results from fzy

Hooray! You should be able to search for a file, move up and down in the list via C-n and C-p, and select a file with Enter. However, you may be noticing some slight issues.

  1. The window is too small to see the results properly.
  2. Depending on your settings, you might not be in terminal mode  automatically when you enter the window, causing you to have to type i before you can search.
  3. Selecting a file produces a [Process exited 0] message, making you press Enter again before continuing.
  4. Selecting a result does not open it!

Solving the second issue is dead simple: we call startinsert  before running termopen() via nvim_command  .

vim.api.nvim_command('startinsert')

We’ll address each of the other issues, but let’s tackle the window size first, so we can better see what we’re doing.

Dynamic width and height

Alright, back to window sizing. We can improve the display by taking full advantage of the amount of space we have available to us. Since we already re-factored our width and height to single variables, we simply modify them where they are declared.

Wouldn’t it be nice to stretch the width of the popup window to however large the Neovim instance is? Easy. We change the width variable to equal vim.o.columns, minus four. The number four is arbitrary; it gives two columns of space between the edge of the Neovim instance and the popup window, which feels right to me. Feel free to experiment with your own values.

local width = vim.o.columns - 4

For setting the height, we want to show all the results that fzy shows, or, in other words, we want our popup window to be as tall as the fzy output. fzy defaults to displaying ten search results at a time. This number can be controlled via the --lines option, but changing that will be left as an exorcise for the reader. For now, we’ll redefine height to be equal to 11, which is the default 10 results fzy displays, plus an extra line for the search prompt.

local height = 11

We now have an adaptive display window that shows our searches more clearly.

Dynamic window width

But what happens on very large screens? Our window will stretch all the way across, packing the results at the left, and wasting space on the right. We can spend a moment fixing this by setting a max width for the window. The window will still center, so the eye won’t have to travel all the way to the edge to see results. The standard max line length for Vim is a sensible 80 columns, so we’ll stick to that for our window.

Since we’re subtracting four from the total width, and we want to trigger the max after we would naturally reach 80 columns, we’ll set the width at 85 columns.

After our local variable declarations, we’ll add our conditional.

if (vim.o.columns >= 85) then
width = 80
end

Now the entirety of our function should look like this.

FuzzySearch = function()
local width = vim.o.columns - 4
local height = 11
if (vim.o.columns >= 85) then
width = 80
end
vim.api.nvim_open_win(
vim.api.nvim_create_buf(false, true),
true,
{
relative = 'editor',
style = 'minimal',
border = 'shadow',
noautocmd = true,
width = width,
height = height,
col = math.min((vim.o.columns - width) / 2),
row = math.min((vim.o.lines - height) / 2 - 1),
}
)
vim.fn.termopen('find . -type f | fzy')
end

Let’s move on to solving the third and fourth problems mentioned above—not actually being able to open the file searched for!

Opening the searched for file

We want to perform an action—edit a file—when the terminal process for fzy exits, which happens after the file is selected. We know from the fzy man page  that on exit the currently selected item is printed to stdout, which is how we can detect which file is selected.

The termopen() function takes a table of event-driven callbacks as it’s second argument. We’ll be using the appropriately named on_exit.

vim.fn.termopen('find . -type f', {on_exit = function()
-- code goes here.
end})

Let’s get rid of the extra Enter press. Inside the on_exit callback, we’ll call bdelete  , meaning that once the terminal process exits, we’ll automatically delete the buffer. We’ll add the ! option, which will delete the buffer even if there are changes to it. This buffer should never have meaningful changes, so we never want that safety (otherwise, if there were changes, bdelete would produce an error).

vim.api.nvim_command('bdelete!')

If you test the function, the popup window should immediately dismiss after a file is selected. Excellent!

Now we can move on to opening the file searched for. We know that fzy prints the path to the selected file to {stdout}. Maybe there’s an argument that Neovim passes {stdout} to the terminal event callbacks? However, the on_exit  callback only receives the job id  , the exit code, and the event type, which in this case is always “exit”.

There must be a better way to solve this, but how I’ve figured it out is to write the contents of {stdout} to a file as part of the fzy pipeline, then read the file contents back in the on_exit function. If you know of a better method, hit me up on Twitter  .

Since the file we’re creating is totally throw-away, you could say temporary, we’ll use Neovim’s tempname()  function to generate a unique temporary file name in a clean path.

local file = vim.fn.tempname()

Then we can save the output fzy (which is {stdout}) to our file with simple Unix redirection  and Lua concatenation  .

'find . -type f | fzy > ' .. file

Back inside our on_exit callback function, and after our bdelete call, is where we can access the file we wrote. Lua provides a robust filesystem API  which we can use to open a stream to the file and read the contents into a variable. We’ll open the file stream as read only, keeping the principle of only asking for what we need.

local f = io.open(file, 'r')
local stdout = f:read('*all')

We should also clean up after ourselves, removing the temporary file from disk and closing the file stream.

f:close()
os.remove(file)

Now we have the file path stored in the stdout variable; we can use the nvim_command Neovim API method to :edit it!

vim.api.nvim_command('edit ' .. stdout)

Our whole function should now look like this.

FuzzySearch = function()
local width = vim.o.columns - 4
local height = 11
if (vim.o.columns >= 85) then
width = 80
end
vim.api.nvim_open_win(
vim.api.nvim_create_buf(false, true),
true,
{
relative = 'editor',
style = 'minimal',
border = 'shadow',
noautocmd = true,
width = width,
height = height,
col = math.min((vim.o.columns - width) / 2),
row = math.min((vim.o.lines - height) / 2 - 1),
}
)
local file = vim.fn.tempname()
vim.fn.termopen('find . -type f | fzy > ' .. file, {on_exit = function()
vim.api.nvim_command('bdelete!')
local f = io.open(file, 'r')
local stdout = f:read('*all')
f:close()
os.remove(file)
vim.api.nvim_command('edit ' .. stdout)
end})
end

Test the function; selecting a file should open it. Yay! We have a fully working solution.

Implementing the search command

Wouldn’t it be nice to be able to access our function outside of our fuzzy-search.lua file? Say, in our init.vim or init.lua file?

Lua includes a simple yet powerful module system  , which we can leverage with only a few changes to our file.

All we need to do is return our function, and that will expose it to require statements. However, to make it possible to add further exportable functions to this file in the future, and to adhere to convention, we’ll add our function to a table.

local M = {}
M.FuzzySearch = function()
-- all our code.
end
return M

We name the returned variable M, again, to follow convention.

This adds fuzzy-search as a module to the Neovim environment. In a Lua file within the Neovim context, we could add our function to the environment with:

local fs = require'fuzzy-search'
fs.FuzzySearch()

Notice there’s no .lua extension or leading lua directory name in the require—Neovim/Lua handles this for us so we don’t have to type all that.

Now, in our init.vim or init.lua file, we can create a mapping to this function by requiring our search file inline, and parsing it with the built-in lua  command.

Say we wanted to map <leader>f, we would add, for init.vim:

nnoremap <leader>f <cmd>lua require'fuzzy-search'.FuzzySearch()<CR>

Or for init.lua:

vim.api.nvim_set_keymap('n', '<leader>f', '<cmd>lua require"fuzzy-search".FuzzySearch()<CR>')

The final script

We did it. Here’s our completed code.

-- ~/.config/nvim/lua/fuzzy-search.lua
local M = {}
M.FuzzySearch = function()
local width = vim.o.columns - 4
local height = 11
if (vim.o.columns >= 85) then
width = 80
end
vim.api.nvim_open_win(
vim.api.nvim_create_buf(false, true),
true,
{
relative = 'editor',
style = 'minimal',
border = 'shadow',
noautocmd = true,
width = width,
height = height,
col = math.min((vim.o.columns - width) / 2),
row = math.min((vim.o.lines - height) / 2 - 1),
}
)
local file = vim.fn.tempname()
vim.fn.termopen('find . -type f | fzy > ' .. file, {on_exit = function()
vim.api.nvim_command('bdelete!')
local f = io.open(file, 'r')
local stdout = f:read('*all')
f:close()
os.remove(file)
vim.api.nvim_command('edit ' .. stdout)
end})
end
return M

Download the search code.

Improvement ideas

This script is just a starting point. Here’s some ideas for improvements.

  • Allow mappings to specify how they want to open the file (split/vsplit/tab/etc).
  • Allow mappings to change the file gathering command, e.g. fd  or my personal favoriate, git ls-files  .
  • Allow mappings to change the number of results returned.
  • Get rid of that file write!

I implemented some of these in my own dotfiles  .

Wrap up

That’s it! Thanks for reading.

Read the whole story
bronzehedwick
6 days ago
reply
This ended up being much longer than anticipated, but I'm proud of the content.
Jersey City, NJ
Share this story
Delete

A secret tape made after Columbine shows the NRA's evolution on school shootings

1 Comment and 2 Shares
Charlton Heston (left), then president of the NRA, meets with fellow leaders Wayne LaPierre (far right) and Jim Baker (center) on April 30, 1999, ahead of the NRA

Just after the 1999 shooting at Columbine High School, NRA leaders agonized over what to do. NPR obtained recordings of the calls, which lay out how the NRA has handled mass shootings ever since.

(Image credit: Kevin Moloney/Getty Images)

Read the whole story
bronzehedwick
73 days ago
reply
Glad this reporting is coming out.
Jersey City, NJ
zippy72
71 days ago
reply
FourSquare, qv
Share this story
Delete

“Hacker X”—the American who built a pro-Trump fake news empire—unmasks himself

1 Comment
A shadowy figure holds a mask of Donald Trump.

Enlarge (credit: Aurich Lawson | Getty Images)

This is the story of the mastermind behind one of the largest "fake news" operations in the US.

For two years, he ran websites and Facebook groups that spread bogus stories, conspiracy theories, and propaganda. Under him was a dedicated team of writers and editors paid to produce deceptive content—from outright hoaxes to political propaganda—with the supreme goal of tipping the 2016 election to Donald Trump.

Through extensive efforts, he built a secret network of self-reinforcing sites from the ground up. He devised a strategy that got prominent personalities—including Trump—to retweet misleading claims to their followers. And he fooled unwary American citizens, including the hacker's own father, into regarding fake news sources more highly than the mainstream media.

Read 72 remaining paragraphs | Comments

Read the whole story
bronzehedwick
99 days ago
reply
😳 dear god.
Jersey City, NJ
Share this story
Delete

Stick Figures :: Archeology

1 Comment

Tampa, Florida’s Stick Figures revered the Delta 5, opened for the Fall and caught the attention of John Peel in their short first run, churning out a clatter and rattle, jittering post-punk more in line with London or Manchester scenes than their native South Florida. The band made only one recording in its heyday, a four-song self-titled EP. That EP plus six additional unreleased studio tracks, two live cuts and a modern day reworking of their most chaotic song “Ellis Otivator Dub” make up the new Archeology compilation.

The post Stick Figures :: Archeology appeared first on Aquarium Drunkard.

Read the whole story
bronzehedwick
127 days ago
reply
I never heard of this band, but I'm digging them. Very angular, propulsive post-punk.
Jersey City, NJ
Share this story
Delete

Manasseh Meets The Equaliser :: Dub The Millennium

1 Comment

Dub The Millennium. First released in 1993, Manasseh's swirling medley of dub, reggae, electronic, ambient and UK indie. The original vinyl edition of the lp is home to ten tracks, the CD twelve. This matters as the eleventh track, "Souljah", is a high watermark of the album-long exercise in disparate fusion.

The post Manasseh Meets The Equaliser :: Dub The Millennium appeared first on Aquarium Drunkard.





Download audio: https://aquariumdrunkard.info/upload/11%20-%20Souljah.mp3
Read the whole story
bronzehedwick
127 days ago
reply
Very cool chill-out music.
Jersey City, NJ
Share this story
Delete

Long-Secret FBI Report Reveals New Connections Between 9/11 Hijackers and Saudi Religious Officials in U.S.

1 Comment
]

ProPublica is a nonprofit newsroom that investigates abuses of power. Sign up to receive our biggest stories as soon as they’re published.

A long-suppressed FBI report on Saudi Arabia’s connections to the 9/11 plot has revealed that Saudi religious officials stationed in the United States had more significant connections to two of the hijackers than has been previously known.

The 2016 report was released late Saturday night under an executive order from President Joe Biden, who promised to make it public no later than the 20th anniversary of the Sept. 11 attacks that killed 2,977 people and injured more than 6,000 others. The 16-page document was a final inventory of circumstantial evidence and leads from the FBI’s investigation of Saudi ties to the plot; it was heavily redacted.

Never miss the most important reporting from ProPublica’s newsroom. Subscribe to the Big Story newsletter.

Nonetheless, lawyers for families of the 9/11 victims, who are suing the Saudi kingdom in federal court, said the document provided important support to their theory that a handful of Saudis connected to their government worked in concert to assist the first two Qaida hijackers sent to the United States in January 2000.

“This validates what we have been saying,” said James Kreindler, one of the attorneys for the plaintiffs. “The FBI agents working this case detailed a Saudi government support network that was working in 1999, 2000 and 2001 to provide the hijackers with everything they needed to mount the attacks — apartments, money, English lessons, flight school.”

The Saudi government has always denied any role in the attacks, noting that al-Qaida and its former leader, Osama bin Laden, were sworn enemies of the royal family. But the 2016 report shows that FBI agents found evidence that several Saudi religious officials working in the United States had connections not only to people who assisted the hijackers but also to other Qaida operatives and suspected extremists. At the time, there were many Saudis in the country who had diplomatic credentials but were mainly involved in religious activity. The FBI later investigated many of them for extremism.

The FBI agents investigating possible Saudi involvement in the 9/11 attacks were part of a largely secret second phase of the bureau’s examination of the plot, called Operation Encore. The story of that inquiry, and the obstacles it faced, was first revealed last year by ProPublica and The New York Times Magazine.

The report released on Saturday was written by a senior analyst on the Encore team, John Nicholson, after the leader of the FBI’s Joint Terrorism Task Force in New York, Carlos Fernandez, decided with federal prosecutors to reassign Nicholson and the rest of his New York team, effectively shutting down their work.

Although the FBI stopped investigating the case, officials said, it kept the Encore file nominally open until earlier this year. The Justice Department repeatedly cited the continuing inquiry as a primary reason why it could not disclose Encore files to families of the 9/11 victims. But relatives of the victims say the U.S. government has maintained a shield of secrecy to protect the Saudi kingdom from embarrassing revelations.

“There is no reason this shouldn’t be brought to light,” said Christopher Ganci, a battalion chief in the New York Fire Department, whose father, Peter, was the highest-ranking fire official to die in the attacks. “The American people deserve to know this information. The ground troops, the FBI agents on the street, have been chomping at the bit to have this come out. It’s been so frustrating for them and for us.”

Among the pieces of new evidence cited in the 2016 report are telephone records showing that a Saudi graduate student who helped the two first hijackers to settle in San Diego was in contact with a Saudi religious official stationed in the United States, who in turn had connections to other Qaida operatives and later became a target of a new investigation.

The Saudi student, Omar al-Bayoumi, was a middle-aged man who rarely attended classes and was being paid surreptitiously by the Saudi Defense Ministry, where he had previously worked. Starting in 1998, the FBI had investigated him for suspected extremist activity, but that inquiry was inconclusive.

An FBI official who was a case agent for the bureau’s initial investigation of the attacks, Jacqueline Maguire, testified to the bipartisan 9/11 Commission in 2004 that “by all indications” Bayoumi’s first meeting with the hijackers “was a random encounter.” Maguire and other FBI officials have described Bayoumi as an unwitting accomplice.

But the Encore team came to believe that Bayoumi not only gave extensive help to the two Qaida operatives, Nawaf al-Hazmi and Khalid al-Mihdhar, but later lied about his dealings with them and others.

Although Mihdhar and Hazmi were seasoned Qaida operatives, they spoke virtually no English, could not read street signs and were unable to navigate around the United States without considerable help, people who knew them told investigators. The Encore team believed that a support network of Saudi officials and other extremists in Southern California mobilized before their arrival in Los Angeles on Jan. 15, 2000.

Witness testimony in the 2016 report provides the strongest evidence yet that on Feb. 1, 2000, Bayoumi went directly from a meeting at the Saudi Consulate in Los Angeles to a nearby cafe, where he waited for Hazmi and Mihdhar, approached them when they arrived and then spent about half an hour speaking with them.

Another witness, who appears to be a former Yemeni student in Los Angeles, told the FBI that a friend of his was tasked with helping the hijackers by a Saudi imam assigned to the Saudi Consulate, Fahad al-Thumairy. The FBI report quotes the witness as saying his friend, an Eritrean worshipper at Thumairy’s mosque named Mohammed Johar, was instructed to take the two hijackers to the cafe where they met Bayoumi.

In interviews through his lawyer with ProPublica and in his statements to the FBI, Johar denied having been asked by Thumairy to assist the hijackers as well as allegations that he provided lodging for them at Thumairy’s direction. According to the 2016 report, he said that a few days after the lunch meeting, he took Hazmi and Mihdhar to a Greyhound station to catch a bus to San Diego. They were met there by Bayoumi, who found them an apartment in his building, loaned them money to rent it, helped them arrange English classes and flying lessons, and introduced them to a circle of other Muslims, including the future Qaida cleric Anwar al-Awlaki.

FBI officials had previously described Bayoumi as having been in close telephone contact with Thumairy, the Saudi imam and consular official in Los Angeles. The 2016 report reveals that Thumairy was also in telephone contact with the family home in Saudi Arabia of two Qaida militants, Suleyman and Abd al Aziz Al-Khalidi, who were later captured in Afghanistan and sent to the U.S. detention camp at Guantanamo Bay, Cuba. The detainees’ older brother, Issa, was killed by Saudi forces during the 2004 kidnapping of an American worker in Saudi Arabia, Paul Johnson, who was beheaded by his captors.

According to the 2016 report, Thumairy also had telephone contacts with some alleged Muslim extremists in Los Angeles who were suspected of helping Ahmed Ressam, an Algerian who was captured by U.S. border agents as he tried to cross from Canada on his way to bomb Los Angeles International Airport in late 1999. It is not clear if the FBI determined the extent of those suspected connections.

The FBI investigated Thumairy after the attacks, and the State Department withdrew his diplomatic visa on the suspicion that he led a radical Islamist faction at the King Fahad Mosque in the Los Angeles suburb of Culver City. He was deported to Saudi Arabia when he tried to return to Los Angeles in 2003; he has denied knowing the hijackers or supporting militant causes. Investigators for the 9/11 Commission concluded that he was not a credible witness.

That 2016 report also cites an intriguing but briefly described report from a source that Thumairy received a telephone call from an unidentified person in Malaysia shortly before Hazmi and Mihdhar flew into Los Angeles International Airport on Jan. 15, 2000.

It has long been known that the CIA had the hijackers under surveillance in Malaysia as they met there with other Qaida operatives early that January, days before leaving for the United States. The CIA then lost the hijackers’ trail and neglected for more than 16 months to alert the FBI, even after learning that at least one of them had entered the United States.

The 2016 report also reveals a new layer to Bayoumi’s efforts, noting telephone records that show he was in touch with another Saudi religious official, Mutaeb al-Sudairy, who was then assigned to the Saudi Embassy in Washington. Significantly, “Bayoumi called Sudairy five times” during the crucial period when the hijackers met Bayoumi in Los Angeles and he helped them move to San Diego, the report says.

Sudairy, the son of a prominent Saudi family, traveled extensively in the United States as a Muslim missionary for the Saudi Ministry of Islamic Affairs, according to documents and interviews. During this period, the Encore report states that he also spent four months as the roommate of Ziyad Khaleel, a Palestinian-American extremist who was living in Missouri. The FBI investigated Khaleel for terrorism-related activities, including the procurement of a satellite phone for bin Laden, according to court documents and interviews. (Khaleel has since died.)

After the Sept. 11 attacks, an American who knew Sudairy in Missouri reported him to the FBI as a possible extremist. But the Saudi religious official had left the country, and the result of the report is not known.

In 2010, Sudairy caught the FBI’s attention again. While examining old phone activity of Bayoumi, an analyst on the Encore team discovered links to Sudairy. Soon afterward, the analyst learned that Sudairy and another official in the religious ministry had recently applied for new U.S. visas to study English at the University of Oklahoma. This was strange because the two Saudis were educated, wealthy officials who had lived and worked in the United States years earlier. Because of their suspected extremist links, agents believed that the plan to study in Oklahoma might be a cover for something more nefarious.

In contrast to other leads developed by the Encore team, FBI leaders took the matter seriously. They authorized an operation to put the two Saudis under full-time surveillance after they landed in the United States, former officials have told ProPublica.

But the episode ended when CIA officers in Riyadh, the Saudi capital, objected strongly to the FBI plan, one former official said. For reasons that remain unclear, the two Saudis canceled the visit at the last minute. Former investigators felt they lost an important opportunity to learn more about the suspected role of Saudi officials in the support network of the Sept. 11 hijackers. The new information about Sudairy raises even more questions about why U.S. authorities were not able to pursue the lead more aggressively in 2010.

Read the whole story
bronzehedwick
130 days ago
reply
Maaaaaaan
Jersey City, NJ
Share this story
Delete
Next Page of Stories