/* * This file is part of Psy Shell. * * (c) 2012-2023 Justin Hileman * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Psy; use Psy\ExecutionLoop\ProcessForker; use Psy\VersionUpdater\GitHubChecker; use Psy\VersionUpdater\Installer; use Psy\VersionUpdater\SelfUpdate; use Symfony\Component\Console\Input\ArgvInput; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputDefinition; use Symfony\Component\Console\Input\InputOption; if (!\function_exists('Psy\\sh')) { /** * Command to return the eval-able code to startup PsySH. * * eval(\Psy\sh()); */ function sh(): string { if (\version_compare(\PHP_VERSION, '8.0', '<')) { return '\extract(\Psy\debug(\get_defined_vars(), isset($this) ? $this : @\get_called_class()));'; } return <<<'EOS' if (isset($this)) { \extract(\Psy\debug(\get_defined_vars(), $this)); } else { try { static::class; \extract(\Psy\debug(\get_defined_vars(), static::class)); } catch (\Error $e) { \extract(\Psy\debug(\get_defined_vars())); } } EOS; } } if (!\function_exists('Psy\\debug')) { /** * Invoke a Psy Shell from the current context. * * For example: * * foreach ($items as $item) { * \Psy\debug(get_defined_vars()); * } * * If you would like your shell interaction to affect the state of the * current context, you can extract() the values returned from this call: * * foreach ($items as $item) { * extract(\Psy\debug(get_defined_vars())); * var_dump($item); // will be whatever you set $item to in Psy Shell * } * * Optionally, supply an object as the `$bindTo` parameter. This determines * the value `$this` will have in the shell, and sets up class scope so that * private and protected members are accessible: * * class Foo { * function bar() { * \Psy\debug(get_defined_vars(), $this); * } * } * * For the static equivalent, pass a class name as the `$bindTo` parameter. * This makes `self` work in the shell, and sets up static scope so that * private and protected static members are accessible: * * class Foo { * static function bar() { * \Psy\debug(get_defined_vars(), get_called_class()); * } * } * * @param array $vars Scope variables from the calling context (default: []) * @param object|string $bindTo Bound object ($this) or class (self) value for the shell * * @return array Scope variables from the debugger session */ function debug(array $vars = [], $bindTo = null): array { echo \PHP_EOL; $sh = new Shell(); $sh->setScopeVariables($vars); // Show a couple of lines of call context for the debug session. // // @todo come up with a better way of doing this which doesn't involve injecting input :-P if ($sh->has('whereami')) { $sh->addInput('whereami -n2', true); } if (\is_string($bindTo)) { $sh->setBoundClass($bindTo); } elseif ($bindTo !== null) { $sh->setBoundObject($bindTo); } $sh->run(); return $sh->getScopeVariables(false); } } if (!\function_exists('Psy\\info')) { /** * Get a bunch of debugging info about the current PsySH environment and * configuration. * * If a Configuration param is passed, that configuration is stored and * used for the current shell session, and no debugging info is returned. * * @param Configuration|null $config * * @return array|null */ function info(Configuration $config = null) { static $lastConfig; if ($config !== null) { $lastConfig = $config; return; } $prettyPath = function ($path) { return $path; }; $homeDir = (new ConfigPaths())->homeDir(); if ($homeDir && $homeDir = \rtrim($homeDir, '/')) { $homePattern = '#^'.\preg_quote($homeDir, '#').'/#'; $prettyPath = function ($path) use ($homePattern) { if (\is_string($path)) { return \preg_replace($homePattern, '~/', $path); } else { return $path; } }; } $config = $lastConfig ?: new Configuration(); $configEnv = (isset($_SERVER['PSYSH_CONFIG']) && $_SERVER['PSYSH_CONFIG']) ? $_SERVER['PSYSH_CONFIG'] : false; if ($configEnv === false && \PHP_SAPI === 'cli-server') { $configEnv = \getenv('PSYSH_CONFIG'); } $shellInfo = [ 'PsySH version' => Shell::VERSION, ]; $core = [ 'PHP version' => \PHP_VERSION, 'OS' => \PHP_OS, 'default includes' => $config->getDefaultIncludes(), 'require semicolons' => $config->requireSemicolons(), 'strict types' => $config->strictTypes(), 'error logging level' => $config->errorLoggingLevel(), 'config file' => [ 'default config file' => $prettyPath($config->getConfigFile()), 'local config file' => $prettyPath($config->getLocalConfigFile()), 'PSYSH_CONFIG env' => $prettyPath($configEnv), ], // 'config dir' => $config->getConfigDir(), // 'data dir' => $config->getDataDir(), // 'runtime dir' => $config->getRuntimeDir(), ]; // Use an explicit, fresh update check here, rather than relying on whatever is in $config. $checker = new GitHubChecker(); $updateAvailable = null; $latest = null; try { $updateAvailable = !$checker->isLatest(); $latest = $checker->getLatest(); } catch (\Throwable $e) { } $updates = [ 'update available' => $updateAvailable, 'latest release version' => $latest, 'update check interval' => $config->getUpdateCheck(), 'update cache file' => $prettyPath($config->getUpdateCheckCacheFile()), ]; $input = [ 'interactive mode' => $config->interactiveMode(), 'input interactive' => $config->getInputInteractive(), 'yolo' => $config->yolo(), ]; if ($config->hasReadline()) { $info = \readline_info(); $readline = [ 'readline available' => true, 'readline enabled' => $config->useReadline(), 'readline service' => \get_class($config->getReadline()), ]; if (isset($info['library_version'])) { $readline['readline library'] = $info['library_version']; } if (isset($info['readline_name']) && $info['readline_name'] !== '') { $readline['readline name'] = $info['readline_name']; } } else { $readline = [ 'readline available' => false, ]; } $output = [ 'color mode' => $config->colorMode(), 'output decorated' => $config->getOutputDecorated(), 'output verbosity' => $config->verbosity(), 'output pager' => $config->getPager(), ]; $theme = $config->theme(); // TODO: show styles (but only if they're different than default?) $output['theme'] = [ 'compact' => $theme->compact(), 'prompt' => $theme->prompt(), 'bufferPrompt' => $theme->bufferPrompt(), 'replayPrompt' => $theme->replayPrompt(), 'returnValue' => $theme->returnValue(), ]; $pcntl = [ 'pcntl available' => ProcessForker::isPcntlSupported(), 'posix available' => ProcessForker::isPosixSupported(), ]; if ($disabledPcntl = ProcessForker::disabledPcntlFunctions()) { $pcntl['disabled pcntl functions'] = $disabledPcntl; } if ($disabledPosix = ProcessForker::disabledPosixFunctions()) { $pcntl['disabled posix functions'] = $disabledPosix; } $pcntl['use pcntl'] = $config->usePcntl(); $history = [ 'history file' => $prettyPath($config->getHistoryFile()), 'history size' => $config->getHistorySize(), 'erase duplicates' => $config->getEraseDuplicates(), ]; $docs = [ 'manual db file' => $prettyPath($config->getManualDbFile()), 'sqlite available' => true, ]; try { if ($db = $config->getManualDb()) { if ($q = $db->query('SELECT * FROM meta;')) { $q->setFetchMode(\PDO::FETCH_KEY_PAIR); $meta = $q->fetchAll(); foreach ($meta as $key => $val) { switch ($key) { case 'built_at': $d = new \DateTime('@'.$val); $val = $d->format(\DateTime::RFC2822); break; } $key = 'db '.\str_replace('_', ' ', $key); $docs[$key] = $val; } } else { $docs['db schema'] = '0.1.0'; } } } catch (Exception\RuntimeException $e) { if ($e->getMessage() === 'SQLite PDO driver not found') { $docs['sqlite available'] = false; } else { throw $e; } } $autocomplete = [ 'tab completion enabled' => $config->useTabCompletion(), 'bracketed paste' => $config->useBracketedPaste(), ]; // Shenanigans, but totally justified. try { if ($shell = Sudo::fetchProperty($config, 'shell')) { $shellClass = \get_class($shell); if ($shellClass !== 'Psy\\Shell') { $shellInfo = [ 'PsySH version' => $shell::VERSION, 'Shell class' => $shellClass, ]; } try { $core['loop listeners'] = \array_map('get_class', Sudo::fetchProperty($shell, 'loopListeners')); } catch (\ReflectionException $e) { // shrug } $core['commands'] = \array_map('get_class', $shell->all()); try { $autocomplete['custom matchers'] = \array_map('get_class', Sudo::fetchProperty($shell, 'matchers')); } catch (\ReflectionException $e) { // shrug } } } catch (\ReflectionException $e) { // shrug } // @todo Show Presenter / custom casters. return \array_merge($shellInfo, $core, \compact('updates', 'pcntl', 'input', 'readline', 'output', 'history', 'docs', 'autocomplete')); } } if (!\function_exists('Psy\\bin')) { /** * `psysh` command line executable. * * @return \Closure */ function bin(): \Closure { return function () { if (!isset($_SERVER['PSYSH_IGNORE_ENV']) || !$_SERVER['PSYSH_IGNORE_ENV']) { if (\defined('HHVM_VERSION_ID')) { \fwrite(\STDERR, 'PsySH v0.11 and higher does not support HHVM. Install an older version, or set the environment variable PSYSH_IGNORE_ENV=1 to override this restriction and proceed anyway.'.\PHP_EOL); exit(1); } if (\PHP_VERSION_ID < 70000) { \fwrite(\STDERR, 'PHP 7.0.0 or higher is required. You can set the environment variable PSYSH_IGNORE_ENV=1 to override this restriction and proceed anyway.'.\PHP_EOL); exit(1); } if (\PHP_VERSION_ID > 89999) { \fwrite(\STDERR, 'PHP 9 or higher is not supported. You can set the environment variable PSYSH_IGNORE_ENV=1 to override this restriction and proceed anyway.'.\PHP_EOL); exit(1); } if (!\function_exists('json_encode')) { \fwrite(\STDERR, 'The JSON extension is required. Please install it. You can set the environment variable PSYSH_IGNORE_ENV=1 to override this restriction and proceed anyway.'.\PHP_EOL); exit(1); } if (!\function_exists('token_get_all')) { \fwrite(\STDERR, 'The Tokenizer extension is required. Please install it. You can set the environment variable PSYSH_IGNORE_ENV=1 to override this restriction and proceed anyway.'.\PHP_EOL); exit(1); } } $usageException = null; $shellIsPhar = Shell::isPhar(); $input = new ArgvInput(); try { $input->bind(new InputDefinition(\array_merge(Configuration::getInputOptions(), [ new InputOption('help', 'h', InputOption::VALUE_NONE), new InputOption('version', 'V', InputOption::VALUE_NONE), new InputOption('self-update', 'u', InputOption::VALUE_NONE), new InputArgument('include', InputArgument::IS_ARRAY), ]))); } catch (\RuntimeException $e) { $usageException = $e; } try { $config = Configuration::fromInput($input); } catch (\InvalidArgumentException $e) { $usageException = $e; } // Handle --help if (!isset($config) || $usageException !== null || $input->getOption('help')) { if ($usageException !== null) { echo $usageException->getMessage().\PHP_EOL.\PHP_EOL; } $version = Shell::getVersionHeader(false); $argv = isset($_SERVER['argv']) ? $_SERVER['argv'] : []; $name = $argv ? \basename(\reset($argv)) : 'psysh'; echo <<getOption('version')) { echo Shell::getVersionHeader($config->useUnicode()).\PHP_EOL; exit(0); } // Handle --self-update if ($input->getOption('self-update')) { if (!$shellIsPhar) { \fwrite(\STDERR, 'The --self-update option can only be used with with a phar based install.'.\PHP_EOL); exit(1); } $selfUpdate = new SelfUpdate(new GitHubChecker(), new Installer()); $result = $selfUpdate->run($input, $config->getOutput()); exit($result); } $shell = new Shell($config); // Pass additional arguments to Shell as 'includes' $shell->setIncludes($input->getArgument('include')); try { // And go! $shell->run(); } catch (\Throwable $e) { \fwrite(\STDERR, $e->getMessage().\PHP_EOL); // @todo this triggers the "exited unexpectedly" logic in the // ForkingLoop, so we can't exit(1) after starting the shell... // fix this :) // exit(1); } }; } } Sam Langford: a Canadian Boxing Footnote (1883 -1956) - DarkOct02

Sam Langford: a Canadian Boxing Footnote (1883 -1956)

Sam Langford, 1913

In the Canadian sporting canon there is much to be proud of. Famous Olympians like burgeoning star Kaetlyn Osmond and former first overall pick in the NHL Nathan MacKinnon are well known to us in Atlantic Canada and our friends across the country. When an athlete rises up, we generally take notice and revel in prideful joy in their achievements. There is one man, however, that very few people in this country – or anywhere in the world for that matter – know very much about. His story is built more on rumour and legend than actual fact, because when he was active there was a concerted effort to diminish him. Those efforts resulted in one of Canada’s greatest athletes being effectively erased from the sporting folklore he should dominate.

The year is 1922, right in the middle of what some call boxing’s Golden Age. Tiger Flowers, a man who would soon be Middleweight Champion of the World returns to his corner after the first round of a fight with a little-known man based out of Boston. It is a scorching hot night in Atlanta’s Ponce de Leon Ballpark, and Flowers is feeling good. Rumours swirl that the man he is fighting, called the Boston Bonecrusher by some, is blind in his left eye and Flowers has hit him with a punch that seems to have gravely wounded the good eye. His trainers try to keep him centred, warning him not to get too excited.

Across the ring in the other corner, there is panic. The man who lives in Boston, he is now blind. His left eye was rendered nearly useless in 1917 in a fight with Fred Fulton, one of the premier knockout artists of his era. Now the right eye was badly injured, though calling a halt to the bout was surely out of the question. Quitting would surely mean he would have to give up a portion of the fight purse, and he simply could not afford it.

The man, while he lives in Boston, is not from Boston. He was born on March 4, 1886, in the village of Weymouth, Nova Scotia. His grandfather, a former slave somewhere in the United States – it is unclear where – helped settle Weymouth years earlier. Juanita Peters, who still lives in Weymouth, wrote a play about his cousin, John H. Jarvis, who would become a successful inventor. Sam Langford, widely regarded as one of the greatest boxers to ever live, though narrowly known, was a footnote in the play.

Sam Langford, 1912.

Langford left for Boston when he was young. I write to Blair Cromwell, who is as close to an expert on the life of Sam Langford as anyone is. He tells me that Sam left home young, and never got along with his father. His first fights were with his old man, and Sam rarely came out on the winning end. He found work at a hotel, The Goodwin, before he left Weymouth for good and settled in Boston. He had walked there, catching a boat to the mainland and foot toddling as the great Pierce Egan would have said, to his destiny.

Once in Boston, Sam started working as a janitor in a local boxing gym. It was not long before he was in the ring himself, becoming a decorated featherweight (126 pounds) amateur fighter at just 15 years of age. By 16, Langford was set to turn professional, and did so against unheralded but reportedly tough Jack McVicker with a fifth-round knockout win in 1902.

Twenty years later, Langford was in his corner and he was blind. Tiger Flowers, one of the great practitioners of the era, was across from him and Langford appeared to be in trouble. The call came from the referee Johnny Glenn, seconds out! The “seconds” are what trainers are called in boxing, and they are theoretically responsible for the well-being of their boxers. Ten seconds later, the bell rang and round two began. You may be wondering how a blind man would plan on continuing a fist fight, especially against someone who was specifically trained to box. Langford seemed to be uniquely prepared for such a challenge.

Most boxers, especially today, are not great a fighting on the inside. That is, very close to their opponent. Langford was by all accounts the greatest inside fighter of his time, comparable to the great Roberto Duran later in the century, and had through years of experience, learned what to do on the outside even without his sight. When he was younger, Langford would use his exceptionally long arms to box from the outside and committed the motions to his memory. Despite standing a meager five feet seven inches, his wingspan was 73 inches, nearly six feet and one inch, making him unnaturally good at moving in and out against bigger men. 

Now, in there with Flowers, Langford would call upon his experience. He jabbed gracefully and carefully with his left hand, his feet firmly rooted in the earth and ready to carry him wherever he needed to be. When Flowers tried to go at the wounded eye with his own left, Langford slipped inside and applied his mythic punching power, converting Flowers into a horizontal. The fight was stopped in the second round, Langford – the blind man – a winner by knockout. Generally speaking, fighters did not get up after Langford hit them.

The chief reason most people know nothing of Langford is that he never once fought for a world title and the chief reason for this was that Langford was black. Author of The Sundowners: The History of the Black Prizefighter 1870-1930, Kevin Smith has called Langford one of the five greatest fighters to have ever lived. Nat Fleischer, founder of Ring Magazine, counted Langford among the ten greatest heavyweights of all time, an achievement all the more impressive when we consider that Langford started his career at lightweight (135 pounds). Jack Dempsey, one of the most celebrated fighters in boxing history, called Langford the greatest fighter he had ever seen. The praise goes on and on, but Langford never benefitted from it.

Time and time again, the kid from Weymouth would be denied his opportunity to be Champion. It started when Langford defeated Joe Gans – lightweight champion and much admired by Langford – in a non-title bout. He would later fight for Joe Walcott’s welterweight title, though the fight was declared a draw. Most believe Langford handily outpointed Walcott, and crooked judges had robbed him of the victory. He would never be given a rematch. 

At heavyweight, where Langford spent his most effective years, he was in line to fight the first black heavyweight champion Jack Johnson. Johnson, ironically, invoked the colour bar for much of his reign and refused to give Langford – and many other talented black fighters – his rightfully deserved shot at the crown. The consensus is that Johnson, who had nearly lost to Langford years earlier when Langford was not yet a fully-fledged heavyweight – he weighed 155 pounds whereas Johnson weighed about 190, was afraid that Langford would easily beat him. 

That is probably true. Langford was fluent in a secret language in boxing that former boxing manager and current Deadspin writer Charles Farrell calls The Black Code. Spending years, typically their entire careers, being denied championship fights and often getting jobbed in other fighters’ hometowns, boxers like Langford developed boxing vocabularies that no one speaks today. The least celebrated of these fighters were some of the best to ever live, but Langford transcended it entirely. For nearly twenty years, Langford was deeply feared and widely avoided by anyone who did not want their career derailed by a man who could separate them from consciousness with his ferocious punching power or embarrass them with his advanced boxing skill. As Mike Silver, author and boxing historian, says, there was nothing Langford did not do well: “He was just about a complete fighter. He was very short, but he had unusually long arms. Also, he was way ahead of his time as a boxer. He could fight on the inside, he could fight on the outside. If he had to fight on the inside, he knew how to get inside. He was a long-distance, middle-distance and short-distance fighter. He could do it all. He was also a devastating puncher, which was amazing because he carried his punch in every weight division he moved to.”

Unfortunately, Langford would never reap the benefits of his otherworldly talent. It is the secret fate, the dirty secret, and universal truth of boxing that fighters will be born poor and will die poor regardless of what happens in the middle. For Langford, this was all too true. By 1944, when one Al Laney of the New York Herald came to write a story on the great former boxer, Langford was already less than a footnote. Less than twenty years after his career had ended, he was poor and blind and alone, living in a one room apartment in Harlem. After Laney published his article, a collection was taken up to pay Langford’s medical bills. He had nothing left to pay them himself.

Langford’s story is one of brief triumph and protracted defeat. He was several times the ‘Coloured’ Heavyweight Champion, and he fought all across North America for regional and national titles that no one cared about even then. He was during his career a ghost story used to scare other fighters. You want to screw around during training? We’ll make you with Langford. The man from Weymouth died in a private nursing home in 1956, a year after he was finally recognized by the boxing community and enshrined in the Hall of Fame, as well as having been inducted into the Canadian Sports Hall of Fame. He died penniless and largely unknown.

But from 1902 to 1926, Sam Langford was a force. He earned a reputation for fearlessly accepting any fight, no matter how big the opponent. In an era where fighters now contract weights down to a single pound, Langford’s willingness to go from fighting at 135 pounds to fighting men of 200 pounds is nearly unthinkable. Commissions would not even sanction such fights today, but Langford took them and won them. A small man with a tremendous punch – partly due to his stout composition and partly owing to his unique understanding of how to punch – may not have been a Champion in his day, but he deserves to be celebrated among Canada’s most prolific and talented athletes.