├── .gitignore
├── menus
└── hex.cson
├── package.json
├── README.md
├── styles
└── hex.less
├── lib
├── hex.coffee
└── hex-view.coffee
└── LICENSE.md
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | npm-debug.log
3 | node_modules
4 | images
5 |
--------------------------------------------------------------------------------
/menus/hex.cson:
--------------------------------------------------------------------------------
1 | 'menu': [
2 | {
3 | 'label': 'Packages'
4 | 'submenu': [
5 | 'label': 'Hex View',
6 | 'command': 'hex:view'
7 | ]
8 | }
9 | ]
10 |
11 | 'context-menu':
12 | '.image-view': [
13 | {
14 | 'label': 'Hex View',
15 | 'command': 'hex:view',
16 | }
17 | ]
18 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "hex",
3 | "main": "./lib/hex",
4 | "version": "0.6.2",
5 | "description": "Hex Viewer for Atom",
6 | "repository": "https://github.com/AbeEstrada/atom-hex",
7 | "license": "MIT",
8 | "engines": {
9 | "atom": ">0.50.0 <2.0.0"
10 | },
11 | "dependencies": {
12 | "fs-plus": "^2.0.0",
13 | "entities": "^1.0.0",
14 | "atom-space-pen-views": "^2.0.3"
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Hex Viewer for [Atom](http://atom.io)
2 |
3 | View the hex dump of any file
4 |
5 | ## Install
6 |
7 | apm install hex
8 |
9 | If you want a shortcut, you can open your `keymap.cson` file and add this:
10 |
11 | '.editor:not(.mini)':
12 | 'shift-ctrl-h': 'hex:view'
13 |
14 | ---
15 |
16 | 
17 |
--------------------------------------------------------------------------------
/styles/hex.less:
--------------------------------------------------------------------------------
1 | @import "ui-variables";
2 |
3 | atom-pane-container atom-pane .item-views {
4 | overflow: auto;
5 | .hex-view {
6 | padding-top: 0;
7 | overflow: auto;
8 | }
9 | }
10 | .hex-dump {
11 | font-family: Menlo, Monaco, Consolas, "Courier New", monospace;
12 | }
13 | .hex-dump header {
14 | padding-top: 10px;
15 | white-space: nowrap;
16 | }
17 | .hex-dump .hex {
18 | float: left;
19 | margin: 10px 0 0 0;
20 | padding: 0 20px 0 0;
21 | white-space: nowrap;
22 | overflow: hidden;
23 | }
24 | .hex-dump .ascii {
25 | margin: 10px 0 0 0;
26 | white-space: nowrap;
27 | overflow: hidden;
28 | }
29 |
--------------------------------------------------------------------------------
/lib/hex.coffee:
--------------------------------------------------------------------------------
1 | fs = require 'fs-plus'
2 | HexView = null
3 |
4 | module.exports =
5 | config:
6 | bytesPerLine:
7 | type: 'integer'
8 | default: 16
9 | minimum: 1
10 |
11 | activate: ->
12 | atom.commands.add 'atom-workspace', 'hex:view', => createView()
13 | @openerDisposable = atom.workspace.addOpener(openURI)
14 |
15 | deactivate: ->
16 | @openerDisposable.dispose()
17 |
18 | openURI = (uriToOpen) ->
19 | pathname = uriToOpen.replace 'hex://', ''
20 | return unless uriToOpen.substr(0, 4) is 'hex:'
21 |
22 | HexView ?= require './hex-view'
23 | new HexView(filePath: pathname)
24 |
25 | createView = ->
26 | paneItem = atom.workspace.getActivePaneItem()
27 | filePath = paneItem.getPath()
28 | if paneItem and fs.isFileSync(filePath)
29 | atom.workspace.open "hex://#{filePath}"
30 | else
31 | console.warn "File (#{filePath}) does not exists"
32 |
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | This software is released under the MIT license:
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining a copy of
4 | this software and associated documentation files (the "Software"), to deal in
5 | the Software without restriction, including without limitation the rights to
6 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
7 | the Software, and to permit persons to whom the Software is furnished to do so,
8 | subject to the following conditions:
9 |
10 | The above copyright notice and this permission notice shall be included in all
11 | copies or substantial portions of the Software.
12 |
13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
15 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
16 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
17 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
18 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
19 |
--------------------------------------------------------------------------------
/lib/hex-view.coffee:
--------------------------------------------------------------------------------
1 | {$, ScrollView} = require 'atom-space-pen-views'
2 | {Disposable} = require 'atom'
3 | path = require 'path'
4 | fs = require 'fs-plus'
5 | entities = null
6 |
7 | module.exports =
8 | class HexView extends ScrollView
9 | @content: ->
10 | @div class: 'hex-view padded pane-item', tabindex: -1, =>
11 | @div class: 'hex-dump', outlet: 'hexDump'
12 |
13 | initialize: ({@filePath}) =>
14 | super
15 |
16 | attached: ->
17 | entities ?= require 'entities'
18 | @hexFile(@filePath)
19 |
20 | @hexDump.css
21 | 'font-family': atom.config.get('editor.fontFamily')
22 | 'font-size': atom.config.get('editor.fontSize')
23 |
24 | hexFile: (filePath) ->
25 | stream = fs.ReadStream(filePath)
26 | stream.on 'data', (chunk) =>
27 | @hex chunk if @hexDump.is(':empty')
28 |
29 | getPath: -> @filePath
30 |
31 | getURI: -> @filePath
32 |
33 | getTitle: -> "#{path.basename(@getPath())} Hex"
34 |
35 | # NOP to remove deprecation. This kind of sucks
36 | onDidChangeTitle: ->
37 | new Disposable()
38 |
39 | onDidChangeModified: ->
40 | new Disposable()
41 |
42 | # Based on "node-hex" by Gabriel Llamas
43 | # https://github.com/gagle/node-hex
44 |
45 | hex: (buffer) =>
46 | bytesPerLine = atom.config.get('hex.bytesPerLine')
47 | rows = Math.ceil(buffer.length / bytesPerLine)
48 | last = buffer.length % bytesPerLine or bytesPerLine
49 | offsetLength = buffer.length.toString(16).length
50 | offsetLength = 6 if offsetLength < 6
51 |
52 | offset = "Offset:"
53 | hex = ""
54 | ascii = ""
55 |
56 | i = 0
57 | while i < bytesPerLine
58 | offset += " #{zero(i, 2)}"
59 | i++
60 |
61 | b = 0
62 | lastBytes = undefined
63 | v = undefined
64 | i = 0
65 |
66 | while i < rows
67 | hex += "#{zero(b, offsetLength)}:"
68 | lastBytes = (if i is rows - 1 then last else bytesPerLine)
69 |
70 | j = 0
71 | while j < lastBytes
72 | hex += " #{zero(buffer[b], 2)}"
73 | b++
74 | j++
75 |
76 | b -= lastBytes
77 |
78 | j = 0
79 | while j < lastBytes
80 | v = buffer[b]
81 | if (v > 31 and v < 127) or v > 159
82 | ascii += entities.encodeHTML(String.fromCharCode(v))
83 | else
84 | ascii += "."
85 | b++
86 | j++
87 |
88 | hex += "
"
89 | ascii += "
"
90 | i++
91 |
92 | @hexDump.append "